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 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 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 * in-place path name canonicalization -- preserves the logical view 28 * pointer to trailing 0 in path returned 29 * 30 * remove redundant .'s and /'s 31 * move ..'s to the front 32 * /.. preserved (for pdu and newcastle hacks) 33 * FS_3D handles ... 34 * if (flags&PATH_PHYSICAL) then symlinks resolved at each component 35 * if (flags&PATH_DOTDOT) then each .. checked for access 36 * if (flags&PATH_EXISTS) then path must exist at each component 37 * if (flags&PATH_VERIFIED(n)) then first n chars of path exist 38 * 39 * longer pathname possible if (flags&PATH_PHYSICAL) or FS_3D ... involved 40 * 0 returned on error and if (flags&(PATH_DOTDOT|PATH_EXISTS)) then path 41 * will contain the components following the failure point 42 */ 43 44 #define _AST_API_H 1 45 46 #include <ast.h> 47 #include <ls.h> 48 #include <fs3d.h> 49 #include <error.h> 50 51 char* 52 pathcanon(char* path, int flags) 53 { 54 return pathcanon_20100601(path, PATH_MAX, flags); 55 } 56 57 #undef _AST_API_H 58 59 #include <ast_api.h> 60 61 char* 62 pathcanon_20100601(char* path, size_t size, int flags) 63 { 64 register char* p; 65 register char* r; 66 register char* s; 67 register char* t; 68 register int dots; 69 char* phys; 70 char* v; 71 int loop; 72 int oerrno; 73 #if defined(FS_3D) 74 long visits = 0; 75 #endif 76 77 oerrno = errno; 78 dots = loop = 0; 79 phys = path; 80 v = path + ((flags >> 5) & 01777); 81 if (!size) 82 size = strlen(path) + 1; 83 if (*path == '/') 84 { 85 if (*(path + 1) == '/' && *astconf("PATH_LEADING_SLASHES", NiL, NiL) == '1') 86 do path++; while (*path == '/' && *(path + 1) == '/'); 87 if (!*(path + 1)) 88 return path + 1; 89 } 90 p = r = s = t = path; 91 for (;;) 92 switch (*t++ = *s++) 93 { 94 case '.': 95 dots++; 96 break; 97 case 0: 98 s--; 99 /*FALLTHROUGH*/ 100 case '/': 101 while (*s == '/') s++; 102 switch (dots) 103 { 104 case 1: 105 t -= 2; 106 break; 107 case 2: 108 if ((flags & (PATH_DOTDOT|PATH_EXISTS)) == PATH_DOTDOT && (t - 2) >= v) 109 { 110 struct stat st; 111 112 *(t - 2) = 0; 113 if (stat(phys, &st)) 114 { 115 strcpy(path, s); 116 return 0; 117 } 118 *(t - 2) = '.'; 119 } 120 #if PRESERVE_TRAILING_SLASH 121 if (t - 5 < r) r = t; 122 #else 123 if (t - 5 < r) 124 { 125 if (t - 4 == r) t = r + 1; 126 else r = t; 127 } 128 #endif 129 else for (t -= 5; t > r && *(t - 1) != '/'; t--); 130 break; 131 case 3: 132 #if defined(FS_3D) 133 { 134 char* x; 135 char* o; 136 int c; 137 138 o = t; 139 if ((t -= 5) <= path) t = path + 1; 140 c = *t; 141 *t = 0; 142 if (x = pathnext(phys, s - (*s != 0), &visits)) 143 { 144 r = path; 145 if (t == r + 1) x = r; 146 v = s = t = x; 147 } 148 else 149 { 150 *t = c; 151 t = o; 152 } 153 } 154 #else 155 r = t; 156 #endif 157 break; 158 default: 159 if ((flags & PATH_PHYSICAL) && loop < 32 && (t - 1) > path) 160 { 161 int c; 162 char buf[PATH_MAX]; 163 164 c = *(t - 1); 165 *(t - 1) = 0; 166 dots = pathgetlink(phys, buf, sizeof(buf)); 167 *(t - 1) = c; 168 if (dots > 0) 169 { 170 loop++; 171 strcpy(buf + dots, s - (*s != 0)); 172 if (*buf == '/') p = r = path; 173 v = s = t = p; 174 strcpy(p, buf); 175 } 176 else if (dots < 0 && errno == ENOENT) 177 { 178 if (flags & PATH_EXISTS) 179 { 180 strcpy(path, s); 181 return 0; 182 } 183 flags &= ~(PATH_PHYSICAL|PATH_DOTDOT); 184 } 185 dots = 4; 186 } 187 break; 188 } 189 if (dots >= 4 && (flags & PATH_EXISTS) && (t - 1) >= v && (t > path + 1 || t > path && *(t - 1) && *(t - 1) != '/')) 190 { 191 struct stat st; 192 193 *(t - 1) = 0; 194 if (stat(phys, &st)) 195 { 196 strcpy(path, s); 197 return 0; 198 } 199 v = t; 200 if (*s) *(t - 1) = '/'; 201 } 202 if (!*s) 203 { 204 if (t > path && !*(t - 1)) t--; 205 if (t == path) *t++ = '.'; 206 #if DONT_PRESERVE_TRAILING_SLASH 207 else if (t > path + 1 && *(t - 1) == '/') t--; 208 #else 209 else if ((s <= path || *(s - 1) != '/') && t > path + 1 && *(t - 1) == '/') t--; 210 #endif 211 *t = 0; 212 errno = oerrno; 213 return t; 214 } 215 dots = 0; 216 p = t; 217 break; 218 default: 219 dots = 4; 220 break; 221 } 222 } 223