X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=bin%2Fad%2Fad_mv.c;h=7dab6c6fc35102cb7118414e0e13a352deb61b7a;hb=7da5be70fe636491c5cb45a7d1cd9d2ada48ef1e;hp=0c973d06a7ac64c603841f5705a2d32e951d01fe;hpb=8a88ad5deb609e8bb8c557bb512b9641a0cbbd9f;p=netatalk.git diff --git a/bin/ad/ad_mv.c b/bin/ad/ad_mv.c index 0c973d06..7dab6c6f 100644 --- a/bin/ad/ad_mv.c +++ b/bin/ad/ad_mv.c @@ -51,7 +51,6 @@ static int fflg, iflg, nflg, vflg; static afpvol_t svolume, dvolume; static cnid_t did, pdid; static volatile sig_atomic_t alarmed; -static char *adexecp; static char *netatalk_dirs[] = { ".AppleDouble", ".AppleDB", @@ -61,7 +60,6 @@ static char *netatalk_dirs[] = { static int copy(const char *, const char *); static int do_move(const char *, const char *); -static int fastcopy(const char *, const char *, struct stat *); static void preserve_fd_acls(int source_fd, int dest_fd, const char *source_path, const char *dest_path); /* @@ -155,7 +153,6 @@ int ad_mv(int argc, char *argv[]) pdid = htonl(1); did = htonl(2); - adexecp = argv[0]; argc--; argv++; @@ -189,7 +186,7 @@ int ad_mv(int argc, char *argv[]) set_signal(); cnid_init(); if (openvol(argv[argc - 1], &dvolume) != 0) { - SLOG("Error opening CNID database for %s: ", argv[argc - 1]); + SLOG("Error opening CNID database for source \"%s\": ", argv[argc - 1]); return 1; } @@ -201,7 +198,7 @@ int ad_mv(int argc, char *argv[]) if (argc > 2) usage_mv(); if (openvol(argv[0], &svolume) != 0) { - SLOG("Error opening CNID database for %s: ", argv[0]); + SLOG("Error opening CNID database for destination \"%s\": ", argv[0]); return 1; } rval = do_move(argv[0], argv[1]); @@ -238,11 +235,8 @@ int ad_mv(int argc, char *argv[]) rval = 1; } else { memmove(endp, p, (size_t)len + 1); - if (openvol(*argv, &svolume) != 0) { - SLOG("Error opening CNID database for %s: ", argv[0]); - rval = 1; - goto exit; - } + openvol(*argv, &svolume); + if (do_move(*argv, path)) rval = 1; closevol(&svolume); @@ -358,137 +352,46 @@ static int do_move(const char *from, const char *to) return -1; } - char *newdir = strdup(to); - cnid_t newdid; - if ((newdid = cnid_for_path(&svolume, dirname(newdir), &pdid)) == CNID_INVALID) { - SLOG("Couldn't resolve CNID for %s", to); + /* get CNID of new parent dir */ + cnid_t newpdid, newdid; + if ((newdid = cnid_for_paths_parent(&dvolume, to, &newpdid)) == CNID_INVALID) { + SLOG("Couldn't resolve CNID for parent of %s", to); + return -1; } - free(newdir); if (stat(to, &sb) != 0) { SLOG("Cant stat %s: %s", to, strerror(errno)); return 1; } - char *name = strdup(to); - if (cnid_update(dvolume.volume.v_cdb, cnid, &sb, newdid, basename(to), strlen(basename(to))) != 0) { + + char *p = strdup(to); + char *name = basename(p); + if (cnid_update(dvolume.volume.v_cdb, cnid, &sb, newdid, name, strlen(name)) != 0) { SLOG("Cant update CNID for: %s", to); return 1; } - free(name); + free(p); struct adouble ad; - ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options); - if (ad_open_metadata(to, S_ISDIR(sb.st_mode) ? ADFLAGS_DIR : 0, O_RDWR, &ad) != 0) { + ad_init_old(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options); + if (ad_open(&ad, to, S_ISDIR(sb.st_mode) ? (ADFLAGS_DIR | ADFLAGS_HF | ADFLAGS_RDWR) : ADFLAGS_HF | ADFLAGS_RDWR) != 0) { SLOG("Error opening adouble for: %s", to); return 1; } ad_setid(&ad, sb.st_dev, sb.st_ino, cnid, newdid, dvolume.db_stamp); ad_flush(&ad); - ad_close_metadata(&ad); + ad_close(&ad, ADFLAGS_HF); if (vflg) printf("%s -> %s\n", from, to); return (0); } + + if (mustcopy) + return copy(from, to); - if (mustcopy) { - /* - * If rename fails because we're trying to cross devices, and - * it's a regular file, do the copy internally; otherwise, use - * cp and rm. - */ - if (lstat(from, &sb)) { - SLOG("%s: %s", from, strerror(errno)); - return (1); - } - return (S_ISREG(sb.st_mode) ? - fastcopy(from, to, &sb) : copy(from, to)); - } - return 1; -} - -static int fastcopy(const char *from, const char *to, struct stat *sbp) -{ - struct timeval tval[2]; - static u_int blen; - static char *bp; - mode_t oldmode; - int nread, from_fd, to_fd; - - if ((from_fd = open(from, O_RDONLY, 0)) < 0) { - SLOG("%s: %s", from, strerror(errno)); - return (1); - } - if (blen < sbp->st_blksize) { - if (bp != NULL) - free(bp); - if ((bp = malloc((size_t)sbp->st_blksize)) == NULL) { - blen = 0; - SLOG("malloc failed"); - return (1); - } - blen = sbp->st_blksize; - } - while ((to_fd = open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) { - if (errno == EEXIST && unlink(to) == 0) - continue; - SLOG("%s: %s", to, strerror(errno)); - (void)close(from_fd); - return (1); - } - while ((nread = read(from_fd, bp, (size_t)blen)) > 0) - if (write(to_fd, bp, (size_t)nread) != nread) { - SLOG("%s: %s", to, strerror(errno)); - goto err; - } - if (nread < 0) { - SLOG("%s: %s", from, strerror(errno)); - err: - if (unlink(to)) - SLOG("%s: remove", to, strerror(errno)); - (void)close(from_fd); - (void)close(to_fd); - return (1); - } - - oldmode = sbp->st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID); - if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) { - SLOG("%s: set owner/group (was: %lu/%lu)", to, - (u_long)sbp->st_uid, (u_long)sbp->st_gid, strerror(errno)); - if (oldmode & S_ISUID) { - SLOG("%s: owner/group changed; clearing suid (mode was 0%03o)", - to, oldmode); - sbp->st_mode &= ~S_ISUID; - } - } - if (fchmod(to_fd, sbp->st_mode)) - SLOG("%s: set mode (was: 0%03o): %s", to, oldmode, strerror(errno)); - /* - * POSIX 1003.2c states that if _POSIX_ACL_EXTENDED is in effect - * for dest_file, then its ACLs shall reflect the ACLs of the - * source_file. - */ - preserve_fd_acls(from_fd, to_fd, from, to); - (void)close(from_fd); - - tval[0].tv_sec = sbp->st_atime; - tval[1].tv_sec = sbp->st_mtime; - tval[0].tv_usec = tval[1].tv_usec = 0; - if (utimes(to, tval)) - SLOG("%s: set times: %s", to, strerror(errno)); - - if (close(to_fd)) { - SLOG("%s: %s", to, strerror(errno)); - return (1); - } - - if (unlink(from)) { - SLOG("%s: remove: %s", from, strerror(errno)); - return (1); - } - if (vflg) - printf("%s -> %s\n", from, to); - return 0; + /* If we get here it's an error */ + return -1; } static int copy(const char *from, const char *to) @@ -516,49 +419,49 @@ static int copy(const char *from, const char *to) /* Copy source to destination. */ if (!(pid = fork())) { - execl(adexecp, "ad", "cp", vflg ? "-Rpv" : "-Rp", from, to, (char *)NULL); + execl(_PATH_AD, "ad", "cp", vflg ? "-Rpv" : "-Rp", from, to, (char *)NULL); _exit(1); } while ((waitpid(pid, &status, 0)) == -1) { if (errno == EINTR) continue; - SLOG("%s %s %s: waitpid: %s", adexecp, from, to, strerror(errno)); + SLOG("%s cp -R %s %s: waitpid: %s", _PATH_AD, from, to, strerror(errno)); return (1); } if (!WIFEXITED(status)) { - SLOG("%s %s %s: did not terminate normally", adexecp, from, to); + SLOG("%s cp -R %s %s: did not terminate normally", _PATH_AD, from, to); return (1); } switch (WEXITSTATUS(status)) { case 0: break; default: - SLOG("%s cp %s %s: terminated with %d (non-zero) status", - adexecp, from, to, WEXITSTATUS(status)); + SLOG("%s cp -R %s %s: terminated with %d (non-zero) status", + _PATH_AD, from, to, WEXITSTATUS(status)); return (1); } /* Delete the source. */ if (!(pid = fork())) { - execl(adexecp, "ad", "rm", "-R", from, (char *)NULL); + execl(_PATH_AD, "ad", "rm", "-R", from, (char *)NULL); _exit(1); } while ((waitpid(pid, &status, 0)) == -1) { if (errno == EINTR) continue; - SLOG("%s rm %s: waitpid: %s", adexecp, from, strerror(errno)); + SLOG("%s rm -R %s: waitpid: %s", _PATH_AD, from, strerror(errno)); return (1); } if (!WIFEXITED(status)) { - SLOG("%s rm %s: did not terminate normally", adexecp, from); + SLOG("%s rm -R %s: did not terminate normally", _PATH_AD, from); return (1); } switch (WEXITSTATUS(status)) { case 0: break; default: - SLOG("%s rm %s: terminated with %d (non-zero) status", - adexecp, from, WEXITSTATUS(status)); + SLOG("%s rm -R %s: terminated with %d (non-zero) status", + _PATH_AD, from, WEXITSTATUS(status)); return (1); } return 0;