(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.
This commit is contained in:
Jim Meyering
1995-12-22 05:30:48 +00:00
parent 8cff7ef2b9
commit 654ad9e596
+51 -2
View File
@@ -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. */