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