Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/path/pathcanon.c
1810 views
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 <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
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
224