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