#pragma prototyped
#include <ast.h>
#include <error.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
typedef struct Tree_s
{
struct Tree_s* next;
struct Tree_s* tree;
int mode;
char name[1];
} Tree_t;
int
pathexists(char* path, int mode)
{
register char* s;
register char* e;
register Tree_t* p;
register Tree_t* t;
register int c;
char* ee;
int cc = 0;
int x;
struct stat st;
static Tree_t tree;
t = &tree;
e = path + 1;
c = *path;
while (c)
{
p = t;
for (s = e; *e && *e != '/'; e++);
c = *e;
*e = 0;
for (t = p->tree; t && !streq(s, t->name); t = t->next);
if (!t)
{
if (!(t = newof(0, Tree_t, 1, strlen(s))))
{
*e = c;
return 0;
}
strcpy(t->name, s);
t->next = p->tree;
p->tree = t;
if (c)
{
*e = c;
for (s = ee = e + 1; *ee && *ee != '/'; ee++);
cc = *ee;
*ee = 0;
}
else
ee = 0;
x = stat(path, &st);
if (ee)
{
e = ee;
c = cc;
if (!x || errno == ENOENT)
t->mode = PATH_READ|PATH_EXECUTE;
if (!(p = newof(0, Tree_t, 1, strlen(s))))
{
*e = c;
return 0;
}
strcpy(p->name, s);
p->next = t->tree;
t->tree = p;
t = p;
}
if (x)
{
*e = c;
return 0;
}
if (st.st_mode & (S_IRUSR|S_IRGRP|S_IROTH))
t->mode |= PATH_READ;
if (st.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))
t->mode |= PATH_WRITE;
if (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
t->mode |= PATH_EXECUTE;
if (!S_ISDIR(st.st_mode))
t->mode |= PATH_REGULAR;
}
*e++ = c;
if (!t->mode || (c && (t->mode & PATH_REGULAR)))
return 0;
}
mode &= (PATH_READ|PATH_WRITE|PATH_EXECUTE|PATH_REGULAR);
return (t->mode & mode) == mode;
}