summaryrefslogtreecommitdiff
path: root/src/lib/libast/path/pathexists.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libast/path/pathexists.c')
-rw-r--r--src/lib/libast/path/pathexists.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/lib/libast/path/pathexists.c b/src/lib/libast/path/pathexists.c
new file mode 100644
index 0000000..90b4ae7
--- /dev/null
+++ b/src/lib/libast/path/pathexists.c
@@ -0,0 +1,134 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2011 AT&T Intellectual Property *
+* and is licensed under the *
+* Eclipse Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.eclipse.org/org/documents/epl-v10.html *
+* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * return 1 if path exisis
+ * maintains a cache to minimize stat(2) calls
+ * path is modified in-place but restored on return
+ * path components checked in pairs to cut stat()'s
+ * in half by checking ENOTDIR vs. ENOENT
+ * case ignorance infection unavoidable here
+ */
+
+#include "lclib.h"
+
+#include <ls.h>
+#include <error.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;
+ int x;
+ struct stat st;
+ int (*cmp)(const char*, const char*);
+
+ static Tree_t tree;
+
+ t = &tree;
+ e = (c = *path) == '/' ? path + 1 : path;
+ cmp = strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'c') ? strcasecmp : strcmp;
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find))
+ sfprintf(sfstderr, "locale test %s\n", path);
+ while (c)
+ {
+ p = t;
+ for (s = e; *e && *e != '/'; e++);
+ c = *e;
+ *e = 0;
+ for (t = p->tree; t && (*cmp)(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;
+ if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find))
+ sfprintf(sfstderr, "locale stat %s\n", path);
+ 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;
+}