diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2007-04-06 06:50:01 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2007-04-06 06:50:01 +0000 |
commit | 6b0096fa8cd214ebd47963815eca5df17a7fb9c0 (patch) | |
tree | b0c8ea05fafadde1b1742080c7fc5d92844f7e70 /bin/cp | |
parent | ae4bd25363a42e533d1655f3f8676a5ce572624f (diff) |
when copying regular files, look for blocks of zeroes. when we see them,
just lseek ahead to create a sparse file. saves disk and time.
note this behavior in the man page.
ok? deraadt millert
Diffstat (limited to 'bin/cp')
-rw-r--r-- | bin/cp/cp.1 | 6 | ||||
-rw-r--r-- | bin/cp/utils.c | 30 |
2 files changed, 31 insertions, 5 deletions
diff --git a/bin/cp/cp.1 b/bin/cp/cp.1 index 3c7a7ac6bc3..66702981e63 100644 --- a/bin/cp/cp.1 +++ b/bin/cp/cp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: cp.1,v 1.25 2004/12/10 10:23:30 jmc Exp $ +.\" $OpenBSD: cp.1,v 1.26 2007/04/06 06:50:00 tedu Exp $ .\" $NetBSD: cp.1,v 1.9 1995/07/25 19:36:45 jtc Exp $ .\" .\" Copyright (c) 1989, 1990, 1993, 1994 @@ -166,6 +166,10 @@ conditions must be fulfilled or both bits are removed. .Pp Appropriate permissions are required for file creation or overwriting. .Pp +When a file containing large blocks of zero-valued bytes is copied, +.Nm +will attempt to create a sparse file. +.Pp Symbolic links are always followed unless the .Fl R flag is set, in which case symbolic links are not followed, by default. diff --git a/bin/cp/utils.c b/bin/cp/utils.c index 7e1185fd48b..fa62660fe76 100644 --- a/bin/cp/utils.c +++ b/bin/cp/utils.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utils.c,v 1.26 2004/12/10 10:23:30 jmc Exp $ */ +/* $OpenBSD: utils.c,v 1.27 2007/04/06 06:50:00 tedu Exp $ */ /* $NetBSD: utils.c,v 1.6 1997/02/26 14:40:51 cgd Exp $ */ /*- @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94"; #else -static char rcsid[] = "$OpenBSD: utils.c,v 1.26 2004/12/10 10:23:30 jmc Exp $"; +static char rcsid[] = "$OpenBSD: utils.c,v 1.27 2007/04/06 06:50:00 tedu Exp $"; #endif #endif /* not lint */ @@ -57,13 +57,26 @@ static char rcsid[] = "$OpenBSD: utils.c,v 1.26 2004/12/10 10:23:30 jmc Exp $"; int copy_file(FTSENT *entp, int dne) { - static char buf[MAXBSIZE]; + static char *buf; + static char *zeroes; struct stat to_stat, *fs; int ch, checkch, from_fd, rcount, rval, to_fd, wcount; #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED char *p; #endif + if (!buf) { + buf = malloc(MAXBSIZE); + if (!buf) + err(1, "malloc"); + } + if (!zeroes) { + zeroes = malloc(MAXBSIZE); + if (!zeroes) + err(1, "malloc"); + memset(zeroes, 0, MAXBSIZE); + } + if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) { warn("%s", entp->fts_path); return (1); @@ -136,14 +149,23 @@ copy_file(FTSENT *entp, int dne) } else #endif { + int skipholes = 0; + struct stat tosb; + if (!fstat(to_fd, &tosb) && S_ISREG(tosb.st_mode)) + skipholes = 1; while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { - wcount = write(to_fd, buf, rcount); + if (skipholes && memcmp(buf, zeroes, rcount) == 0) + wcount = lseek(to_fd, rcount, SEEK_CUR) == -1 ? -1 : rcount; + else + wcount = write(to_fd, buf, rcount); if (rcount != wcount || wcount == -1) { warn("%s", to.p_path); rval = 1; break; } } + if (skipholes && rcount >= 0) + rcount = ftruncate(to_fd, fs->st_size); if (rcount < 0) { warn("%s", entp->fts_path); rval = 1; |