On Thu, May 23, 2019 at 02:35:10PM -0600, Tracey Emery wrote:
> Hello tech@,
>
> Attached is a proposed diff for cp(1). It adds the -l (hard link) and -s
> (symlink) options. These options are available in GNU cp, FreeBSD cp,
> and the -l option is at least in NetBSD and Dragonfly.
>
> I needed the -l option to use the system cp for rsnapshots, instead of
> their native_cl_al function. Hopefully, this will speed up my backups.
>
> Thanks for your consideration,
> Tracey
>
>
> Index: bin/cp/cp.1
> ===================================================================
> RCS file: /cvs/src/bin/cp/cp.1,v
> retrieving revision 1.40
> diff -u -p -u -r1.40 cp.1
> --- bin/cp/cp.1 28 Jan 2019 18:58:42 -0000 1.40
> +++ bin/cp/cp.1 23 May 2019 20:28:29 -0000
> @@ -103,6 +103,8 @@ The
> option overrides any previous
> .Fl f
> options.
> +.It Fl l
> +Create hard links to regular files in a hierarchy instead of copying.
> .It Fl L
> If the
> .Fl R
> @@ -128,6 +130,8 @@ If the source file has both its set-user
> and either the user ID or group ID cannot be preserved, neither
> the set-user-ID nor set-group-ID bits are preserved in the copy's
> permissions.
> +.It Fl s
> +Create symbolic links to regular files in a hirarcy instead of copying.
> .It Fl R
> If
> .Ar source
> Index: bin/cp/cp.c
> ===================================================================
> RCS file: /cvs/src/bin/cp/cp.c,v
> retrieving revision 1.52
> diff -u -p -u -r1.52 cp.c
> --- bin/cp/cp.c 28 Jan 2019 18:58:42 -0000 1.52
> +++ bin/cp/cp.c 23 May 2019 20:28:30 -0000
> @@ -71,7 +71,7 @@
> PATH_T to = { to.p_path, "" };
>
> uid_t myuid;
> -int Rflag, fflag, iflag, pflag, rflag, vflag;
> +int Rflag, fflag, iflag, lflag, pflag, rflag, sflag, vflag;
> mode_t myumask;
>
> enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
> @@ -88,7 +88,7 @@ main(int argc, char *argv[])
> char *target;
>
> Hflag = Lflag = Pflag = Rflag = 0;
> - while ((ch = getopt(argc, argv, "HLPRafiprv")) != -1)
> + while ((ch = getopt(argc, argv, "HLPRafiprvls")) != -1)
> switch (ch) {
> case 'H':
> Hflag = 1;
> @@ -119,12 +119,18 @@ main(int argc, char *argv[])
> iflag = 1;
> fflag = 0;
> break;
> + case 'l':
> + lflag = 1;
> + break;
> case 'p':
> pflag = 1;
> break;
> case 'r':
> rflag = 1;
> break;
> + case 's':
> + sflag = 1;
> + break;
> case 'v':
> vflag = 1;
> break;
> @@ -157,6 +163,8 @@ main(int argc, char *argv[])
> fts_options &= ~FTS_PHYSICAL;
> fts_options |= FTS_LOGICAL;
> }
> + if (lflag && sflag)
> + errx(1, "the -l and -s options may not be specified together.");
> if (Rflag) {
> if (Hflag)
> fts_options |= FTS_COMFOLLOW;
> @@ -319,7 +327,7 @@ copy(char *argv[], enum op type, int fts
> if (type != DIR_TO_DNE) {
> p = find_last_component(curr->fts_path);
> base = p - curr->fts_path;
> -
> +
> if (!strcmp(&curr->fts_path[base],
> ".."))
> base += 1;
> @@ -435,7 +443,7 @@ copy(char *argv[], enum op type, int fts
> break;
> case S_IFBLK:
> case S_IFCHR:
> - if (Rflag) {
> + if (Rflag && !sflag) {
> if ((cval = copy_special(curr->fts_statp,
> !fts_dne(curr))) == 1)
> rval = 1;
> @@ -448,7 +456,7 @@ copy(char *argv[], enum op type, int fts
> cval = 0;
> break;
> case S_IFIFO:
> - if (Rflag) {
> + if (Rflag && !sflag) {
> if ((cval = copy_fifo(curr->fts_statp,
> !fts_dne(curr))) == 1)
> rval = 1;
> Index: bin/cp/extern.h
> ===================================================================
> RCS file: /cvs/src/bin/cp/extern.h,v
> retrieving revision 1.15
> diff -u -p -u -r1.15 extern.h
> --- bin/cp/extern.h 26 Dec 2015 18:11:43 -0000 1.15
> +++ bin/cp/extern.h 23 May 2019 20:28:30 -0000
> @@ -40,7 +40,7 @@ typedef struct {
>
> extern PATH_T to;
> extern uid_t myuid;
> -extern int fflag, iflag, pflag;
> +extern int fflag, iflag, lflag, pflag, sflag;
> extern mode_t myumask;
> extern char *__progname;
>
> Index: bin/cp/utils.c
> ===================================================================
> RCS file: /cvs/src/bin/cp/utils.c,v
> retrieving revision 1.47
> diff -u -p -u -r1.47 utils.c
> --- bin/cp/utils.c 28 Jan 2019 18:58:42 -0000 1.47
> +++ bin/cp/utils.c 23 May 2019 20:28:30 -0000
> @@ -71,7 +71,8 @@ copy_file(FTSENT *entp, int exists)
> err(1, "calloc");
> }
>
> - if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
> + if (!lflag && !sflag &&
> + (from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
> warn("%s", entp->fts_path);
> return (1);
> }
> @@ -97,12 +98,13 @@ copy_file(FTSENT *entp, int exists)
> (void)close(from_fd);
> return 2;
> }
> - to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
> - } else
> + if (!lflag && !sflag)
> + to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
> + } else if (!lflag && !sflag)
> to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
> fs->st_mode & ~(S_ISTXT | S_ISUID | S_ISGID));
>
> - if (to_fd == -1) {
> + if (!lflag && !sflag && to_fd == -1) {
> warn("%s", to.p_path);
> (void)close(from_fd);
> return (1);
> @@ -110,52 +112,69 @@ copy_file(FTSENT *entp, int exists)
>
> 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 && !sflag) {
> + /*
> + * 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
> - /* XXX broken for 0-size mmap */
> - if (fs->st_size <= 8 * 1048576) {
> - if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
> - MAP_FILE|MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
> - warn("mmap: %s", entp->fts_path);
> - rval = 1;
> - } else {
> - madvise(p, fs->st_size, MADV_SEQUENTIAL);
> - if (write(to_fd, p, fs->st_size) != fs->st_size) {
> - warn("%s", to.p_path);
> + /* XXX broken for 0-size mmap */
> + if (fs->st_size <= 8 * 1048576) {
> + if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
> + MAP_FILE|MAP_SHARED, from_fd,
> + (off_t)0)) == MAP_FAILED) {
> + warn("mmap: %s", entp->fts_path);
> rval = 1;
> + } else {
> + madvise(p, fs->st_size, MADV_SEQUENTIAL);
> + if (write(to_fd, p,
> + fs->st_size) != fs->st_size) {
> + 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;
> + }
> }
> - /* Some systems don't unmap on close(2). */
> - if (munmap(p, fs->st_size) < 0) {
> + } 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) {
> + 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, lseek(to_fd, 0,
> + SEEK_CUR));
> + if (rcount < 0) {
> warn("%s", entp->fts_path);
> rval = 1;
> }
> }
> - } 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) {
> - 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;
> - }
> + } else if (lflag) {
> + if (link(entp->fts_path, to.p_path) == -1) {
> + warn("%s", to.p_path);
> + rval = 1;
> }
> - if (skipholes && rcount >= 0)
> - rcount = ftruncate(to_fd, lseek(to_fd, 0, SEEK_CUR));
> - if (rcount < 0) {
> - warn("%s", entp->fts_path);
> + } else if (sflag) {
> + if (symlink(entp->fts_path, to.p_path) == -1) {
> + warn("%s", to.p_path);
> rval = 1;
> }
> }
> @@ -166,30 +185,34 @@ copy_file(FTSENT *entp, int exists)
> return (1);
> }
>
> - if (pflag && setfile(fs, to_fd))
> - rval = 1;
> - /*
> - * If the source was setuid or setgid, lose the bits unless the
> - * copy is owned by the same user and group.
> - */
> + if (!lflag && !sflag) {
> + if (pflag && setfile(fs, to_fd))
> + rval = 1;
> + /*
> + * If the source was setuid or setgid, lose the bits unless the
> + * copy is owned by the same user and group.
> + */
> #define RETAINBITS \
> (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
> - if (!pflag && !exists &&
> - fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) {
> - if (fstat(to_fd, &to_stat)) {
> - warn("%s", to.p_path);
> - rval = 1;
> - } else if (fs->st_gid == to_stat.st_gid &&
> - fchmod(to_fd, fs->st_mode & RETAINBITS & ~myumask)) {
> + if (!pflag && !exists &&
> + fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) {
> + if (fstat(to_fd, &to_stat)) {
> + warn("%s", to.p_path);
> + rval = 1;
> + } else if (fs->st_gid == to_stat.st_gid &&
> + fchmod(to_fd,
> + fs->st_mode & RETAINBITS & ~myumask)) {
> + warn("%s", to.p_path);
> + rval = 1;
> + }
> + }
> + if (close(to_fd)) {
> warn("%s", to.p_path);
> rval = 1;
> }
> }
> +
> (void)close(from_fd);
> - if (close(to_fd)) {
> - warn("%s", to.p_path);
> - rval = 1;
> - }
> return (rval);
> }
>
> @@ -326,9 +349,10 @@ void
> usage(void)
> {
> (void)fprintf(stderr,
> - "usage: %s [-afipv] [-R [-H | -L | -P]] source target\n",
> __progname);
> + "usage: %s [-afilpsv] [-R [-H | -L | -P]] source target\n",
> + __progname);
> (void)fprintf(stderr,
> - " %s [-afipv] [-R [-H | -L | -P]] source ... directory\n",
> + " %s [-afilpsv] [-R [-H | -L | -P]] source ... directory\n",
> __progname);
> exit(1);
> }
Sorry, getopt not alphabetized.
Index: bin/cp/cp.1
===================================================================
RCS file: /cvs/src/bin/cp/cp.1,v
retrieving revision 1.40
diff -u -p -u -r1.40 cp.1
--- bin/cp/cp.1 28 Jan 2019 18:58:42 -0000 1.40
+++ bin/cp/cp.1 23 May 2019 20:39:48 -0000
@@ -103,6 +103,8 @@ The
option overrides any previous
.Fl f
options.
+.It Fl l
+Create hard links to regular files in a hierarchy instead of copying.
.It Fl L
If the
.Fl R
@@ -128,6 +130,8 @@ If the source file has both its set-user
and either the user ID or group ID cannot be preserved, neither
the set-user-ID nor set-group-ID bits are preserved in the copy's
permissions.
+.It Fl s
+Create symbolic links to regular files in a hirarcy instead of copying.
.It Fl R
If
.Ar source
Index: bin/cp/cp.c
===================================================================
RCS file: /cvs/src/bin/cp/cp.c,v
retrieving revision 1.52
diff -u -p -u -r1.52 cp.c
--- bin/cp/cp.c 28 Jan 2019 18:58:42 -0000 1.52
+++ bin/cp/cp.c 23 May 2019 20:39:48 -0000
@@ -71,7 +71,7 @@
PATH_T to = { to.p_path, "" };
uid_t myuid;
-int Rflag, fflag, iflag, pflag, rflag, vflag;
+int Rflag, fflag, iflag, lflag, pflag, rflag, sflag, vflag;
mode_t myumask;
enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
@@ -88,7 +88,7 @@ main(int argc, char *argv[])
char *target;
Hflag = Lflag = Pflag = Rflag = 0;
- while ((ch = getopt(argc, argv, "HLPRafiprv")) != -1)
+ while ((ch = getopt(argc, argv, "HLPRafilprsv")) != -1)
switch (ch) {
case 'H':
Hflag = 1;
@@ -119,12 +119,18 @@ main(int argc, char *argv[])
iflag = 1;
fflag = 0;
break;
+ case 'l':
+ lflag = 1;
+ break;
case 'p':
pflag = 1;
break;
case 'r':
rflag = 1;
break;
+ case 's':
+ sflag = 1;
+ break;
case 'v':
vflag = 1;
break;
@@ -157,6 +163,8 @@ main(int argc, char *argv[])
fts_options &= ~FTS_PHYSICAL;
fts_options |= FTS_LOGICAL;
}
+ if (lflag && sflag)
+ errx(1, "the -l and -s options may not be specified together.");
if (Rflag) {
if (Hflag)
fts_options |= FTS_COMFOLLOW;
@@ -319,7 +327,7 @@ copy(char *argv[], enum op type, int fts
if (type != DIR_TO_DNE) {
p = find_last_component(curr->fts_path);
base = p - curr->fts_path;
-
+
if (!strcmp(&curr->fts_path[base],
".."))
base += 1;
@@ -435,7 +443,7 @@ copy(char *argv[], enum op type, int fts
break;
case S_IFBLK:
case S_IFCHR:
- if (Rflag) {
+ if (Rflag && !sflag) {
if ((cval = copy_special(curr->fts_statp,
!fts_dne(curr))) == 1)
rval = 1;
@@ -448,7 +456,7 @@ copy(char *argv[], enum op type, int fts
cval = 0;
break;
case S_IFIFO:
- if (Rflag) {
+ if (Rflag && !sflag) {
if ((cval = copy_fifo(curr->fts_statp,
!fts_dne(curr))) == 1)
rval = 1;
Index: bin/cp/extern.h
===================================================================
RCS file: /cvs/src/bin/cp/extern.h,v
retrieving revision 1.15
diff -u -p -u -r1.15 extern.h
--- bin/cp/extern.h 26 Dec 2015 18:11:43 -0000 1.15
+++ bin/cp/extern.h 23 May 2019 20:39:48 -0000
@@ -40,7 +40,7 @@ typedef struct {
extern PATH_T to;
extern uid_t myuid;
-extern int fflag, iflag, pflag;
+extern int fflag, iflag, lflag, pflag, sflag;
extern mode_t myumask;
extern char *__progname;
Index: bin/cp/utils.c
===================================================================
RCS file: /cvs/src/bin/cp/utils.c,v
retrieving revision 1.47
diff -u -p -u -r1.47 utils.c
--- bin/cp/utils.c 28 Jan 2019 18:58:42 -0000 1.47
+++ bin/cp/utils.c 23 May 2019 20:39:48 -0000
@@ -71,7 +71,8 @@ copy_file(FTSENT *entp, int exists)
err(1, "calloc");
}
- if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
+ if (!lflag && !sflag &&
+ (from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
warn("%s", entp->fts_path);
return (1);
}
@@ -97,12 +98,13 @@ copy_file(FTSENT *entp, int exists)
(void)close(from_fd);
return 2;
}
- to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
- } else
+ if (!lflag && !sflag)
+ to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
+ } else if (!lflag && !sflag)
to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
fs->st_mode & ~(S_ISTXT | S_ISUID | S_ISGID));
- if (to_fd == -1) {
+ if (!lflag && !sflag && to_fd == -1) {
warn("%s", to.p_path);
(void)close(from_fd);
return (1);
@@ -110,52 +112,69 @@ copy_file(FTSENT *entp, int exists)
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 && !sflag) {
+ /*
+ * 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
- /* XXX broken for 0-size mmap */
- if (fs->st_size <= 8 * 1048576) {
- if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
- MAP_FILE|MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
- warn("mmap: %s", entp->fts_path);
- rval = 1;
- } else {
- madvise(p, fs->st_size, MADV_SEQUENTIAL);
- if (write(to_fd, p, fs->st_size) != fs->st_size) {
- warn("%s", to.p_path);
+ /* XXX broken for 0-size mmap */
+ if (fs->st_size <= 8 * 1048576) {
+ if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
+ MAP_FILE|MAP_SHARED, from_fd,
+ (off_t)0)) == MAP_FAILED) {
+ warn("mmap: %s", entp->fts_path);
rval = 1;
+ } else {
+ madvise(p, fs->st_size, MADV_SEQUENTIAL);
+ if (write(to_fd, p,
+ fs->st_size) != fs->st_size) {
+ 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;
+ }
}
- /* Some systems don't unmap on close(2). */
- if (munmap(p, fs->st_size) < 0) {
+ } 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) {
+ 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, lseek(to_fd, 0,
+ SEEK_CUR));
+ if (rcount < 0) {
warn("%s", entp->fts_path);
rval = 1;
}
}
- } 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) {
- 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;
- }
+ } else if (lflag) {
+ if (link(entp->fts_path, to.p_path) == -1) {
+ warn("%s", to.p_path);
+ rval = 1;
}
- if (skipholes && rcount >= 0)
- rcount = ftruncate(to_fd, lseek(to_fd, 0, SEEK_CUR));
- if (rcount < 0) {
- warn("%s", entp->fts_path);
+ } else if (sflag) {
+ if (symlink(entp->fts_path, to.p_path) == -1) {
+ warn("%s", to.p_path);
rval = 1;
}
}
@@ -166,30 +185,34 @@ copy_file(FTSENT *entp, int exists)
return (1);
}
- if (pflag && setfile(fs, to_fd))
- rval = 1;
- /*
- * If the source was setuid or setgid, lose the bits unless the
- * copy is owned by the same user and group.
- */
+ if (!lflag && !sflag) {
+ if (pflag && setfile(fs, to_fd))
+ rval = 1;
+ /*
+ * If the source was setuid or setgid, lose the bits unless the
+ * copy is owned by the same user and group.
+ */
#define RETAINBITS \
(S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
- if (!pflag && !exists &&
- fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) {
- if (fstat(to_fd, &to_stat)) {
- warn("%s", to.p_path);
- rval = 1;
- } else if (fs->st_gid == to_stat.st_gid &&
- fchmod(to_fd, fs->st_mode & RETAINBITS & ~myumask)) {
+ if (!pflag && !exists &&
+ fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) {
+ if (fstat(to_fd, &to_stat)) {
+ warn("%s", to.p_path);
+ rval = 1;
+ } else if (fs->st_gid == to_stat.st_gid &&
+ fchmod(to_fd,
+ fs->st_mode & RETAINBITS & ~myumask)) {
+ warn("%s", to.p_path);
+ rval = 1;
+ }
+ }
+ if (close(to_fd)) {
warn("%s", to.p_path);
rval = 1;
}
}
+
(void)close(from_fd);
- if (close(to_fd)) {
- warn("%s", to.p_path);
- rval = 1;
- }
return (rval);
}
@@ -326,9 +349,10 @@ void
usage(void)
{
(void)fprintf(stderr,
- "usage: %s [-afipv] [-R [-H | -L | -P]] source target\n",
__progname);
+ "usage: %s [-afilpsv] [-R [-H | -L | -P]] source target\n",
+ __progname);
(void)fprintf(stderr,
- " %s [-afipv] [-R [-H | -L | -P]] source ... directory\n",
+ " %s [-afilpsv] [-R [-H | -L | -P]] source ... directory\n",
__progname);
exit(1);
}