[PATCH] adding two new options to 'cp'
Eric Anderson
anderson at centtech.com
Thu Jul 27 02:51:36 UTC 2006
I'm tired of trying to use rsync or gcp (which doesn't like symlinks
often) to copy trees of files/directories using hard links, so I added
the gcp-ish options -a and -l.
-a is 'archive' mode, which is just a quick form of -PpR.
-l is 'link' mode, where regular files get hard linked instead of copied.
So, you can mimic an entire tree with something like:
cp -al /from/ /to/
and it's fast too!
Patch is against 6-STABLE, but works well on 7-CURRENT as well.
Patch is here (with man page edits):
http://www.googlebit.com/freebsd/patches/cp-patch
cd /tmp/
fetch http://www.googlebit.com/freebsd/patches/cp-patch
cd /usr/src/
patch < /tmp/cp-patch
cd bin/cp
make && make install
Patch was done for rsnapshot users mainly (there are quite a few of us).
Comments? Flames? Committers willing to commit?
Eric
--
------------------------------------------------------------------------
Eric Anderson Sr. Systems Administrator Centaur Technology
Anything that works is better than anything that doesn't.
------------------------------------------------------------------------
-------------- next part --------------
Index: bin/cp/cp.1
===================================================================
RCS file: /alt/ncvs/src/bin/cp/cp.1,v
retrieving revision 1.33
diff -u -u -r1.33 cp.1
--- bin/cp/cp.1 25 Feb 2005 00:40:46 -0000 1.33
+++ bin/cp/cp.1 26 Jul 2006 19:52:42 -0000
@@ -45,7 +45,7 @@
.Op Fl H | Fl L | Fl P
.Oc
.Op Fl f | i | n
-.Op Fl pv
+.Op Fl aplv
.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 aplv
.Ar source_file ... target_directory
.Sh DESCRIPTION
In the first synopsis form, the
@@ -116,6 +116,10 @@
or
.Xr pax 1
instead.
+.It Fl a
+Archive mode. Same as -PpR
+.It Fl l
+Create hard links to regular files instead of copying.
.It Fl f
For each existing destination pathname, remove it and
create a new file, without prompting for confirmation
Index: bin/cp/cp.c
===================================================================
RCS file: /alt/ncvs/src/bin/cp/cp.c,v
retrieving revision 1.51.2.1
diff -u -u -r1.51.2.1 cp.c
--- bin/cp/cp.c 12 Nov 2005 21:21:45 -0000 1.51.2.1
+++ bin/cp/cp.c 26 Jul 2006 17:49:55 -0000
@@ -83,7 +83,7 @@
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 @@
char *target;
Hflag = Lflag = Pflag = 0;
- while ((ch = getopt(argc, argv, "HLPRfinprv")) != -1)
+ while ((ch = getopt(argc, argv, "HLPRfinprvla")) != -1)
switch (ch) {
case 'H':
Hflag = 1;
@@ -140,6 +140,15 @@
case 'v':
vflag = 1;
break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'a':
+ Pflag = 1;
+ pflag = 1;
+ Rflag = 1;
+ Hflag = Lflag = 0;
+ break;
default:
usage();
break;
Index: bin/cp/extern.h
===================================================================
RCS file: /alt/ncvs/src/bin/cp/extern.h,v
retrieving revision 1.19.8.1
diff -u -u -r1.19.8.1 extern.h
--- bin/cp/extern.h 12 Nov 2005 21:21:45 -0000 1.19.8.1
+++ bin/cp/extern.h 26 Jul 2006 17:49:55 -0000
@@ -37,7 +37,7 @@
} 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
Index: bin/cp/utils.c
===================================================================
RCS file: /alt/ncvs/src/bin/cp/utils.c,v
retrieving revision 1.45.2.1
diff -u -u -r1.45.2.1 utils.c
--- bin/cp/utils.c 12 Nov 2005 21:21:45 -0000 1.45.2.1
+++ bin/cp/utils.c 26 Jul 2006 19:39:09 -0000
@@ -61,7 +61,7 @@
{
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 @@
/* 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,73 +131,81 @@
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)) {
+ (void)close(from_fd);
+ warn("%s", to.p_path);
rval = 1;
}
}
@@ -204,14 +217,16 @@
* 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);
}
Index: etc/mtree/BSD.include.dist
===================================================================
RCS file: /alt/ncvs/src/etc/mtree/BSD.include.dist,v
retrieving revision 1.100.2.2
diff -u -u -r1.100.2.2 BSD.include.dist
--- etc/mtree/BSD.include.dist 16 Nov 2005 10:50:10 -0000 1.100.2.2
+++ etc/mtree/BSD.include.dist 26 Jul 2006 03:42:10 -0000
@@ -100,6 +100,8 @@
..
gate
..
+ journal
+ ..
label
..
mirror
Index: include/Makefile
===================================================================
RCS file: /alt/ncvs/src/include/Makefile,v
retrieving revision 1.244.2.4
diff -u -u -r1.244.2.4 Makefile
--- include/Makefile 17 Jul 2006 10:09:54 -0000 1.244.2.4
+++ include/Makefile 26 Jul 2006 03:42:10 -0000
@@ -42,8 +42,8 @@
fs/devfs fs/fdescfs fs/fifofs fs/msdosfs fs/ntfs fs/nullfs \
fs/nwfs fs/portalfs fs/procfs fs/smbfs fs/udf fs/umapfs \
fs/unionfs \
- geom/concat geom/eli geom/gate geom/label geom/mirror geom/nop \
- geom/raid3 geom/shsec geom/stripe \
+ geom/concat geom/eli geom/gate geom/journal geom/label geom/mirror \
+ geom/nop geom/raid3 geom/shsec geom/stripe \
isofs/cd9660 \
netatm/ipatm netatm/sigpvc netatm/spans netatm/uni \
netgraph/atm netgraph/netflow \
More information about the freebsd-hackers
mailing list