Implement '-s' to copy as symlink, similar to the current -l link(2) handling.
This is also implemented in at least GNU coreutils cp. While here also improve the '-l' handling to not open(2) the source file as it does not actually need the descriptor. Sponsored by: EMC / Isilon Storage Division
This commit is contained in:
parent
14376e1f21
commit
7ea2450f42
13
bin/cp/cp.1
13
bin/cp/cp.1
@ -32,7 +32,7 @@
|
||||
.\" @(#)cp.1 8.3 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 15, 2013
|
||||
.Dd June 6, 2015
|
||||
.Dt CP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -45,7 +45,7 @@
|
||||
.Op Fl H | Fl L | Fl P
|
||||
.Oc
|
||||
.Op Fl f | i | n
|
||||
.Op Fl alpvx
|
||||
.Op Fl alpsvx
|
||||
.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 alpvx
|
||||
.Op Fl alpsvx
|
||||
.Ar source_file ... target_directory
|
||||
.Sh DESCRIPTION
|
||||
In the first synopsis form, the
|
||||
@ -179,6 +179,8 @@ If the source file has both its set-user-ID and set-group-ID bits on,
|
||||
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 hierarchy instead of copying.
|
||||
.It Fl v
|
||||
Cause
|
||||
.Nm
|
||||
@ -298,7 +300,10 @@ differ as they copy special files as normal
|
||||
files while recreating a hierarchy.
|
||||
.Pp
|
||||
The
|
||||
.Fl v
|
||||
.Fl l,
|
||||
.Fl s,
|
||||
.Fl v,
|
||||
.Fl x
|
||||
and
|
||||
.Fl n
|
||||
options are non-standard and their use in scripts is not recommended.
|
||||
|
13
bin/cp/cp.c
13
bin/cp/cp.c
@ -83,7 +83,7 @@ static char emptystring[] = "";
|
||||
|
||||
PATH_T to = { to.p_path, emptystring, "" };
|
||||
|
||||
int fflag, iflag, lflag, nflag, pflag, vflag;
|
||||
int fflag, iflag, lflag, nflag, pflag, sflag, vflag;
|
||||
static int Rflag, rflag;
|
||||
volatile sig_atomic_t info;
|
||||
|
||||
@ -102,7 +102,7 @@ main(int argc, char *argv[])
|
||||
|
||||
fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
|
||||
Hflag = Lflag = 0;
|
||||
while ((ch = getopt(argc, argv, "HLPRafilnprvx")) != -1)
|
||||
while ((ch = getopt(argc, argv, "HLPRafilnprsvx")) != -1)
|
||||
switch (ch) {
|
||||
case 'H':
|
||||
Hflag = 1;
|
||||
@ -145,6 +145,9 @@ main(int argc, char *argv[])
|
||||
rflag = Lflag = 1;
|
||||
Hflag = 0;
|
||||
break;
|
||||
case 's':
|
||||
sflag = 1;
|
||||
break;
|
||||
case 'v':
|
||||
vflag = 1;
|
||||
break;
|
||||
@ -163,6 +166,8 @@ main(int argc, char *argv[])
|
||||
|
||||
if (Rflag && rflag)
|
||||
errx(1, "the -R and -r options may not be specified together");
|
||||
if (lflag && sflag)
|
||||
errx(1, "the -l and -s options may not be specified together");
|
||||
if (rflag)
|
||||
Rflag = 1;
|
||||
if (Rflag) {
|
||||
@ -452,7 +457,7 @@ copy(char *argv[], enum op type, int fts_options)
|
||||
break;
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
if (Rflag) {
|
||||
if (Rflag && !sflag) {
|
||||
if (copy_special(curr->fts_statp, !dne))
|
||||
badcp = rval = 1;
|
||||
} else {
|
||||
@ -465,7 +470,7 @@ copy(char *argv[], enum op type, int fts_options)
|
||||
curr->fts_path);
|
||||
break;
|
||||
case S_IFIFO:
|
||||
if (Rflag) {
|
||||
if (Rflag && !sflag) {
|
||||
if (copy_fifo(curr->fts_statp, !dne))
|
||||
badcp = rval = 1;
|
||||
} else {
|
||||
|
@ -37,7 +37,7 @@ typedef struct {
|
||||
} PATH_T;
|
||||
|
||||
extern PATH_T to;
|
||||
extern int fflag, iflag, lflag, nflag, pflag, vflag;
|
||||
extern int fflag, iflag, lflag, nflag, pflag, sflag, vflag;
|
||||
extern volatile sig_atomic_t info;
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
@ -77,13 +77,15 @@ copy_file(const FTSENT *entp, int dne)
|
||||
ssize_t wcount;
|
||||
size_t wresid;
|
||||
off_t wtotal;
|
||||
int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0;
|
||||
int ch, checkch, from_fd, rcount, rval, to_fd;
|
||||
char *bufp;
|
||||
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
|
||||
char *p;
|
||||
#endif
|
||||
|
||||
if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
|
||||
from_fd = to_fd = -1;
|
||||
if (!lflag && !sflag &&
|
||||
(from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
|
||||
warn("%s", entp->fts_path);
|
||||
return (1);
|
||||
}
|
||||
@ -103,8 +105,8 @@ copy_file(const FTSENT *entp, int dne)
|
||||
if (nflag) {
|
||||
if (vflag)
|
||||
printf("%s not overwritten\n", to.p_path);
|
||||
(void)close(from_fd);
|
||||
return (1);
|
||||
rval = 1;
|
||||
goto done;
|
||||
} else if (iflag) {
|
||||
(void)fprintf(stderr, "overwrite %s? %s",
|
||||
to.p_path, YESNO);
|
||||
@ -112,9 +114,9 @@ copy_file(const FTSENT *entp, int dne)
|
||||
while (ch != '\n' && ch != EOF)
|
||||
ch = getchar();
|
||||
if (checkch != 'y' && checkch != 'Y') {
|
||||
(void)close(from_fd);
|
||||
(void)fprintf(stderr, "not overwritten\n");
|
||||
return (1);
|
||||
rval = 1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,28 +124,28 @@ copy_file(const FTSENT *entp, int dne)
|
||||
/* remove existing destination file name,
|
||||
* create a new file */
|
||||
(void)unlink(to.p_path);
|
||||
if (!lflag) {
|
||||
if (!lflag && !sflag) {
|
||||
to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
|
||||
fs->st_mode & ~(S_ISUID | S_ISGID));
|
||||
}
|
||||
} else if (!lflag) {
|
||||
} else if (!lflag && !sflag) {
|
||||
/* overwrite existing destination file name */
|
||||
to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
|
||||
}
|
||||
} else if (!lflag) {
|
||||
} else if (!lflag && !sflag) {
|
||||
to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
|
||||
fs->st_mode & ~(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);
|
||||
rval = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
rval = 0;
|
||||
|
||||
if (!lflag) {
|
||||
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
|
||||
@ -229,11 +231,16 @@ copy_file(const FTSENT *entp, int dne)
|
||||
rval = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (lflag) {
|
||||
if (link(entp->fts_path, to.p_path)) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
}
|
||||
} else if (sflag) {
|
||||
if (symlink(entp->fts_path, to.p_path)) {
|
||||
warn("%s", to.p_path);
|
||||
rval = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -243,7 +250,7 @@ copy_file(const FTSENT *entp, int dne)
|
||||
* to remove it if we created it and its length is 0.
|
||||
*/
|
||||
|
||||
if (!lflag) {
|
||||
if (!lflag && !sflag) {
|
||||
if (pflag && setfile(fs, to_fd))
|
||||
rval = 1;
|
||||
if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
|
||||
@ -254,8 +261,9 @@ copy_file(const FTSENT *entp, int dne)
|
||||
}
|
||||
}
|
||||
|
||||
(void)close(from_fd);
|
||||
|
||||
done:
|
||||
if (from_fd != -1)
|
||||
(void)close(from_fd);
|
||||
return (rval);
|
||||
}
|
||||
|
||||
@ -535,8 +543,8 @@ usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "%s\n%s\n",
|
||||
"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpvx] source_file target_file",
|
||||
" cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpvx] source_file ... "
|
||||
"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpsvx] source_file target_file",
|
||||
" cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpsvx] source_file ... "
|
||||
"target_directory");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user