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* Common Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.opensource.org/licenses/cpl1.0.txt * 11* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 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 40typedef 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 48int 49pathexists(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