diff --git a/cp.c b/cp.c index 4bba1b5..ebc3566 100644 --- a/cp.c +++ b/cp.c @@ -17,7 +17,7 @@ main(int argc, char *argv[]) ARGBEGIN { case 'a': - cp_HLPflag = 'P'; + cp_follow = 'P'; cp_aflag = cp_pflag = cp_rflag = 1; break; case 'f': @@ -36,7 +36,7 @@ main(int argc, char *argv[]) case 'H': case 'L': case 'P': - cp_HLPflag = ARGC(); + cp_follow = ARGC(); break; default: usage(); diff --git a/fs.h b/fs.h index 91b130f..e7590f8 100644 --- a/fs.h +++ b/fs.h @@ -25,7 +25,7 @@ extern int cp_fflag; extern int cp_pflag; extern int cp_rflag; extern int cp_vflag; -extern int cp_HLPflag; +extern int cp_follow; extern int cp_status; extern int rm_fflag; diff --git a/libutil/cp.c b/libutil/cp.c index c6ff48e..32e0dc6 100644 --- a/libutil/cp.c +++ b/libutil/cp.c @@ -15,136 +15,162 @@ #include "../text.h" #include "../util.h" -int cp_aflag = 0; -int cp_fflag = 0; -int cp_pflag = 0; -int cp_rflag = 0; -int cp_vflag = 0; +int cp_aflag = 0; +int cp_fflag = 0; +int cp_pflag = 0; +int cp_rflag = 0; +int cp_vflag = 0; int cp_status = 0; -int cp_HLPflag = 'L'; +int cp_follow = 'L'; int cp(const char *s1, const char *s2, int depth) { + DIR *dp; FILE *f1, *f2; - char ns1[PATH_MAX], ns2[PATH_MAX]; struct dirent *d; struct stat st; struct utimbuf ut; - char buf[PATH_MAX]; - DIR *dp; - int r; + ssize_t r; + int (*statf)(const char *, struct stat *); + char target[PATH_MAX], ns1[PATH_MAX], ns2[PATH_MAX], *statf_name; + + if (cp_follow == 'P' || (cp_follow == 'H' && depth)) { + statf_name = "lstat"; + statf = lstat; + } else { + statf_name = "stat"; + statf = stat; + } + + if (statf(s1, &st) < 0) { + weprintf("%s %s:", statf_name, s1); + cp_status = 1; + return 0; + } if (cp_vflag) - printf("'%s' -> '%s'\n", s1, s2); - - r = (cp_HLPflag == 'P' || (cp_HLPflag == 'H' && depth > 0)) ? - lstat(s1, &st) : stat(s1, &st); - if (r < 0) { - weprintf("%s %s:", (cp_HLPflag == 'P' || - (cp_HLPflag == 'H' && depth > 0)) ? "lstat" : "stat", s1); - cp_status = 1; - return 0; - } + printf("%s -> %s\n", s1, s2); if (S_ISLNK(st.st_mode)) { - if (readlink(s1, buf, sizeof(buf) - 1) >= 0) { - if (cp_fflag) - unlink(s2); - if (symlink(buf, s2) != 0) { - weprintf("%s: can't create '%s'\n", argv0, s2); + if ((r = readlink(s1, target, sizeof(target) - 1)) >= 0) { + target[r] = '\0'; + if (cp_fflag && unlink(s2) < 0 && errno != ENOENT) { + weprintf("unlink %s:", s2); + cp_status = 1; + return 0; + } else if (symlink(target, s2) < 0) { + weprintf("symlink %s -> %s:", s2, target); cp_status = 1; return 0; } } - goto preserve; - } - - if (S_ISDIR(st.st_mode)) { - if (!cp_rflag) - eprintf("%s: is a directory\n", s1); - - if (!(dp = opendir(s1))) - eprintf("opendir %s:", s1); - - if (mkdir(s2, st.st_mode) < 0 && errno != EEXIST) - eprintf("mkdir %s:", s2); + } else if (S_ISDIR(st.st_mode)) { + if (!cp_rflag) { + weprintf("%s is a directory\n", s1); + cp_status = 1; + return 0; + } + if (!(dp = opendir(s1))) { + weprintf("opendir %s:", s1); + cp_status = 1; + return 0; + } + if (mkdir(s2, st.st_mode) < 0 && errno != EEXIST) { + weprintf("mkdir %s:", s2); + cp_status = 1; + return 0; + } while ((d = readdir(dp))) { - if (strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) { - r = snprintf(ns1, sizeof(ns1), "%s/%s", s1, d->d_name); - if (r >= sizeof(ns1) || r < 0) { - eprintf("%s/%s: filename too long\n", - s1, d->d_name); - } - r = snprintf(ns2, sizeof(ns2), "%s/%s", s2, d->d_name); - if (r >= sizeof(ns2) || r < 0) { - eprintf("%s/%s: filename too long\n", - s2, d->d_name); - } - fnck(ns1, ns2, cp, depth + 1); - } + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; + + estrlcpy(ns1, s1, sizeof(ns1)); + if(s1[strlen(s1) - 1] != '/') + estrlcat(ns1, "/", sizeof(ns1)); + estrlcat(ns1, d->d_name, sizeof(ns1)); + + estrlcpy(ns2, s2, sizeof(ns2)); + if(s2[strlen(s2) - 1] != '/') + estrlcat(ns2, "/", sizeof(ns2)); + estrlcat(ns2, d->d_name, sizeof(ns2)); + + fnck(ns1, ns2, cp, depth + 1); } + closedir(dp); - goto preserve; - } - - if (cp_aflag) { - if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || - S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode)) { - unlink(s2); - if (mknod(s2, st.st_mode, st.st_rdev) < 0) { - weprintf("%s: can't create '%s':", argv0, s2); - cp_status = 1; - return 0; - } - goto preserve; + } else if (cp_aflag && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || + S_ISSOCK(st.st_mode) || S_ISFIFO(st.st_mode))) { + if (cp_fflag && unlink(s2) < 0 && errno != ENOENT) { + weprintf("unlink %s:", s2); + cp_status = 1; + return 0; + } else if (mknod(s2, st.st_mode, st.st_rdev) < 0) { + weprintf("mknod %s:", s2); + cp_status = 1; + return 0; } - } - - if (!(f1 = fopen(s1, "r"))) { - weprintf("fopen %s:", s1); - cp_status = 1; - return 0; - } - - if (!(f2 = fopen(s2, "w"))) { - if (cp_fflag) { - unlink(s2); - if (!(f2 = fopen(s2, "w"))) { + } else { + if (!(f1 = fopen(s1, "r"))) { + weprintf("fopen %s:", s1); + cp_status = 1; + return 0; + } + if (!(f2 = fopen(s2, "w"))) { + if (cp_fflag) { + if (unlink(s2) < 0 && errno != ENOENT) { + weprintf("unlink %s:", s2); + cp_status = 1; + return 0; + } else if (!(f2 = fopen(s2, "w"))) { + weprintf("fopen %s:", s2); + cp_status = 1; + return 0; + } + } else { weprintf("fopen %s:", s2); cp_status = 1; return 0; } - } else { - weprintf("fopen %s:", s2); + } + concat(f1, s1, f2, s2); + + /* preserve permissions by default */ + fchmod(fileno(f2), st.st_mode); + + if (fclose(f2) == EOF) { + weprintf("fclose %s:", s2); + cp_status = 1; + return 0; + } + if (fclose(f1) == EOF) { + weprintf("fclose %s:", s1); cp_status = 1; return 0; } } - concat(f1, s1, f2, s2); - /* preserve permissions by default */ - fchmod(fileno(f2), st.st_mode); - fclose(f2); - fclose(f1); -preserve: if (cp_aflag || cp_pflag) { - if (!(S_ISLNK(st.st_mode))) { - /* timestamp */ + /* timestamp and owner*/ + if (!S_ISLNK(st.st_mode)) { ut.actime = st.st_atime; ut.modtime = st.st_mtime; utime(s2, &ut); - } - /* preserve owner ? */ - if (S_ISLNK(st.st_mode)) - r = lchown(s2, st.st_uid, st.st_gid); - else - r = chown(s2, st.st_uid, st.st_gid); - if (r < 0) { - weprintf("cp: can't preserve ownership of '%s':", s2); - cp_status = 1; + + if (chown(s2, st.st_uid, st.st_gid) < 0) { + weprintf("chown %s:", s2); + cp_status = 1; + return 0; + } + } else { + if (lchown(s2, st.st_uid, st.st_gid) < 0) { + weprintf("lchown %s:", s2); + cp_status = 1; + return 0; + } } } + return 0; } diff --git a/mv.c b/mv.c index 404a310..9d5b77a 100644 --- a/mv.c +++ b/mv.c @@ -18,7 +18,7 @@ mv(const char *s1, const char *s2, int depth) return (mv_status = 0); if (errno == EXDEV) { cp_aflag = cp_rflag = cp_pflag = 1; - cp_HLPflag = 'P'; + cp_follow = 'P'; rm_rflag = 1; cp(s1, s2, depth); rm(s1, NULL, NULL, &r);