1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                   Phong Vo <kpv@research.att.com>                    *
20*b30d1939SAndy Fiddaman *                                                                      *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman #pragma prototyped
23*b30d1939SAndy Fiddaman /*
24*b30d1939SAndy Fiddaman  * Glenn Fowler
25*b30d1939SAndy Fiddaman  * AT&T Research
26*b30d1939SAndy Fiddaman  *
27*b30d1939SAndy Fiddaman  * return 1 if path exisis
28*b30d1939SAndy Fiddaman  * maintains a cache to minimize stat(2) calls
29*b30d1939SAndy Fiddaman  * path is modified in-place but restored on return
30*b30d1939SAndy Fiddaman  * path components checked in pairs to cut stat()'s
31*b30d1939SAndy Fiddaman  * in half by checking ENOTDIR vs. ENOENT
32*b30d1939SAndy Fiddaman  * case ignorance infection unavoidable here
33*b30d1939SAndy Fiddaman  */
34*b30d1939SAndy Fiddaman 
35*b30d1939SAndy Fiddaman #include "lclib.h"
36*b30d1939SAndy Fiddaman 
37*b30d1939SAndy Fiddaman #include <ls.h>
38*b30d1939SAndy Fiddaman #include <error.h>
39*b30d1939SAndy Fiddaman 
40*b30d1939SAndy Fiddaman typedef struct Tree_s
41*b30d1939SAndy Fiddaman {
42*b30d1939SAndy Fiddaman 	struct Tree_s*	next;
43*b30d1939SAndy Fiddaman 	struct Tree_s*	tree;
44*b30d1939SAndy Fiddaman 	int		mode;
45*b30d1939SAndy Fiddaman 	char		name[1];
46*b30d1939SAndy Fiddaman } Tree_t;
47*b30d1939SAndy Fiddaman 
48*b30d1939SAndy Fiddaman int
pathexists(char * path,int mode)49*b30d1939SAndy Fiddaman pathexists(char* path, int mode)
50*b30d1939SAndy Fiddaman {
51*b30d1939SAndy Fiddaman 	register char*		s;
52*b30d1939SAndy Fiddaman 	register char*		e;
53*b30d1939SAndy Fiddaman 	register Tree_t*	p;
54*b30d1939SAndy Fiddaman 	register Tree_t*	t;
55*b30d1939SAndy Fiddaman 	register int		c;
56*b30d1939SAndy Fiddaman 	char*			ee;
57*b30d1939SAndy Fiddaman 	int			cc;
58*b30d1939SAndy Fiddaman 	int			x;
59*b30d1939SAndy Fiddaman 	struct stat		st;
60*b30d1939SAndy Fiddaman 	int			(*cmp)(const char*, const char*);
61*b30d1939SAndy Fiddaman 
62*b30d1939SAndy Fiddaman 	static Tree_t		tree;
63*b30d1939SAndy Fiddaman 
64*b30d1939SAndy Fiddaman 	t = &tree;
65*b30d1939SAndy Fiddaman 	e = (c = *path) == '/' ? path + 1 : path;
66*b30d1939SAndy Fiddaman 	cmp = strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'c') ? strcasecmp : strcmp;
67*b30d1939SAndy Fiddaman 	if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find))
68*b30d1939SAndy Fiddaman 		sfprintf(sfstderr, "locale test %s\n", path);
69*b30d1939SAndy Fiddaman 	while (c)
70*b30d1939SAndy Fiddaman 	{
71*b30d1939SAndy Fiddaman 		p = t;
72*b30d1939SAndy Fiddaman 		for (s = e; *e && *e != '/'; e++);
73*b30d1939SAndy Fiddaman 		c = *e;
74*b30d1939SAndy Fiddaman 		*e = 0;
75*b30d1939SAndy Fiddaman 		for (t = p->tree; t && (*cmp)(s, t->name); t = t->next);
76*b30d1939SAndy Fiddaman 		if (!t)
77*b30d1939SAndy Fiddaman 		{
78*b30d1939SAndy Fiddaman 			if (!(t = newof(0, Tree_t, 1, strlen(s))))
79*b30d1939SAndy Fiddaman 			{
80*b30d1939SAndy Fiddaman 				*e = c;
81*b30d1939SAndy Fiddaman 				return 0;
82*b30d1939SAndy Fiddaman 			}
83*b30d1939SAndy Fiddaman 			strcpy(t->name, s);
84*b30d1939SAndy Fiddaman 			t->next = p->tree;
85*b30d1939SAndy Fiddaman 			p->tree = t;
86*b30d1939SAndy Fiddaman 			if (c)
87*b30d1939SAndy Fiddaman 			{
88*b30d1939SAndy Fiddaman 				*e = c;
89*b30d1939SAndy Fiddaman 				for (s = ee = e + 1; *ee && *ee != '/'; ee++);
90*b30d1939SAndy Fiddaman 				cc = *ee;
91*b30d1939SAndy Fiddaman 				*ee = 0;
92*b30d1939SAndy Fiddaman 			}
93*b30d1939SAndy Fiddaman 			else
94*b30d1939SAndy Fiddaman 				ee = 0;
95*b30d1939SAndy Fiddaman 			if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find))
96*b30d1939SAndy Fiddaman 				sfprintf(sfstderr, "locale stat %s\n", path);
97*b30d1939SAndy Fiddaman 			x = stat(path, &st);
98*b30d1939SAndy Fiddaman 			if (ee)
99*b30d1939SAndy Fiddaman 			{
100*b30d1939SAndy Fiddaman 				e = ee;
101*b30d1939SAndy Fiddaman 				c = cc;
102*b30d1939SAndy Fiddaman 				if (!x || errno == ENOENT)
103*b30d1939SAndy Fiddaman 					t->mode = PATH_READ|PATH_EXECUTE;
104*b30d1939SAndy Fiddaman 				if (!(p = newof(0, Tree_t, 1, strlen(s))))
105*b30d1939SAndy Fiddaman 				{
106*b30d1939SAndy Fiddaman 					*e = c;
107*b30d1939SAndy Fiddaman 					return 0;
108*b30d1939SAndy Fiddaman 				}
109*b30d1939SAndy Fiddaman 				strcpy(p->name, s);
110*b30d1939SAndy Fiddaman 				p->next = t->tree;
111*b30d1939SAndy Fiddaman 				t->tree = p;
112*b30d1939SAndy Fiddaman 				t = p;
113*b30d1939SAndy Fiddaman 			}
114*b30d1939SAndy Fiddaman 			if (x)
115*b30d1939SAndy Fiddaman 			{
116*b30d1939SAndy Fiddaman 				*e = c;
117*b30d1939SAndy Fiddaman 				return 0;
118*b30d1939SAndy Fiddaman 			}
119*b30d1939SAndy Fiddaman 			if (st.st_mode & (S_IRUSR|S_IRGRP|S_IROTH))
120*b30d1939SAndy Fiddaman 				t->mode |= PATH_READ;
121*b30d1939SAndy Fiddaman 			if (st.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))
122*b30d1939SAndy Fiddaman 				t->mode |= PATH_WRITE;
123*b30d1939SAndy Fiddaman 			if (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
124*b30d1939SAndy Fiddaman 				t->mode |= PATH_EXECUTE;
125*b30d1939SAndy Fiddaman 			if (!S_ISDIR(st.st_mode))
126*b30d1939SAndy Fiddaman 				t->mode |= PATH_REGULAR;
127*b30d1939SAndy Fiddaman 		}
128*b30d1939SAndy Fiddaman 		*e++ = c;
129*b30d1939SAndy Fiddaman 		if (!t->mode || c && (t->mode & PATH_REGULAR))
130*b30d1939SAndy Fiddaman 			return 0;
131*b30d1939SAndy Fiddaman 	}
132*b30d1939SAndy Fiddaman 	mode &= (PATH_READ|PATH_WRITE|PATH_EXECUTE|PATH_REGULAR);
133*b30d1939SAndy Fiddaman 	return (t->mode & mode) == mode;
134*b30d1939SAndy Fiddaman }
135