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