diff options
author | julian <julian@FreeBSD.org> | 2006-08-24 20:45:38 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 2006-08-24 20:45:38 +0000 |
commit | b0fd0e692560ae88e7e9773907b6d2c18a8d0196 (patch) | |
tree | 4d497ada8393e7dbb8d94ec459fa2ab39e7c063d /bin/cp | |
parent | e574350b77b314c0adecc7516040ab41e14df230 (diff) | |
download | FreeBSD-src-b0fd0e692560ae88e7e9773907b6d2c18a8d0196.zip FreeBSD-src-b0fd0e692560ae88e7e9773907b6d2c18a8d0196.tar.gz |
Add an option to allow copying of a hierarchy while linking he regular files.
Bikeshedded to death on: hackers
Submitted by:andersonatcenttech.com
MFC in: 1 month
Diffstat (limited to 'bin/cp')
-rw-r--r-- | bin/cp/cp.1 | 6 | ||||
-rw-r--r-- | bin/cp/cp.c | 10 | ||||
-rw-r--r-- | bin/cp/extern.h | 2 | ||||
-rw-r--r-- | bin/cp/utils.c | 169 |
4 files changed, 105 insertions, 82 deletions
diff --git a/bin/cp/cp.1 b/bin/cp/cp.1 index 91b532f..3730423 100644 --- a/bin/cp/cp.1 +++ b/bin/cp/cp.1 @@ -45,7 +45,7 @@ .Op Fl H | Fl L | Fl P .Oc .Op Fl f | i | n -.Op Fl pv +.Op Fl plv .Ar source_file target_file .Nm .Oo @@ -53,7 +53,7 @@ .Op Fl H | Fl L | Fl P .Oc .Op Fl f | i | n -.Op Fl pv +.Op Fl plv .Ar source_file ... target_directory .Sh DESCRIPTION In the first synopsis form, the @@ -116,6 +116,8 @@ If you need to preserve hard links, consider using or .Xr pax 1 instead. +.It Fl l +Create hard links to regular files in a hierarchy instead of copying. .It Fl f For each existing destination pathname, remove it and create a new file, without prompting for confirmation diff --git a/bin/cp/cp.c b/bin/cp/cp.c index b0a3db7..e87588b 100644 --- a/bin/cp/cp.c +++ b/bin/cp/cp.c @@ -83,7 +83,7 @@ static char emptystring[] = ""; PATH_T to = { to.p_path, emptystring, "" }; -int fflag, iflag, nflag, pflag, vflag; +int fflag, iflag, lflag, nflag, pflag, vflag; static int Rflag, rflag; volatile sig_atomic_t info; @@ -102,7 +102,7 @@ main(int argc, char *argv[]) char *target; Hflag = Lflag = Pflag = 0; - while ((ch = getopt(argc, argv, "HLPRfinprv")) != -1) + while ((ch = getopt(argc, argv, "HLPRfinprvl")) != -1) switch (ch) { case 'H': Hflag = 1; @@ -140,6 +140,9 @@ main(int argc, char *argv[]) case 'v': vflag = 1; break; + case 'l': + lflag = 1; + break; default: usage(); break; @@ -457,6 +460,9 @@ copy(char *argv[], enum op type, int fts_options) badcp = rval = 1; } break; + case S_IFSOCK: + warnx("%s is a socket (not copied).", + curr->fts_path); case S_IFIFO: if (Rflag) { if (copy_fifo(curr->fts_statp, !dne)) diff --git a/bin/cp/extern.h b/bin/cp/extern.h index 25077f8..94c416b 100644 --- a/bin/cp/extern.h +++ b/bin/cp/extern.h @@ -37,7 +37,7 @@ typedef struct { } PATH_T; extern PATH_T to; -extern int fflag, iflag, nflag, pflag, vflag; +extern int fflag, iflag, lflag, nflag, pflag, vflag; extern volatile sig_atomic_t info; __BEGIN_DECLS diff --git a/bin/cp/utils.c b/bin/cp/utils.c index 5b29e6a..c40204f 100644 --- a/bin/cp/utils.c +++ b/bin/cp/utils.c @@ -61,7 +61,7 @@ copy_file(const FTSENT *entp, int dne) { static char buf[MAXBSIZE]; struct stat *fs; - int ch, checkch, from_fd, rcount, rval, to_fd; + int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0; ssize_t wcount; size_t wresid; size_t wtotal; @@ -109,15 +109,20 @@ copy_file(const FTSENT *entp, int dne) /* remove existing destination file name, * create a new file */ (void)unlink(to.p_path); - to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, - fs->st_mode & ~(S_ISUID | S_ISGID)); - } else - /* overwrite existing destination file name */ - to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0); - } else - to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, - fs->st_mode & ~(S_ISUID | S_ISGID)); - + if (!lflag) + to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, + fs->st_mode & ~(S_ISUID | S_ISGID)); + } else { + if (!lflag) + /* overwrite existing destination file name */ + to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0); + } + } else { + if (!lflag) + to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, + fs->st_mode & ~(S_ISUID | S_ISGID)); + } + if (to_fd == -1) { warn("%s", to.p_path); (void)close(from_fd); @@ -126,77 +131,85 @@ copy_file(const FTSENT *entp, int dne) rval = 0; - /* - * Mmap and write if less than 8M (the limit is so we don't totally - * trash memory on big files. This is really a minor hack, but it - * wins some CPU back. - */ + if (!lflag) { + /* + * Mmap and write if less than 8M (the limit is so we don't totally + * trash memory on big files. This is really a minor hack, but it + * wins some CPU back. + */ #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED - if (S_ISREG(fs->st_mode) && fs->st_size > 0 && - fs->st_size <= 8 * 1048576) { - if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ, - MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) { - warn("%s", entp->fts_path); - rval = 1; - } else { - wtotal = 0; - for (bufp = p, wresid = fs->st_size; ; - bufp += wcount, wresid -= (size_t)wcount) { - wcount = write(to_fd, bufp, wresid); - wtotal += wcount; - if (info) { - info = 0; - (void)fprintf(stderr, - "%s -> %s %3d%%\n", - entp->fts_path, to.p_path, - cp_pct(wtotal, fs->st_size)); - - } - if (wcount >= (ssize_t)wresid || wcount <= 0) - break; - } - if (wcount != (ssize_t)wresid) { - warn("%s", to.p_path); - rval = 1; - } - /* Some systems don't unmap on close(2). */ - if (munmap(p, fs->st_size) < 0) { + if (S_ISREG(fs->st_mode) && fs->st_size > 0 && + fs->st_size <= 8 * 1048576) { + if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ, + MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) { warn("%s", entp->fts_path); rval = 1; + } else { + wtotal = 0; + for (bufp = p, wresid = fs->st_size; ; + bufp += wcount, wresid -= (size_t)wcount) { + wcount = write(to_fd, bufp, wresid); + wtotal += wcount; + if (info) { + info = 0; + (void)fprintf(stderr, + "%s -> %s %3d%%\n", + entp->fts_path, to.p_path, + cp_pct(wtotal, fs->st_size)); + + } + if (wcount >= (ssize_t)wresid || wcount <= 0) + break; + } + if (wcount != (ssize_t)wresid) { + warn("%s", to.p_path); + rval = 1; + } + /* Some systems don't unmap on close(2). */ + if (munmap(p, fs->st_size) < 0) { + warn("%s", entp->fts_path); + rval = 1; + } } - } - } else + } else #endif - { - wtotal = 0; - while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { - for (bufp = buf, wresid = rcount; ; - bufp += wcount, wresid -= wcount) { - wcount = write(to_fd, bufp, wresid); - wtotal += wcount; - if (info) { - info = 0; - (void)fprintf(stderr, - "%s -> %s %3d%%\n", - entp->fts_path, to.p_path, - cp_pct(wtotal, fs->st_size)); - + { + wtotal = 0; + while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { + for (bufp = buf, wresid = rcount; ; + bufp += wcount, wresid -= wcount) { + wcount = write(to_fd, bufp, wresid); + wtotal += wcount; + if (info) { + info = 0; + (void)fprintf(stderr, + "%s -> %s %3d%%\n", + entp->fts_path, to.p_path, + cp_pct(wtotal, fs->st_size)); + + } + if (wcount >= (ssize_t)wresid || wcount <= 0) + break; } - if (wcount >= (ssize_t)wresid || wcount <= 0) + if (wcount != (ssize_t)wresid) { + warn("%s", to.p_path); + rval = 1; break; + } } - if (wcount != (ssize_t)wresid) { - warn("%s", to.p_path); + if (rcount < 0) { + warn("%s", entp->fts_path); rval = 1; - break; } } - if (rcount < 0) { - warn("%s", entp->fts_path); + } else { + if (link(entp->fts_path, to.p_path)) { + warn("%s", to.p_path); rval = 1; } } - + (void)close(from_fd); + /* * Don't remove the target even after an error. The target might * not be a regular file, or its attributes might be important, @@ -204,14 +217,16 @@ copy_file(const FTSENT *entp, int dne) * to remove it if we created it and its length is 0. */ - if (pflag && setfile(fs, to_fd)) - rval = 1; - if (pflag && preserve_fd_acls(from_fd, to_fd) != 0) - rval = 1; - (void)close(from_fd); - if (close(to_fd)) { - warn("%s", to.p_path); - rval = 1; + if (!lflag) { + if (pflag && setfile(fs, to_fd)) + rval = 1; + if (pflag && preserve_fd_acls(from_fd, to_fd) != 0) + rval = 1; + (void)close(from_fd); + if (close(to_fd)) { + warn("%s", to.p_path); + rval = 1; + } } return (rval); } @@ -411,8 +426,8 @@ usage(void) { (void)fprintf(stderr, "%s\n%s\n", -"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-pv] source_file target_file", -" cp [-R [-H | -L | -P]] [-f | -i | -n] [-pv] source_file ... " +"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-aplv] source_file target_file", +" cp [-R [-H | -L | -P]] [-f | -i | -n] [-aplv] source_file ... " "target_directory"); exit(EX_USAGE); } |