Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Jun 2015 06:30:25 +0000 (UTC)
From:      Bryan Drewery <bdrewery@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r284106 - head/bin/cp
Message-ID:  <201506070630.t576UPOi040637@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bdrewery
Date: Sun Jun  7 06:30:25 2015
New Revision: 284106
URL: https://svnweb.freebsd.org/changeset/base/284106

Log:
  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

Modified:
  head/bin/cp/cp.1
  head/bin/cp/cp.c
  head/bin/cp/extern.h
  head/bin/cp/utils.c

Modified: head/bin/cp/cp.1
==============================================================================
--- head/bin/cp/cp.1	Sun Jun  7 03:49:41 2015	(r284105)
+++ head/bin/cp/cp.1	Sun Jun  7 06:30:25 2015	(r284106)
@@ -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
 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 nor
 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.

Modified: head/bin/cp/cp.c
==============================================================================
--- head/bin/cp/cp.c	Sun Jun  7 03:49:41 2015	(r284105)
+++ head/bin/cp/cp.c	Sun Jun  7 06:30:25 2015	(r284106)
@@ -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
 			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
 				    curr->fts_path);
 			break;
 		case S_IFIFO:
-			if (Rflag) {
+			if (Rflag && !sflag) {
 				if (copy_fifo(curr->fts_statp, !dne))
 					badcp = rval = 1;
 			} else {

Modified: head/bin/cp/extern.h
==============================================================================
--- head/bin/cp/extern.h	Sun Jun  7 03:49:41 2015	(r284105)
+++ head/bin/cp/extern.h	Sun Jun  7 06:30:25 2015	(r284106)
@@ -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

Modified: head/bin/cp/utils.c
==============================================================================
--- head/bin/cp/utils.c	Sun Jun  7 03:49:41 2015	(r284105)
+++ head/bin/cp/utils.c	Sun Jun  7 06:30:25 2015	(r284106)
@@ -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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506070630.t576UPOi040637>