int ad_set(int argc, char **argv, AFPObj *obj) { int c, firstarg; afpvol_t vol; struct stat st; int adflags = 0; struct adouble ad; while ((c = getopt(argc, argv, ":l:t:c:f:a:")) != -1) { switch(c) { case 'l': new_label = strdup(optarg); break; case 't': new_type = strdup(optarg); break; case 'c': new_creator = strdup(optarg); break; case 'f': new_flags = strdup(optarg); break; case 'a': new_attributes = strdup(optarg); break; case ':': case '?': usage_set(); return -1; break; } } if (argc <= optind) exit(1); cnid_init(); openvol(obj, argv[optind], &vol); if (vol.vol->v_path == NULL) exit(1); if (stat(argv[optind], &st) != 0) { perror("stat"); exit(1); } if (S_ISDIR(st.st_mode)) adflags = ADFLAGS_DIR; ad_init(&ad, vol.vol); if (ad_open(&ad, argv[optind], adflags | ADFLAGS_HF | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666) < 0) goto exit; if (new_label) change_label(argv[optind], &vol, &st, &ad, new_label); if (new_type) change_type(argv[optind], &vol, &st, &ad, new_type); if (new_creator) change_creator(argv[optind], &vol, &st, &ad, new_creator); if (new_flags) change_flags(argv[optind], &vol, &st, &ad, new_flags); if (new_attributes) change_attributes(argv[optind], &vol, &st, &ad, new_attributes); ad_flush(&ad); ad_close(&ad, ADFLAGS_HF); exit: closevol(&vol); return 0; }
int ad_mv(int argc, char *argv[], AFPObj *obj) { size_t baselen, len; int rval; char *p, *endp; struct stat sb; int ch; char path[MAXPATHLEN]; pdid = htonl(1); did = htonl(2); argc--; argv++; while ((ch = getopt(argc, argv, "finv")) != -1) switch (ch) { case 'i': iflg = 1; fflg = nflg = 0; break; case 'f': fflg = 1; iflg = nflg = 0; break; case 'n': nflg = 1; fflg = iflg = 0; break; case 'v': vflg = 1; break; default: usage_mv(); } argc -= optind; argv += optind; if (argc < 2) usage_mv(); set_signal(); cnid_init(); if (openvol(obj, argv[argc - 1], &dvolume) != 0) { SLOG("Error opening CNID database for source \"%s\": ", argv[argc - 1]); return 1; } /* * If the stat on the target fails or the target isn't a directory, * try the move. More than 2 arguments is an error in this case. */ if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) { if (argc > 2) usage_mv(); if (openvol(obj, argv[0], &svolume) != 0) { SLOG("Error opening CNID database for destination \"%s\": ", argv[0]); return 1; } rval = do_move(argv[0], argv[1]); closevol(&svolume); closevol(&dvolume); return 1; } /* It's a directory, move each file into it. */ if (strlen(argv[argc - 1]) > sizeof(path) - 1) ERROR("%s: destination pathname too long", *argv); (void)strcpy(path, argv[argc - 1]); baselen = strlen(path); endp = &path[baselen]; if (!baselen || *(endp - 1) != '/') { *endp++ = '/'; ++baselen; } for (rval = 0; --argc; ++argv) { /* * Find the last component of the source pathname. It * may have trailing slashes. */ p = *argv + strlen(*argv); while (p != *argv && p[-1] == '/') --p; while (p != *argv && p[-1] != '/') --p; if ((baselen + (len = strlen(p))) >= PATH_MAX) { SLOG("%s: destination pathname too long", *argv); rval = 1; } else { memmove(endp, p, (size_t)len + 1); openvol(obj, *argv, &svolume); if (do_move(*argv, path)) rval = 1; closevol(&svolume); } } closevol(&dvolume); return rval; }
int ad_cp(int argc, char *argv[]) { struct stat to_stat, tmp_stat; int r, ch, have_trailing_slash; char *target; #if 0 afpvol_t srcvol; afpvol_t dstvol; #endif ppdid = pdid = htonl(1); did = htonl(2); while ((ch = getopt(argc, argv, "afinpRvx")) != -1) switch (ch) { case 'a': pflag = 1; Rflag = 1; break; case 'f': fflag = 1; iflag = nflag = 0; break; case 'i': iflag = 1; fflag = nflag = 0; break; case 'n': nflag = 1; fflag = iflag = 0; break; case 'p': pflag = 1; break; case 'R': Rflag = 1; break; case 'v': vflag = 1; break; case 'x': ftw_options |= FTW_MOUNT; break; default: usage_cp(); break; } argc -= optind; argv += optind; if (argc < 2) usage_cp(); set_signal(); cnid_init(); /* Save the target base in "to". */ target = argv[--argc]; if ((strlcpy(to.p_path, target, PATH_MAX)) >= PATH_MAX) ERROR("%s: name too long", target); to.p_end = to.p_path + strlen(to.p_path); if (to.p_path == to.p_end) { *to.p_end++ = '.'; *to.p_end = 0; } have_trailing_slash = (to.p_end[-1] == '/'); if (have_trailing_slash) STRIP_TRAILING_SLASH(to); to.target_end = to.p_end; /* Set end of argument list */ argv[argc] = NULL; /* * Cp has two distinct cases: * * cp [-R] source target * cp [-R] source1 ... sourceN directory * * In both cases, source can be either a file or a directory. * * In (1), the target becomes a copy of the source. That is, if the * source is a file, the target will be a file, and likewise for * directories. * * In (2), the real target is not directory, but "directory/source". */ r = stat(to.p_path, &to_stat); if (r == -1 && errno != ENOENT) ERROR("%s", to.p_path); if (r == -1 || !S_ISDIR(to_stat.st_mode)) { /* * Case (1). Target is not a directory. */ if (argc > 1) ERROR("%s is not a directory", to.p_path); /* * Need to detect the case: *cp -R dir foo * Where dir is a directory and foo does not exist, where * we want pathname concatenations turned on but not for * the initial mkdir(). */ if (r == -1) { lstat(*argv, &tmp_stat); if (S_ISDIR(tmp_stat.st_mode) && Rflag) type = DIR_TO_DNE; else type = FILE_TO_FILE; } else type = FILE_TO_FILE; if (have_trailing_slash && type == FILE_TO_FILE) { if (r == -1) ERROR("directory %s does not exist", to.p_path); else ERROR("%s is not a directory", to.p_path); } } else /* * Case (2). Target is a directory. */ type = FILE_TO_DIR; /* * Keep an inverted copy of the umask, for use in correcting * permissions on created directories when not using -p. */ mask = ~umask(0777); umask(~mask); #if 0 /* Inhereting perms in ad_mkdir etc requires this */ ad_setfuid(0); #endif /* Load .volinfo file for destination*/ openvol(to.p_path, &dvolume); for (int i = 0; argv[i] != NULL; i++) { /* Load .volinfo file for source */ openvol(argv[i], &svolume); if (nftw(argv[i], copy, upfunc, 20, ftw_options) == -1) { if (alarmed) { SLOG("...break"); } else { SLOG("Error: %s: %s", argv[i], strerror(errno)); } closevol(&svolume); closevol(&dvolume); } } return rval; }