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