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