From 654ad9e596595ecb17fabe34fe9595a765b6adee Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Fri, 22 Dec 1995 05:30:48 +0000 Subject: [PATCH] (main): Accept new option, --sparse={never,auto,always}, to control creation of sparse files. (copy_reg): Set local, make_holes, from global flag_sparse. Include argmatch.h. --- src/cp.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/src/cp.c b/src/cp.c index 553e93b..84385b6 100644 --- a/src/cp.c +++ b/src/cp.c @@ -27,6 +27,7 @@ #include "cp.h" #include "backupfile.h" #include "version.h" +#include "argmatch.h" #ifndef _POSIX_VERSION uid_t geteuid (); @@ -42,6 +43,25 @@ struct dir_attr struct dir_attr *next; }; +/* Control creation of sparse files (files with holes). */ +enum Sparse_type +{ + /* Never create holes in DEST. */ + SPARSE_NEVER, + + /* This is the default. Use a crude (and sometimes inaccurate) + heuristic to determine if SOURCE has holes. If so, try to create + holes in DEST. */ + SPARSE_AUTO, + + /* For every sufficiently long sequence of bytes in SOURCE, try to + create a corresponding hole in DEST. There is a performance penalty + here because CP has to search for holes in SRC. But if the holes are + big enough, that penalty can be offset by the decrease in the amount + of data written to disk. */ + SPARSE_ALWAYS +}; + int stat (); int lstat (); @@ -121,6 +141,19 @@ static int flag_update = 0; /* If nonzero, display the names of the files before copying them. */ static int flag_verbose = 0; +static char const *const sparse_type_string[] = +{ + "never", "auto", "always", 0 +}; + +static enum Sparse_type const sparse_type[] = +{ + SPARSE_NEVER, SPARSE_AUTO, SPARSE_ALWAYS +}; + +/* Control creation of sparse files. */ +static int flag_sparse = SPARSE_AUTO; + /* The error code to return to the system. */ static int exit_status = 0; @@ -141,6 +174,7 @@ static struct option const long_opts[] = {"archive", no_argument, NULL, 'a'}, {"backup", no_argument, NULL, 'b'}, {"force", no_argument, NULL, 'f'}, + {"sparse", required_argument, NULL, 2}, {"interactive", no_argument, NULL, 'i'}, {"link", no_argument, NULL, 'l'}, {"no-dereference", no_argument, &flag_dereference, 0}, @@ -189,6 +223,21 @@ main (int argc, char **argv) case 0: break; + case 2: + { + int i; + + /* --sparse={never,auto,always} */ + i = argmatch (optarg, sparse_type_string); + if (i < 0) + { + invalid_arg (_("sparse type"), optarg, i); + usage (2, NULL); + } + flag_sparse = sparse_type[i]; + } + break; + case 'a': /* Like -dpR. */ flag_dereference = 0; flag_preserve = 1; @@ -1110,7 +1159,7 @@ copy_reg (char *src_path, char *dst_path) int return_val = 0; long n_read_total = 0; int last_write_made_hole = 0; - int make_holes = 0; + int make_holes = (flag_sparse == SPARSE_ALWAYS); source_desc = open (src_path, O_RDONLY); if (source_desc < 0) @@ -1142,7 +1191,7 @@ copy_reg (char *src_path, char *dst_path) buf_size = ST_BLKSIZE (sb); #ifdef HAVE_ST_BLOCKS - if (S_ISREG (sb.st_mode)) + if (flag_sparse == SPARSE_AUTO && S_ISREG (sb.st_mode)) { /* Find out whether the file contains any sparse blocks. */ -- 2.7.4