xref: /original-bsd/bin/cp/path.c (revision 1cfaf997)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)path.c	5.1 (Berkeley) 04/03/91";
10 #endif /* not lint */
11 
12 #include <sys/param.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include "cp.h"
16 
17 /*
18  * These functions manipulate paths in PATH_T structures.
19  *
20  * They eliminate multiple slashes in paths when they notice them,
21  * and keep the path non-slash terminated.
22  *
23  * Both path_set() and path_append() return 0 if the requested name
24  * would be too long.
25  */
26 
27 #define	STRIP_TRAILING_SLASH(p) { \
28 	while ((p)->p_end > (p)->p_path && (p)->p_end[-1] == '/') \
29 		*--(p)->p_end = 0; \
30 }
31 
32 /*
33  * Move specified string into path.  Convert "" to "." to handle BSD
34  * semantics for a null path.  Strip trailing slashes.
35  */
36 path_set(p, string)
37 	register PATH_T *p;
38 	char *string;
39 {
40 	if (strlen(string) > MAXPATHLEN) {
41 		(void)fprintf(stderr,
42 		    "%s: %s: name too long.\n", progname, string);
43 		return(0);
44 	}
45 
46 	(void)strcpy(p->p_path, string);
47 	p->p_end = p->p_path + strlen(p->p_path);
48 
49 	if (p->p_path == p->p_end) {
50 		*p->p_end++ = '.';
51 		*p->p_end = 0;
52 	}
53 
54 	STRIP_TRAILING_SLASH(p);
55 	return(1);
56 }
57 
58 /*
59  * Append specified string to path, inserting '/' if necessary.  Return a
60  * pointer to the old end of path for restoration.
61  */
62 char *
63 path_append(p, name, len)
64 	register PATH_T *p;
65 	char *name;
66 	int len;
67 {
68 	char *old;
69 
70 	old = p->p_end;
71 	if (len == -1)
72 		len = strlen(name);
73 
74 	/* The "+ 1" accounts for the '/' between old path and name. */
75 	if ((len + p->p_end - p->p_path + 1) > MAXPATHLEN) {
76 		(void)fprintf(stderr,
77 		    "%s: %s/%s: name too long.\n", progname, p->p_path, name);
78 		return(0);
79 	}
80 
81 	/*
82 	 * This code should always be executed, since paths shouldn't
83 	 * end in '/'.
84 	 */
85 	if (p->p_end[-1] != '/') {
86 		*p->p_end++ = '/';
87 		*p->p_end = 0;
88 	}
89 
90 	(void)strncat(p->p_end, name, len);
91 	p->p_end += len;
92 	*p->p_end = 0;
93 
94 	STRIP_TRAILING_SLASH(p);
95 	return(old);
96 }
97 
98 /*
99  * Restore path to previous value.  (As returned by path_append.)
100  */
101 void
102 path_restore(p, old)
103 	PATH_T *p;
104 	char *old;
105 {
106 	p->p_end = old;
107 	*p->p_end = 0;
108 }
109 
110 /*
111  * Return basename of path.
112  */
113 char *
114 path_basename(p)
115 	PATH_T *p;
116 {
117 	char *basename;
118 
119 	basename = rindex(p->p_path, '/');
120 	return(basename ? basename + 1 : p->p_path);
121 }
122