summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorsten Lockert <tholo@cvs.openbsd.org>1996-10-28 02:55:06 +0000
committerThorsten Lockert <tholo@cvs.openbsd.org>1996-10-28 02:55:06 +0000
commit4aca07f730ee34a1c9bfa3cf671d95ebb77d8603 (patch)
tree9856623a8f7f04e0c5987fbbd1d8a185ec3cbc2d
parent444b93f39ec7fc1e22431e1bf74cf3484d402ab1 (diff)
Don't strip off the last slash in the pathname "/". cp used to
stat the pathname "" in order to decide that the pathname "/" is a directory. This caused `cp kernel /' to fail if the kernel has the POSIX behaviour of not allowing the pathname "" to be an alias for ".". It presumably also caused `cp /etc/motd /' to fail in the unlikely event that "." is not stat'able. Be more careful about concatenating pathnames: don't check that the pathname fits until prefixes have been discarded (the check was too strict). Print the final pathname in error messages. Terminate the target directory name properly for error messages. Don't add a slash between components if there is already a slash. Fix from FreeBSD
-rw-r--r--bin/cp/cp.c35
1 files changed, 16 insertions, 19 deletions
diff --git a/bin/cp/cp.c b/bin/cp/cp.c
index e4d9df97d16..7b77747aa3e 100644
--- a/bin/cp/cp.c
+++ b/bin/cp/cp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cp.c,v 1.3 1996/08/02 12:40:51 deraadt Exp $ */
+/* $OpenBSD: cp.c,v 1.4 1996/10/28 02:55:05 tholo Exp $ */
/* $NetBSD: cp.c,v 1.14 1995/09/07 06:14:51 jtc Exp $ */
/*
@@ -47,7 +47,7 @@ static char copyright[] =
#if 0
static char sccsid[] = "@(#)cp.c 8.5 (Berkeley) 4/29/95";
#else
-static char rcsid[] = "$OpenBSD: cp.c,v 1.3 1996/08/02 12:40:51 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: cp.c,v 1.4 1996/10/28 02:55:05 tholo Exp $";
#endif
#endif /* not lint */
@@ -84,7 +84,7 @@ static char rcsid[] = "$OpenBSD: cp.c,v 1.3 1996/08/02 12:40:51 deraadt Exp $";
#include "extern.h"
#define STRIP_TRAILING_SLASH(p) { \
- while ((p).p_end > (p).p_path && (p).p_end[-1] == '/') \
+ while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/') \
*--(p).p_end = 0; \
}
@@ -257,7 +257,7 @@ copy(argv, type, fts_options)
FTS *ftsp;
FTSENT *curr;
int base, dne, nlen, rval;
- char *p;
+ char *p, *target_mid;
if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
err(1, NULL);
@@ -282,14 +282,6 @@ copy(argv, type, fts_options)
* source name to the target name.
*/
if (type != FILE_TO_FILE) {
- if ((curr->fts_namelen +
- to.target_end - to.p_path + 1) > MAXPATHLEN) {
- warnx("%s/%s: name too long (not copied)",
- to.p_path, curr->fts_name);
- rval = 1;
- continue;
- }
-
/*
* Need to remember the roots of traversals to create
* correct pathnames. If there's a directory being
@@ -321,15 +313,20 @@ copy(argv, type, fts_options)
} else
base = curr->fts_pathlen;
- if (to.target_end[-1] != '/') {
- *to.target_end = '/';
- *(to.target_end + 1) = 0;
- }
p = &curr->fts_path[base];
nlen = curr->fts_pathlen - base;
-
- (void)strncat(to.target_end + 1, p, nlen);
- to.p_end = to.target_end + nlen + 1;
+ target_mid = to.target_end;
+ if (*p != '/' && target_mid[-1] != '/')
+ *target_mid++ = '/';
+ *target_mid = 0;
+ if (target_mid - to.p_path + nlen > MAXPATHLEN) {
+ warnx("%s%s: name too long (not copied)",
+ to.p_path, p);
+ rval = 1;
+ continue;
+ }
+ (void)strncat(target_mid, p, nlen);
+ to.p_end = target_mid + nlen;
*to.p_end = 0;
STRIP_TRAILING_SLASH(to);
}