Crossfire Server, Branches 1.12  R18729
path.c
Go to the documentation of this file.
1 /* $Id: path.c 11578 2009-02-23 22:02:27Z lalo $ */
2 
3 /*
4  CrossFire, A Multiplayer game for X-windows
5 
6  Copyright (C) 2006 Mark Wedel & Crossfire Development Team
7  Copyright (C) 1992 Frank Tore Johansen
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 
23  The authors can be reached via e-mail at crossfire-devel@real-time.com
24 */
25 
31 #include <assert.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <global.h>
35 
36 #include "define.h"
37 #include "path.h"
38 
39 #if 0
40 
43 #define DEBUG_PATH
44 #endif
45 
63 char *path_combine(const char *src, const char *dst, char *path, size_t size) {
64  char *p;
65 
66  if (*dst == '/') {
67  /* absolute destination path => ignore source path */
68  snprintf(path, size, "%s", dst);
69  } else {
70  /* relative destination path => add after last '/' of source */
71  snprintf(path, size, "%s", src);
72  p = strrchr(path, '/');
73  if (p != NULL) {
74  p++;
75  } else {
76  p = path;
77  if (*src == '/')
78  *p++ = '/';
79  }
80  snprintf(p, size-(p-path), "%s", dst);
81  }
82 
83 #if defined(DEBUG_PATH)
84  LOG(llevDebug, "path_combine(%s, %s) = %s\n", src, dst, path);
85 #endif
86  return(path);
87 }
88 
97 void path_normalize(char *path) {
98  char *p; /* points to the beginning of the path not yet processed; this is
99  either a path component or a path separator character */
100  char *q; /* points to the end of the path component p points to */
101  char *w; /* points to the end of the already normalized path; w <= p is
102  maintained */
103  size_t len; /* length of current component (which p points to) */
104 
105 #if defined(DEBUG_PATH)
106  LOG(llevDebug, "path_normalize: input '%s'\n", path);
107 #endif
108 
109  p = path;
110  w = p;
111  while (*p != '\0') {
112  if (*p == '/') {
113  if ((w == path && *path == '/') || (w > path && w[-1] != '/'))
114  *w++ = '/';
115  p++;
116  continue;
117  }
118 
119  q = strchr(p, '/');
120  if (q == NULL)
121  q = p+strlen(p);
122  len = q-p;
123  assert(len > 0);
124 
125 #if defined(DEBUG_PATH)
126  LOG(llevDebug, "path_normalize: checking '%.*s'\n", (int)len, p);
127 #endif
128 
129  if (len == 1 && *p == '.') {
130  /* remove current component */
131  } else if (len == 2 && memcmp(p, "..", 2) == 0) {
132  if (w == path || (w == path+3 && memcmp(path, "../", 3) == 0)) {
133  /* keep ".." at beginning of relative path ("../x" => "../x") */
134  memmove(w, p, len);
135  w += len;
136  } else if (w == path+1 && *path == '/') {
137  /* remove ".." at beginning of absolute path ("/../x" => "/x") */
138  } else {
139  /* remove both current component ".." and preceding one */
140  if (w > path && w[-1] == '/')
141  w--;
142  while (w > path && w[-1] != '/')
143  w--;
144  }
145  } else {
146  /* normal component ==> add it */
147  memmove(w, p, len);
148  w += len;
149  }
150 
151  p = q;
152 
153 #if defined(DEBUG_PATH)
154  LOG(llevDebug, "path_normalize: so far '%.*s'\n", (int)(w-path), path);
155 #endif
156  }
157 
158  /* remove trailing slashes, but keep the one at the start of the path */
159  while (w > path+1 && w[-1] == '/') {
160  w--;
161  }
162 
163  *w = '\0';
164 
165 #if defined(DEBUG_PATH)
166  LOG(llevDebug, "path_normalize: result '%s'\n", path);
167 #endif
168 }
169 
184 char *path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size) {
185  path_combine(src, dst, path, size);
186  path_normalize(path);
187  return(path);
188 }
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.c:184
void path_normalize(char *path)
Definition: path.c:97
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
char * path_combine(const char *src, const char *dst, char *path, size_t size)
Definition: path.c:63
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63