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.2 by root, Sun Sep 10 16:00:23 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines