1 /* $Source: /u/mark/src/pax/RCS/pathname.c,v $
2 *
3 * $Revision: 1.2 $
4 *
5 * pathname.c - directory/pathname support functions
6 *
7 * DESCRIPTION
8 *
9 * These functions provide directory/pathname support for PAX
10 *
11 * AUTHOR
12 *
13 * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
14 *
15 * Sponsored by The USENIX Association for public distribution.
16 *
17 * Copyright (c) 1989 Mark H. Colburn.
18 * All rights reserved.
19 *
20 * Redistribution and use in source and binary forms are permitted
21 * provided that the above copyright notice is duplicated in all such
22 * forms and that any documentation, advertising materials, and other
23 * materials related to such distribution and use acknowledge that the
24 * software was developed * by Mark H. Colburn and sponsored by The
25 * USENIX Association.
26 *
27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
29 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * $Log: pathname.c,v $
32 * Revision 1.2 89/02/12 10:05:13 mark
33 * 1.2 release fixes
34 *
35 * Revision 1.1 88/12/23 18:02:21 mark
36 * Initial revision
37 *
38 */
39
40 #ifndef lint
41 static char *ident = "$Id: pathname.c,v 1.2 89/02/12 10:05:13 mark Exp $";
42 static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
43 #endif /* ! lint */
44
45
46 /* Headers */
47
48 #include "pax.h"
49
50
51 /* dirneed - checks for the existance of directories and possibly create
52 *
53 * DESCRIPTION
54 *
55 * Dirneed checks to see if a directory of the name pointed to by name
56 * exists. If the directory does exist, then dirneed returns 0. If
57 * the directory does not exist and the f_dir_create flag is set,
58 * then dirneed will create the needed directory, recursively creating
59 * any needed intermediate directory.
60 *
61 * If f_dir_create is not set, then no directories will be created
62 * and a value of -1 will be returned if the directory does not
63 * exist.
64 *
65 * PARAMETERS
66 *
67 * name - name of the directory to create
68 *
69 * RETURNS
70 *
71 * Returns a 0 if the creation of the directory succeeded or if the
72 * directory already existed. If the f_dir_create flag was not set
73 * and the named directory does not exist, or the directory creation
74 * failed, a -1 will be returned to the calling routine.
75 */
76
77 #ifdef __STDC__
78
dirneed(char * name)79 int dirneed(char *name)
80
81 #else
82
83 int dirneed(name)
84 char *name;
85
86 #endif
87 {
88 char *cp;
89 char *last;
90 int ok;
91 static Stat sb;
92
93 last = (char *)NULL;
94 for (cp = name; *cp;) {
95 if (*cp++ == '/') {
96 last = cp;
97 }
98 }
99 if (last == (char *)NULL) {
100 return (STAT(".", &sb));
101 }
102 *--last = '\0';
103 ok = STAT(*name ? name : ".", &sb) == 0
104 ? ((sb.sb_mode & S_IFMT) == S_IFDIR)
105 : (f_dir_create && dirneed(name) == 0 && dirmake(name, &sb) == 0);
106 *last = '/';
107 return (ok ? 0 : -1);
108 }
109
110
111 /* nameopt - optimize a pathname
112 *
113 * DESCRIPTION
114 *
115 * Confused by "<symlink>/.." twistiness. Returns the number of final
116 * pathname elements (zero for "/" or ".") or -1 if unsuccessful.
117 *
118 * PARAMETERS
119 *
120 * char *begin - name of the path to optimize
121 *
122 * RETURNS
123 *
124 * Returns 0 if successful, non-zero otherwise.
125 *
126 */
127
128 #ifdef __STDC__
129
nameopt(char * begin)130 int nameopt(char *begin)
131
132 #else
133
134 int nameopt(begin)
135 char *begin;
136
137 #endif
138 {
139 char *name;
140 char *item;
141 int idx;
142 int absolute;
143 char *element[PATHELEM];
144
145 absolute = (*(name = begin) == '/');
146 idx = 0;
147 for (;;) {
148 if (idx == PATHELEM) {
149 warn(begin, "Too many elements");
150 return (-1);
151 }
152 while (*name == '/') {
153 ++name;
154 }
155 if (*name == '\0') {
156 break;
157 }
158 element[idx] = item = name;
159 while (*name && *name != '/') {
160 ++name;
161 }
162 if (*name) {
163 *name++ = '\0';
164 }
165 if (strcmp(item, "..") == 0) {
166 if (idx == 0) {
167 if (!absolute) {
168 ++idx;
169 }
170 } else if (strcmp(element[idx - 1], "..") == 0) {
171 ++idx;
172 } else {
173 --idx;
174 }
175 } else if (strcmp(item, ".") != 0) {
176 ++idx;
177 }
178 }
179 if (idx == 0) {
180 element[idx++] = absolute ? "" : ".";
181 }
182 element[idx] = (char *)NULL;
183 name = begin;
184 if (absolute) {
185 *name++ = '/';
186 }
187 for (idx = 0; item = element[idx]; ++idx, *name++ = '/') {
188 while (*item) {
189 *name++ = *item++;
190 }
191 }
192 *--name = '\0';
193 return (idx);
194 }
195
196
197 /* dirmake - make a directory
198 *
199 * DESCRIPTION
200 *
201 * Dirmake makes a directory with the appropritate permissions.
202 *
203 * PARAMETERS
204 *
205 * char *name - Name of directory make
206 * Stat *asb - Stat structure of directory to make
207 *
208 * RETURNS
209 *
210 * Returns zero if successful, -1 otherwise.
211 *
212 */
213
214 #ifdef __STDC__
215
dirmake(char * name,Stat * asb)216 int dirmake(char *name, Stat *asb)
217
218 #else
219
220 int dirmake(name, asb)
221 char *name;
222 Stat *asb;
223
224 #endif
225 {
226 if (mkdir(name, (int) (asb->sb_mode & S_IPOPN)) < 0) {
227 return (-1);
228 }
229 if (asb->sb_mode & S_IPEXE) {
230 chmod(name, (int) (asb->sb_mode & S_IPERM));
231 }
232 if (f_owner) {
233 chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
234 }
235 return (0);
236 }
237