1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1985-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* Glenn Fowler <gsf@research.att.com> *
1N/A* David Korn <dgk@research.att.com> *
1N/A* Phong Vo <kpv@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#pragma prototyped
1N/A/*
1N/A * Glenn Fowler
1N/A * AT&T Research
1N/A *
1N/A * return 1 if path exisis
1N/A * maintains a cache to minimize stat(2) calls
1N/A * path is modified in-place but restored on return
1N/A * path components checked in pairs to cut stat()'s
1N/A * in half by checking ENOTDIR vs. ENOENT
1N/A * case ignorance infection unavoidable here
1N/A */
1N/A
1N/A#include "lclib.h"
1N/A
1N/A#include <ls.h>
1N/A#include <error.h>
1N/A
1N/Atypedef struct Tree_s
1N/A{
1N/A struct Tree_s* next;
1N/A struct Tree_s* tree;
1N/A int mode;
1N/A char name[1];
1N/A} Tree_t;
1N/A
1N/Aint
1N/Apathexists(char* path, int mode)
1N/A{
1N/A register char* s;
1N/A register char* e;
1N/A register Tree_t* p;
1N/A register Tree_t* t;
1N/A register int c;
1N/A char* ee;
1N/A int cc;
1N/A int x;
1N/A struct stat st;
1N/A int (*cmp)(const char*, const char*);
1N/A
1N/A static Tree_t tree;
1N/A
1N/A t = &tree;
1N/A e = (c = *path) == '/' ? path + 1 : path;
1N/A cmp = strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'c') ? strcasecmp : strcmp;
1N/A if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find))
1N/A sfprintf(sfstderr, "locale test %s\n", path);
1N/A while (c)
1N/A {
1N/A p = t;
1N/A for (s = e; *e && *e != '/'; e++);
1N/A c = *e;
1N/A *e = 0;
1N/A for (t = p->tree; t && (*cmp)(s, t->name); t = t->next);
1N/A if (!t)
1N/A {
1N/A if (!(t = newof(0, Tree_t, 1, strlen(s))))
1N/A {
1N/A *e = c;
1N/A return 0;
1N/A }
1N/A strcpy(t->name, s);
1N/A t->next = p->tree;
1N/A p->tree = t;
1N/A if (c)
1N/A {
1N/A *e = c;
1N/A for (s = ee = e + 1; *ee && *ee != '/'; ee++);
1N/A cc = *ee;
1N/A *ee = 0;
1N/A }
1N/A else
1N/A ee = 0;
1N/A if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find))
1N/A sfprintf(sfstderr, "locale stat %s\n", path);
1N/A x = stat(path, &st);
1N/A if (ee)
1N/A {
1N/A e = ee;
1N/A c = cc;
1N/A if (!x || errno == ENOENT)
1N/A t->mode = PATH_READ|PATH_EXECUTE;
1N/A if (!(p = newof(0, Tree_t, 1, strlen(s))))
1N/A {
1N/A *e = c;
1N/A return 0;
1N/A }
1N/A strcpy(p->name, s);
1N/A p->next = t->tree;
1N/A t->tree = p;
1N/A t = p;
1N/A }
1N/A if (x)
1N/A {
1N/A *e = c;
1N/A return 0;
1N/A }
1N/A if (st.st_mode & (S_IRUSR|S_IRGRP|S_IROTH))
1N/A t->mode |= PATH_READ;
1N/A if (st.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))
1N/A t->mode |= PATH_WRITE;
1N/A if (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
1N/A t->mode |= PATH_EXECUTE;
1N/A if (!S_ISDIR(st.st_mode))
1N/A t->mode |= PATH_REGULAR;
1N/A }
1N/A *e++ = c;
1N/A if (!t->mode || c && (t->mode & PATH_REGULAR))
1N/A return 0;
1N/A }
1N/A mode &= (PATH_READ|PATH_WRITE|PATH_EXECUTE|PATH_REGULAR);
1N/A return (t->mode & mode) == mode;
1N/A}