ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/path.C
(Generate patch)

Comparing deliantra/server/common/path.C (file contents):
Revision 1.1 by elmex, Sun Aug 13 17:16:00 2006 UTC vs.
Revision 1.3 by root, Thu Sep 14 22:34:00 2006 UTC

1/* $Id: path.C,v 1.1 2006/08/13 17:16:00 elmex Exp $ */
2
3#include <assert.h> 1#include <assert.h>
4#include <stdio.h> 2#include <stdio.h>
5#include <string.h> 3#include <string.h>
6#include <global.h> 4#include <global.h>
7 5
8#include "define.h" 6#include "define.h"
9#include "path.h" 7#include "path.h"
10 8
11 9
12#if 0 10#if 0
11
13/** 12/**
14 * Define DEBUG_PATH to enable debug output. 13 * Define DEBUG_PATH to enable debug output.
15 */ 14 */
16#define DEBUG_PATH 15# define DEBUG_PATH
17#endif 16#endif
18 17
19#if 0 18#if 0
19
20/** 20/**
21 * Define TEST_PATH to compile this file as a stand-alone self-test application 21 * Define TEST_PATH to compile this file as a stand-alone self-test application
22 * for the functions. 22 * for the functions.
23 */ 23 */
24#define TEST_PATH 24# define TEST_PATH
25 25
26#define LOG fprintf 26# define LOG fprintf
27#define llevDebug stderr 27# define llevDebug stderr
28#define llevError stderr 28# define llevError stderr
29#endif 29#endif
30 30
31 31
32char *
32char *path_combine(const char *src, const char *dst) { 33path_combine (const char *src, const char *dst)
34{
33 char *p; 35 char *p;
34 static char path[HUGE_BUF]; 36 static char path[HUGE_BUF];
35 37
36 if (*dst == '/') { 38 if (*dst == '/')
39 {
37 /* absolute destination path => ignore source path */ 40 /* absolute destination path => ignore source path */
38 strcpy(path, dst); 41 strcpy (path, dst);
39 } else { 42 }
43 else
44 {
40 /* relative destination path => add after last '/' of source */ 45 /* relative destination path => add after last '/' of source */
41 strcpy(path, src); 46 strcpy (path, src);
42 p = strrchr(path, '/'); 47 p = strrchr (path, '/');
43 if (p != NULL) { 48 if (p != NULL)
49 {
44 p++; 50 p++;
51 }
45 } else { 52 else
53 {
46 p = path; 54 p = path;
47 if (*src == '/') 55 if (*src == '/')
48 *p++ = '/'; 56 *p++ = '/';
49 } 57 }
50 strcpy(p, dst); 58 strcpy (p, dst);
51 } 59 }
52 60
53#if defined(DEBUG_PATH) 61#if defined(DEBUG_PATH)
54 LOG(llevDebug, "path_combine(%s, %s) = %s\n", src, dst, path); 62 LOG (llevDebug, "path_combine(%s, %s) = %s\n", src, dst, path);
55#endif 63#endif
56 return(path); 64 return (path);
57} 65}
58 66
67void
59void path_normalize(char *path) { 68path_normalize (char *path)
69{
60 char *p; /* points to the beginning of the path not yet processed; this is 70 char *p; /* points to the beginning of the path not yet processed; this is
61 either a path component or a path separator character */ 71 either a path component or a path separator character */
62 char *q; /* points to the end of the path component p points to */ 72 char *q; /* points to the end of the path component p points to */
63 char *w; /* points to the end of the already normalized path; w <= p is 73 char *w; /* points to the end of the already normalized path; w <= p is
64 maintained */ 74 maintained */
65 size_t len; /* length of current component (which p points to) */ 75 size_t len; /* length of current component (which p points to) */
66 76
67#if defined(DEBUG_PATH) 77#if defined(DEBUG_PATH)
68 LOG(llevDebug, "path_normalize: input '%s'\n", path); 78 LOG (llevDebug, "path_normalize: input '%s'\n", path);
69#endif 79#endif
70 80
71 p = path; 81 p = path;
72 w = p; 82 w = p;
73 while (*p != '\0') { 83 while (*p != '\0')
84 {
74 85
75 if (*p == '/') { 86 if (*p == '/')
87 {
76 if ((w == path && *path == '/') || (w > path && w[-1] != '/')) 88 if ((w == path && *path == '/') || (w > path && w[-1] != '/'))
77 *w++ = '/'; 89 *w++ = '/';
78 p++; 90 p++;
79 continue; 91 continue;
80 } 92 }
81 93
82 q = strchr(p, '/'); 94 q = strchr (p, '/');
83 if (q == NULL) 95 if (q == NULL)
84 q = p+strlen(p); 96 q = p + strlen (p);
85 len = q-p; 97 len = q - p;
86 assert(len > 0); 98 assert (len > 0);
87 99
88#if defined(DEBUG_PATH) 100#if defined(DEBUG_PATH)
89 LOG(llevDebug, "path_normalize: checking '%.*s'\n", (int)len, p); 101 LOG (llevDebug, "path_normalize: checking '%.*s'\n", (int) len, p);
90#endif 102#endif
91 103
92 if (len == 1 && *p == '.') { 104 if (len == 1 && *p == '.')
105 {
93 /* remove current component */ 106 /* remove current component */
107 }
94 } else if (len == 2 && memcmp(p, "..", 2) == 0) { 108 else if (len == 2 && memcmp (p, "..", 2) == 0)
109 {
95 if (w == path || (w == path+3 && memcmp(path, "../", 3) == 0)) { 110 if (w == path || (w == path + 3 && memcmp (path, "../", 3) == 0))
111 {
96 /* keep ".." at beginning of relative path ("../x" => "../x") */ 112 /* keep ".." at beginning of relative path ("../x" => "../x") */
97 memmove(w, p, len); 113 memmove (w, p, len);
98 w += len; 114 w += len;
99 } else if (w == path+1 && *path == '/') {
100 /* remove ".." at beginning of absolute path ("/../x" => "/x") */
101 } else {
102 /* remove both current component ".." and preceding one */
103 if (w > path && w[-1] == '/')
104 w--;
105 while (w > path && w[-1] != '/')
106 w--;
107 } 115 }
116 else if (w == path + 1 && *path == '/')
117 {
118 /* remove ".." at beginning of absolute path ("/../x" => "/x") */
119 }
108 } else { 120 else
121 {
122 /* remove both current component ".." and preceding one */
123 if (w > path && w[-1] == '/')
124 w--;
125 while (w > path && w[-1] != '/')
126 w--;
127 }
128 }
129 else
130 {
109 /* normal component ==> add it */ 131 /* normal component ==> add it */
110 memmove(w, p, len); 132 memmove (w, p, len);
111 w += len; 133 w += len;
112 } 134 }
113 135
114 p = q; 136 p = q;
115 137
116#if defined(DEBUG_PATH) 138#if defined(DEBUG_PATH)
117 LOG(llevDebug, "path_normalize: so far '%.*s'\n", (int)(w-path), path); 139 LOG (llevDebug, "path_normalize: so far '%.*s'\n", (int) (w - path), path);
118#endif 140#endif
119 } 141 }
120 142
121 /* remove trailing slashes, but keep the one at the start of the path */ 143 /* remove trailing slashes, but keep the one at the start of the path */
122 while (w > path+1 && w[-1] == '/') { 144 while (w > path + 1 && w[-1] == '/')
145 {
123 w--; 146 w--;
124 } 147 }
125 148
126 *w = '\0'; 149 *w = '\0';
127 150
128#if defined(DEBUG_PATH) 151#if defined(DEBUG_PATH)
129 LOG(llevDebug, "path_normalize: result '%s'\n", path); 152 LOG (llevDebug, "path_normalize: result '%s'\n", path);
130#endif 153#endif
131} 154}
132 155
156char *
133char *path_combine_and_normalize(const char *src, const char *dst) { 157path_combine_and_normalize (const char *src, const char *dst)
158{
134 char *path; 159 char *path;
135 160
136 path = path_combine(src, dst); 161 path = path_combine (src, dst);
137 path_normalize(path); 162 path_normalize (path);
138 return(path); 163 return (path);
139} 164}
140 165
141#if defined(TEST_PATH) 166#if defined(TEST_PATH)
167static void
142static void check_combine(const char *src, const char *dst, const char *exp) { 168check_combine (const char *src, const char *dst, const char *exp)
169{
143 const char *res; 170 const char *res;
144 171
145 fprintf(stderr, "path_combine(%s, %s) = ", src, dst); 172 fprintf (stderr, "path_combine(%s, %s) = ", src, dst);
146 res = path_combine(src, dst); 173 res = path_combine (src, dst);
147 fprintf(stderr, "%s", res); 174 fprintf (stderr, "%s", res);
148 if (strcmp(res, exp) != 0) { 175 if (strcmp (res, exp) != 0)
176 {
149 fprintf(stderr, ", should be %s\n", exp); 177 fprintf (stderr, ", should be %s\n", exp);
150 } else { 178 }
179 else
180 {
151 fprintf(stderr, " (OK)\n"); 181 fprintf (stderr, " (OK)\n");
152 } 182 }
153} 183}
154 184
185static void
155static void check_normalize(const char *path, const char *exp0) { 186check_normalize (const char *path, const char *exp0)
187{
156 char tmp[HUGE_BUF]; 188 char tmp[HUGE_BUF];
157 char exp[HUGE_BUF]; 189 char exp[HUGE_BUF];
158 190
159 strcpy(exp, exp0 == NULL ? path : exp0); 191 strcpy (exp, exp0 == NULL ? path : exp0);
160 192
161 strcpy(tmp, path); 193 strcpy (tmp, path);
162 fprintf(stderr, "path_normalize(%s) = ", tmp); 194 fprintf (stderr, "path_normalize(%s) = ", tmp);
163 path_normalize(tmp); 195 path_normalize (tmp);
164 fprintf(stderr, "%s", tmp); 196 fprintf (stderr, "%s", tmp);
165 if (strcmp(tmp, exp) != 0) { 197 if (strcmp (tmp, exp) != 0)
198 {
166 fprintf(stderr, ", should be %s\n", exp); 199 fprintf (stderr, ", should be %s\n", exp);
167 } else { 200 }
201 else
202 {
168 fprintf(stderr, " (OK)\n"); 203 fprintf (stderr, " (OK)\n");
169 } 204 }
170} 205}
171 206
207static void
172static void check_combine_and_normalize(const char *src, const char *dst, const char *exp) { 208check_combine_and_normalize (const char *src, const char *dst, const char *exp)
209{
173 const char *res; 210 const char *res;
174 211
175 fprintf(stderr, "path_combine_and_normalize(%s, %s) = ", src, dst); 212 fprintf (stderr, "path_combine_and_normalize(%s, %s) = ", src, dst);
176 res = path_combine_and_normalize(src, dst); 213 res = path_combine_and_normalize (src, dst);
177 fprintf(stderr, "%s", res); 214 fprintf (stderr, "%s", res);
178 if (strcmp(res, exp) != 0) { 215 if (strcmp (res, exp) != 0)
216 {
179 fprintf(stderr, ", should be %s\n", exp); 217 fprintf (stderr, ", should be %s\n", exp);
180 } else { 218 }
219 else
220 {
181 fprintf(stderr, " (OK)\n"); 221 fprintf (stderr, " (OK)\n");
182 } 222 }
183} 223}
184 224
185int main() { 225int
226main ()
227{
186 check_combine("/path1/file1", "/path2/file2", "/path2/file2"); 228 check_combine ("/path1/file1", "/path2/file2", "/path2/file2");
187 check_combine("path1/file1", "/path2/file2", "/path2/file2"); 229 check_combine ("path1/file1", "/path2/file2", "/path2/file2");
188 check_combine("/path1/file1", "path2/file2", "/path1/path2/file2"); 230 check_combine ("/path1/file1", "path2/file2", "/path1/path2/file2");
189 check_combine("path1/file1", "path2/file2", "path1/path2/file2"); 231 check_combine ("path1/file1", "path2/file2", "path1/path2/file2");
190 check_combine("/path1", "/path2", "/path2"); 232 check_combine ("/path1", "/path2", "/path2");
191 check_combine("path1", "/path2", "/path2"); 233 check_combine ("path1", "/path2", "/path2");
192 check_combine("/path1", "path2", "/path2"); 234 check_combine ("/path1", "path2", "/path2");
193 check_combine("path1", "path2", "path2"); 235 check_combine ("path1", "path2", "path2");
194 236
195 check_normalize("", NULL); 237 check_normalize ("", NULL);
196 check_normalize("/", NULL); 238 check_normalize ("/", NULL);
197 check_normalize("path1/file1", NULL); 239 check_normalize ("path1/file1", NULL);
198 check_normalize("/path1/file1", NULL); 240 check_normalize ("/path1/file1", NULL);
199 check_normalize("/path1//file1", "/path1/file1"); 241 check_normalize ("/path1//file1", "/path1/file1");
200 check_normalize("//path1/file1", "/path1/file1"); 242 check_normalize ("//path1/file1", "/path1/file1");
201 check_normalize("///////x////////y///////z////////", "/x/y/z"); 243 check_normalize ("///////x////////y///////z////////", "/x/y/z");
202 check_normalize("/a/b/../c/d/../e/../../f/g/../h", "/a/f/h"); 244 check_normalize ("/a/b/../c/d/../e/../../f/g/../h", "/a/f/h");
203 check_normalize("//a//b//..//c//d//..//e//..//..//f//g//..//h", "/a/f/h"); 245 check_normalize ("//a//b//..//c//d//..//e//..//..//f//g//..//h", "/a/f/h");
204 check_normalize("../a", NULL); 246 check_normalize ("../a", NULL);
205 check_normalize("a/../../b", "../b"); 247 check_normalize ("a/../../b", "../b");
206 check_normalize("/../a", "/a"); 248 check_normalize ("/../a", "/a");
207 check_normalize("/a/../../b", "/b"); 249 check_normalize ("/a/../../b", "/b");
208 check_normalize("./b/./c/.d/..e/./f", "b/c/.d/..e/f"); 250 check_normalize ("./b/./c/.d/..e/./f", "b/c/.d/..e/f");
209 check_normalize("/b/././././e", "/b/e"); 251 check_normalize ("/b/././././e", "/b/e");
210 check_normalize(".", ""); /* maybe the result should be "."? */ 252 check_normalize (".", ""); /* maybe the result should be "."? */
211 check_normalize("/.", "/"); 253 check_normalize ("/.", "/");
212 check_normalize("./", ""); /* maybe the result should be "."? */ 254 check_normalize ("./", ""); /* maybe the result should be "."? */
213 check_normalize("/a/b/..", "/a"); 255 check_normalize ("/a/b/..", "/a");
214 check_normalize("/a/b/../..", "/"); 256 check_normalize ("/a/b/../..", "/");
215 check_normalize("/a/b/../../..", "/"); 257 check_normalize ("/a/b/../../..", "/");
216 check_normalize("a/b/..", "a"); 258 check_normalize ("a/b/..", "a");
217 check_normalize("a/b/../..", ""); 259 check_normalize ("a/b/../..", "");
218 check_normalize("a/b/../../..", ".."); 260 check_normalize ("a/b/../../..", "..");
219 261
220 check_combine_and_normalize("/path1/file1", "/path2/file2", "/path2/file2"); 262 check_combine_and_normalize ("/path1/file1", "/path2/file2", "/path2/file2");
221 check_combine_and_normalize("path1/file1", "/path2/file2", "/path2/file2"); 263 check_combine_and_normalize ("path1/file1", "/path2/file2", "/path2/file2");
222 check_combine_and_normalize("/path1/file1", "path2/file2", "/path1/path2/file2"); 264 check_combine_and_normalize ("/path1/file1", "path2/file2", "/path1/path2/file2");
223 check_combine_and_normalize("/path1", "/path2", "/path2"); 265 check_combine_and_normalize ("/path1", "/path2", "/path2");
224 check_combine_and_normalize("path1", "/path2", "/path2"); 266 check_combine_and_normalize ("path1", "/path2", "/path2");
225 check_combine_and_normalize("/path1", "path2", "/path2"); 267 check_combine_and_normalize ("/path1", "path2", "/path2");
226 check_combine_and_normalize("/path1/file1/../u", "path2/x/../y/z/../a/b/..", "/path1/path2/y/a"); 268 check_combine_and_normalize ("/path1/file1/../u", "path2/x/../y/z/../a/b/..", "/path1/path2/y/a");
227 check_combine_and_normalize("/path1/file1", "/path2//file2", "/path2/file2"); 269 check_combine_and_normalize ("/path1/file1", "/path2//file2", "/path2/file2");
228 check_combine_and_normalize("/path1/file1", "/..", "/"); 270 check_combine_and_normalize ("/path1/file1", "/..", "/");
229 check_combine_and_normalize("/path1/file1", "../x", "/x"); 271 check_combine_and_normalize ("/path1/file1", "../x", "/x");
230 check_combine_and_normalize("/path1/file1", "../../../x", "/x"); 272 check_combine_and_normalize ("/path1/file1", "../../../x", "/x");
231 check_combine_and_normalize("/path1/file1", "/.x/..x/...x/x", "/.x/..x/...x/x"); 273 check_combine_and_normalize ("/path1/file1", "/.x/..x/...x/x", "/.x/..x/...x/x");
232 274
233 return(0); 275 return (0);
234} 276}
235#endif 277#endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines