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

Comparing deliantra/server/common/porting.C (file contents):
Revision 1.2 by root, Tue Aug 29 08:01:35 2006 UTC vs.
Revision 1.9 by pippijn, Mon Dec 11 19:46:46 2006 UTC

1/*
2 * static char *rcsid_porting_c =
3 * "$Id: porting.C,v 1.2 2006/08/29 08:01:35 root Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
21 16
22 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 20
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 22*/
28 23
29/* This file contains various functions that are not really unique for 24/* This file contains various functions that are not really unique for
30 * crossfire, but rather provides what should be standard functions 25 * crossfire, but rather provides what should be standard functions
31 * for systems that do not have them. In this way, most of the 26 * for systems that do not have them. In this way, most of the
32 * nasty system dependent stuff is contained here, with the program 27 * nasty system dependent stuff is contained here, with the program
33 * calling these functions. 28 * calling these functions.
34 */ 29 */
35 30
36 31
37#ifdef WIN32 /* ---win32 exclude/include headers */
38#include "process.h"
39#define pid_t int /* we include it non global, because there is a redefinition in python.h */
40#else
41#include <ctype.h> 32#include <ctype.h>
42#include <sys/stat.h> 33#include <sys/stat.h>
43#include <sys/wait.h> 34#include <sys/wait.h>
44 35
45#include <sys/param.h> 36#include <sys/param.h>
46#include <stdio.h> 37#include <stdio.h>
47 38
48/* Need to pull in the HAVE_... values somehow */ 39/* Need to pull in the HAVE_... values somehow */
49/* win32 reminder: always put this in a ifndef win32 block */ 40
50#include <autoconf.h> 41#include <autoconf.h>
51#endif
52 42
53 43
54#ifdef HAVE_STDLIB_H 44#ifdef HAVE_STDLIB_H
55#include <stdlib.h> 45# include <stdlib.h>
56#endif 46#endif
57 47
58#ifdef HAVE_UNISTD_H 48#ifdef HAVE_UNISTD_H
59#include <unistd.h> 49# include <unistd.h>
60#endif 50#endif
61 51
62#include <stdarg.h> 52#include <stdarg.h>
53
63/* Has to be after above includes so we don't redefine some values */ 54/* Has to be after above includes so we don't redefine some values */
64#include "global.h" 55#include "global.h"
65 56
66static unsigned int curtmp = 0; 57static unsigned int curtmp = 0;
67
68/* This is a list of the suffix, uncompress and compress functions. Thus,
69 * if you have some other compress program you want to use, the only thing
70 * that needs to be done is to extended this.
71 * The first entry must be NULL - this is what is used for non
72 * compressed files.
73 */
74EXTERN char *uncomp[NROF_COMPRESS_METHODS][3] = {
75 {NULL, NULL, NULL},
76 {".Z", UNCOMPRESS, COMPRESS},
77 {".gz", GUNZIP, GZIP},
78 {".bz2", BUNZIP, BZIP}
79};
80 58
81/***************************************************************************** 59/*****************************************************************************
82 * File related functions 60 * File related functions
83 ****************************************************************************/ 61 ****************************************************************************/
84 62
85/* 63/*
86 * A replacement for the tempnam() function since it's not defined 64 * A replacement for the tempnam() function since it's not defined
87 * at some unix variants. 65 * at some unix variants.
88 */ 66 */
89 67
68char *
90char *tempnam_local(const char *dir, const char *pfx) 69tempnam_local (const char *dir, const char *pfx)
91{ 70{
92 char *name; 71 char *name;
93 pid_t pid=getpid(); 72 pid_t pid = getpid ();
94 73
95/* HURD does not have a hard limit, but we do */ 74/* HURD does not have a hard limit, but we do */
96#ifndef MAXPATHLEN 75#ifndef MAXPATHLEN
97#define MAXPATHLEN 4096 76# define MAXPATHLEN 4096
98#endif 77#endif
99 78
100 if (!(name = (char *) malloc(MAXPATHLEN))) 79 if (!(name = (char *) malloc (MAXPATHLEN)))
101 return(NULL); 80 return (NULL);
102 81
103 if (!pfx) 82 if (!pfx)
104 pfx = "cftmp."; 83 pfx = "cftmp.";
105 84
106 /* This is a pretty simple method - put the pid as a hex digit and 85 /* This is a pretty simple method - put the pid as a hex digit and
107 * just keep incrementing the last digit. Check to see if the file 86 * just keep incrementing the last digit. Check to see if the file
108 * already exists - if so, we'll just keep looking - eventually we should 87 * already exists - if so, we'll just keep looking - eventually we should
109 * find one that is free. 88 * find one that is free.
110 */ 89 */
111 if (dir!=NULL) { 90 if (dir != NULL)
91 {
92 do
112 do { 93 {
113#ifdef HAVE_SNPRINTF 94#ifdef HAVE_SNPRINTF
114 (void)snprintf(name, MAXPATHLEN, "%s/%s%hx.%d", dir, pfx, pid, curtmp); 95 (void) snprintf (name, MAXPATHLEN, "%s/%s%hx.%d", dir, pfx, pid, curtmp);
115#else 96#else
116 (void)sprintf(name,"%s/%s%hx%d", dir, pfx, pid, curtmp); 97 (void) sprintf (name, "%s/%s%hx%d", dir, pfx, pid, curtmp);
117#endif 98#endif
118 curtmp++; 99 curtmp++;
100 }
119 } while (access(name, F_OK)!=-1); 101 while (access (name, F_OK) != -1);
120 return(name); 102 return (name);
121 } 103 }
122 return(NULL); 104 return (NULL);
123} 105}
124 106
125 107
126 108
127/* This function removes everything in the directory. */ 109/* This function removes everything in the directory. */
110void
128void remove_directory(const char *path) 111remove_directory (const char *path)
129{ 112{
130 DIR *dirp; 113 DIR *dirp;
131 char buf[MAX_BUF]; 114 char buf[MAX_BUF];
132 struct stat statbuf; 115 struct stat statbuf;
133 int status; 116 int status;
134 117
135 if ((dirp=opendir(path))!=NULL) { 118 if ((dirp = opendir (path)) != NULL)
119 {
136 struct dirent *de; 120 struct dirent *de;
137 121
138 for (de=readdir(dirp); de; de = readdir(dirp)) { 122 for (de = readdir (dirp); de; de = readdir (dirp))
123 {
139 /* Don't remove '.' or '..' In theory we should do a better 124 /* Don't remove '.' or '..' In theory we should do a better
140 * check for .., but the directories we are removing are fairly 125 * check for .., but the directories we are removing are fairly
141 * limited and should not have dot files in them. 126 * limited and should not have dot files in them.
142 */ 127 */
143 if (de->d_name[0] == '.') continue; 128 if (de->d_name[0] == '.')
129 continue;
144 130
145 /* Linux actually has a type field in the dirent structure, 131 /* Linux actually has a type field in the dirent structure,
146 * but that is not portable - stat should be portable 132 * but that is not portable - stat should be portable
147 */ 133 */
148 status=stat(de->d_name, &statbuf); 134 status = stat (de->d_name, &statbuf);
149 if ((status!=-1) && (S_ISDIR(statbuf.st_mode))) { 135 if ((status != -1) && (S_ISDIR (statbuf.st_mode)))
136 {
150 sprintf(buf,"%s/%s", path, de->d_name); 137 sprintf (buf, "%s/%s", path, de->d_name);
151 remove_directory(buf); 138 remove_directory (buf);
152 continue; 139 continue;
153 } 140 }
154 sprintf(buf,"%s/%s", path, de->d_name); 141 sprintf (buf, "%s/%s", path, de->d_name);
155 if (unlink(buf)) { 142 if (unlink (buf))
143 {
156 LOG(llevError,"Unable to remove directory %s\n", path); 144 LOG (llevError, "Unable to remove directory %s\n", path);
157 } 145 }
158 } 146 }
159 closedir(dirp); 147 closedir (dirp);
160 } 148 }
161 if (rmdir(path)) { 149 if (rmdir (path))
150 {
162 LOG(llevError,"Unable to remove directory %s\n", path); 151 LOG (llevError, "Unable to remove directory %s\n", path);
163 } 152 }
164} 153}
165 154
166#if defined(sgi) 155#if defined(sgi)
167 156
168#include <stdio.h> 157# include <stdio.h>
169#include <stdlib.h> 158# include <stdlib.h>
170#include <string.h> 159# include <string.h>
171 160
172#define popen fixed_popen 161# define popen fixed_popen
173 162
163FILE *
174FILE *popen_local(const char *command, const char *type) 164popen_local (const char *command, const char *type)
175{ 165{
176 int fd[2]; 166 int fd[2];
177 int pd; 167 int pd;
178 FILE *ret; 168 FILE *ret;
169
179 if (!strcmp(type,"r")) 170 if (!strcmp (type, "r"))
171 pd = STDOUT_FILENO;
172 else if (!strcmp (type, "w"))
173 pd = STDIN_FILENO;
174 else
175 return NULL;
176
177 if (pipe (fd) != -1)
178 {
179 switch (fork ())
180 { 180 {
181 pd=STDOUT_FILENO; 181 case -1:
182 close (fd[0]);
183 close (fd[1]);
184 break;
185 case 0:
186 close (fd[0]);
187 if ((fd[1] == pd) || (dup2 (fd[1], pd) == pd))
188 {
189 if (fd[1] != pd)
190 {
191 close (fd[1]);
192 }
193 execl ("/bin/sh", "sh", "-c", command, NULL);
194 close (pd);
195 }
196 _exit (1);
197 break;
198 default:
199 close (fd[1]);
200 if (ret = fdopen (fd[0], type))
201 {
202 return ret;
203 }
204 close (fd[0]);
205 break;
182 } 206 }
183 else if (!strcmp(type,"w")) 207 }
184 {
185 pd=STDIN_FILENO;
186 }
187 else
188 {
189 return NULL;
190 }
191 if (pipe(fd)!=-1)
192 {
193 switch (fork())
194 {
195 case -1:
196 close(fd[0]);
197 close(fd[1]);
198 break;
199 case 0:
200 close(fd[0]);
201 if ((fd[1]==pd)||(dup2(fd[1],pd)==pd))
202 {
203 if (fd[1]!=pd)
204 {
205 close(fd[1]);
206 }
207 execl("/bin/sh","sh","-c",command,NULL);
208 close(pd);
209 }
210 exit(1);
211 break;
212 default:
213 close(fd[1]);
214 if (ret=fdopen(fd[0],type))
215 {
216 return ret;
217 }
218 close(fd[0]);
219 break;
220 }
221 }
222 return NULL; 208 return NULL;
223} 209}
224 210
225#endif /* defined(sgi) */ 211#endif /* defined(sgi) */
226 212
227 213
228/***************************************************************************** 214/*****************************************************************************
229 * String related function 215 * String related function
230 ****************************************************************************/ 216 ****************************************************************************/
231 217
232
233
234/* 218/*
235 * A replacement of strdup(), since it's not defined at some 219 * A replacement of strdup(), since it's not defined at some
236 * unix variants. 220 * unix variants.
237 */ 221 */
222char *
238char *strdup_local(const char *str) { 223strdup_local (const char *str)
224{
239 char *c=(char *)malloc(sizeof(char)*(strlen(str)+1)); 225 char *c = (char *) malloc (sizeof (char) * (strlen (str) + 1));
226
240 strcpy(c,str); 227 strcpy (c, str);
241 return c; 228 return c;
242} 229}
243 230
244 231
245#define DIGIT(x) (isdigit(x) ? (x) - '0' : \ 232#define DIGIT(x) (isdigit(x) ? (x) - '0' : \
246islower (x) ? (x) + 10 - 'a' : (x) + 10 - 'A') 233islower (x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
247#define MBASE ('z' - 'a' + 1 + 10) 234#define MBASE ('z' - 'a' + 1 + 10)
248 235
249/* This seems to be lacking on some system */ 236/* This seems to be lacking on some system */
250#if !defined(HAVE_STRNCASECMP) 237#if !defined(HAVE_STRNCASECMP)
238int
251int strncasecmp(const char *s1, const char *s2, int n) 239strncasecmp (const char *s1, const char *s2, int n)
252{ 240{
253 register int c1, c2; 241 register int c1, c2;
254 242
255 while (*s1 && *s2 && n) { 243 while (*s1 && *s2 && n)
244 {
256 c1 = tolower(*s1); 245 c1 = tolower (*s1);
257 c2 = tolower(*s2); 246 c2 = tolower (*s2);
258 if (c1 != c2) 247 if (c1 != c2)
259 return (c1 - c2); 248 return (c1 - c2);
260 s1++; 249 s1++;
261 s2++; 250 s2++;
262 n--; 251 n--;
263 } 252 }
264 if (!n) 253 if (!n)
265 return(0); 254 return (0);
266 return (int) (*s1 - *s2); 255 return (int) (*s1 - *s2);
267} 256}
268#endif 257#endif
269 258
270#if !defined(HAVE_STRCASECMP) 259#if !defined(HAVE_STRCASECMP)
260int
271int strcasecmp(const char *s1, const char*s2) 261strcasecmp (const char *s1, const char *s2)
272{ 262{
273 register int c1, c2; 263 register int c1, c2;
274 264
275 while (*s1 && *s2) { 265 while (*s1 && *s2)
266 {
276 c1 = tolower(*s1); 267 c1 = tolower (*s1);
277 c2 = tolower(*s2); 268 c2 = tolower (*s2);
278 if (c1 != c2) 269 if (c1 != c2)
279 return (c1 - c2); 270 return (c1 - c2);
280 s1++; 271 s1++;
281 s2++; 272 s2++;
282 } 273 }
283 if (*s1=='\0' && *s2=='\0') 274 if (*s1 == '\0' && *s2 == '\0')
284 return 0; 275 return 0;
285 return (int) (*s1 - *s2); 276 return (int) (*s1 - *s2);
286} 277}
287#endif 278#endif
288 279
280char *
289char *strcasestr_local(const char *s, const char *find) 281strcasestr_local (const char *s, const char *find)
290{ 282{
291 char c, sc; 283 char c, sc;
292 size_t len; 284 size_t len;
293 285
294 if ((c = *find++) != 0) { 286 if ((c = *find++) != 0)
287 {
295 c = tolower(c); 288 c = tolower (c);
296 len = strlen(find); 289 len = strlen (find);
290 do
297 do { 291 {
292 do
298 do { 293 {
299 if ((sc = *s++) == 0) 294 if ((sc = *s++) == 0)
300 return NULL; 295 return NULL;
296 }
301 } while (tolower(sc) != c); 297 while (tolower (sc) != c);
298 }
302 } while (strncasecmp(s, find, len) != 0); 299 while (strncasecmp (s, find, len) != 0);
303 s--; 300 s--;
304 } 301 }
305 return (char *)s; 302 return (char *) s;
306} 303}
307 304
308#if !defined(HAVE_SNPRINTF) 305#if !defined(HAVE_SNPRINTF)
309 306
307int
310int snprintf(char *dest, int max, const char *format, ...) 308snprintf (char *dest, int max, const char *format, ...)
311{ 309{
312 va_list var; 310 va_list var;
313 int ret; 311 int ret;
314 312
315 va_start(var, format); 313 va_start (var, format);
316 ret = vsprintf(dest, format, var); 314 ret = vsprintf (dest, format, var);
317 va_end(var); 315 va_end (var);
318 if (ret > max) abort(); 316 if (ret > max)
317 abort ();
319 318
320 return ret; 319 return ret;
321} 320}
322#endif 321#endif
323 322
324
325/* This takes an err number and returns a string with a description of
326 * the error.
327 */
328char *strerror_local(int errnum)
329{
330#if defined(HAVE_STRERROR)
331 return(strerror(errnum));
332#else
333 return("strerror_local not implemented");
334#endif
335}
336 323
337/* 324/*
338 * Based on (n+1)^2 = n^2 + 2n + 1 325 * Based on (n+1)^2 = n^2 + 2n + 1
339 * given that 1^2 = 1, then 326 * given that 1^2 = 1, then
340 * 2^2 = 1 + (2 + 1) = 1 + 3 = 4 327 * 2^2 = 1 + (2 + 1) = 1 + 3 = 4
343 * ... 330 * ...
344 * In other words, a square number can be express as the sum of the 331 * In other words, a square number can be express as the sum of the
345 * series n^2 = 1 + 3 + ... + (2n-1) 332 * series n^2 = 1 + 3 + ... + (2n-1)
346 */ 333 */
347int 334int
348isqrt(int n) 335isqrt (int n)
349{ 336{
350 int result, sum, prev; 337 int result, sum, prev;
338
351 result = 0; 339 result = 0;
352 prev = sum = 1; 340 prev = sum = 1;
353 while (sum <= n) { 341 while (sum <= n)
342 {
354 prev += 2; 343 prev += 2;
355 sum += prev; 344 sum += prev;
356 ++result; 345 ++result;
357 } 346 }
358 return result; 347 return result;
359} 348}
360 349
361 350
362/* 351/*
363 * returns a char-pointer to a static array, in which a representation 352 * returns a char-pointer to a static array, in which a representation
364 * of the decimal number given will be stored. 353 * of the decimal number given will be stored.
365 */ 354 */
366 355
356char *
367char *ltostr10(signed long n) { 357ltostr10 (signed long n)
358{
368 static char buf[12]; /* maximum size is n=-2 billion, i.e. 11 characters+1 359 static char buf[12]; /* maximum size is n=-2 billion, i.e. 11 characters+1
369 character for the trailing nul character */ 360 character for the trailing nul character */
370 snprintf(buf, sizeof(buf), "%ld", n); 361 snprintf (buf, sizeof (buf), "%ld", n);
371 return buf; 362 return buf;
372} 363}
364
365char *
373char *doubletostr10(double v){ 366doubletostr10 (double v)
367{
374 static char tbuf[200]; 368 static char tbuf[200];
369
375 sprintf(tbuf,"%f",v); 370 sprintf (tbuf, "%f", v);
376 return tbuf; 371 return tbuf;
377}
378
379/*
380 * A fast routine which appends the name and decimal number specified
381 * to the given buffer.
382 * Could be faster, though, if the strcat()s at the end could be changed
383 * into alternate strcat which returned a pointer to the _end_, not the
384 * start!
385 *
386 * Hey good news, it IS faster now, according to changes in get_ob_diff
387 * Completly redone prototype and made define in loader.l. See changes there.
388 * Didn't touch those for speed reason (don't use them anymore) .
389 * Tchize
390 */
391
392void save_long(char *buf, char *name, long n) {
393 char buf2[MAX_BUF];
394 strcpy(buf2,name);
395 strcat(buf2," ");
396 strcat(buf2,ltostr10(n));
397 strcat(buf2,"\n");
398 strcat(buf,buf2);
399}
400
401
402
403void save_long_long(char *buf, char *name, sint64 n) {
404 char buf2[MAX_BUF];
405
406#ifndef WIN32
407 sprintf(buf2,"%s %lld\n", name, n);
408#else
409 sprintf(buf2,"%s %I64d\n", name, n);
410#endif
411 strcat(buf,buf2);
412}
413
414/**
415 * Open and possibly uncompress a file.
416 *
417 * @param ext the extension if the file is compressed.
418 *
419 * @param uncompressor the command to uncompress the file if the file is
420 * compressed.
421 *
422 * @param name the base file name without compression extension
423 *
424 * @param flag only used for compressed files: if set, uncompress and open the
425 * file; if unset, uncompress the file via pipe
426 *
427 * @param *compressed set to zero if the file was uncompressed
428 */
429static FILE *open_and_uncompress_file(const char *ext, const char *uncompressor, const char *name, int flag, int *compressed) {
430 struct stat st;
431 char buf[MAX_BUF];
432 char buf2[MAX_BUF];
433 int ret;
434
435 if (ext == NULL) {
436 ext = "";
437 }
438
439 if (strlen(name)+strlen(ext) >= sizeof(buf)) {
440 errno = ENAMETOOLONG; /* File name too long */
441 return NULL;
442 }
443 sprintf(buf, "%s%s", name, ext);
444
445 if (stat(buf, &st) != 0) {
446 return NULL;
447 }
448
449 if (!S_ISREG(st.st_mode)) {
450 errno = EISDIR; /* Not a regular file */
451 return NULL;
452 }
453
454 if (uncompressor == NULL) {
455 /* open without uncompression */
456
457 return fopen(buf, "r");
458 }
459
460 /* The file name buf (and its substring name) is passed as an argument to a
461 * shell command, therefore check for characters that could confuse the
462 * shell.
463 */
464 if (strpbrk(buf, "'\\\r\n") != NULL) {
465 errno = ENOENT; /* Pretend the file does not exist */
466 return NULL;
467 }
468
469 if (!flag) {
470 /* uncompress via pipe */
471
472 if (strlen(uncompressor)+4+strlen(buf)+1 >= sizeof(buf2)) {
473 errno = ENAMETOOLONG; /* File name too long */
474 return NULL;
475 }
476 sprintf(buf2, "%s < '%s'", uncompressor, buf);
477
478 return popen(buf2, "r");
479 }
480
481 /* remove compression from file, then open file */
482
483 if (stat(name, &st) == 0 && !S_ISREG(st.st_mode)) {
484 errno = EISDIR;
485 return NULL;
486 }
487
488 if (strlen(uncompressor)+4+strlen(buf)+5+strlen(name)+1 >= sizeof(buf2)) {
489 errno = ENAMETOOLONG; /* File name too long */
490 return NULL;
491 }
492 sprintf(buf2, "%s < '%s' > '%s'", uncompressor, buf, name);
493
494 ret = system(buf2);
495 if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
496 LOG(llevError, "system(%s) returned %d\n", buf2, ret);
497 errno = ENOENT;
498 return NULL;
499 }
500
501 unlink(buf); /* Delete the original */
502 *compressed = 0; /* Change to "uncompressed file" */
503 chmod(name, st.st_mode); /* Copy access mode from compressed file */
504
505 return fopen(name, "r");
506} 372}
507 373
508/** 374/**
509 * open_and_uncompress() first searches for the original filename. If it exist, 375 * open_and_uncompress() first searches for the original filename. If it exist,
510 * then it opens it and returns the file-pointer. 376 * then it opens it and returns the file-pointer.
511 * 377 */
512 * If not, it does two things depending on the flag. If the flag is set, it 378FILE *
513 * tries to create the original file by appending a compression suffix to name
514 * and uncompressing it. If the flag is not set, it creates a pipe that is used
515 * for reading the file (NOTE - you can not use fseek on pipes).
516 *
517 * The compressed pointer is set to nonzero if the file is compressed (and
518 * thus, fp is actually a pipe.) It returns 0 if it is a normal file.
519 */
520FILE *open_and_uncompress(const char *name, int flag, int *compressed) { 379open_and_uncompress (const char *name, int flag, int *compressed)
521 size_t i; 380{
522 FILE *fp;
523
524 for (i = 0; i < NROF_COMPRESS_METHODS; i++) {
525 *compressed = i; 381 *compressed = 0;
526 fp = open_and_uncompress_file(uncomp[i][0], uncomp[i][1], name, flag, compressed); 382 return fopen (name, "r");
527 if (fp != NULL) {
528 return fp;
529 }
530 }
531
532 errno = ENOENT;
533 return NULL;
534} 383}
535 384
536/* 385/*
537 * See open_and_uncompress(). 386 * See open_and_uncompress().
538 */ 387 */
539 388
389void
540void close_and_delete(FILE *fp, int compressed) { 390close_and_delete (FILE * fp, int compressed)
541 if (compressed) 391{
542 pclose(fp);
543 else
544 fclose(fp); 392 fclose (fp);
545} 393}
546 394
547/* 395/*
548 * If any directories in the given path doesn't exist, they are created. 396 * If any directories in the given path doesn't exist, they are created.
549 */ 397 */
550 398
399void
551void make_path_to_file (char *filename) 400make_path_to_file (char *filename)
552{ 401{
553 char buf[MAX_BUF], *cp = buf; 402 char buf[MAX_BUF], *cp = buf;
554 struct stat statbuf; 403 struct stat statbuf;
555 404
556 if (!filename || !*filename) 405 if (!filename || !*filename)
557 return; 406 return;
558 strcpy (buf, filename); 407 strcpy (buf, filename);
559 408
560 while ((cp = strchr (cp + 1, (int) '/'))) { 409 while ((cp = strchr (cp + 1, (int) '/')))
410 {
561 *cp = '\0'; 411 *cp = '\0';
562 if (stat(buf, &statbuf) || !S_ISDIR (statbuf.st_mode)) { 412 if (stat (buf, &statbuf) || !S_ISDIR (statbuf.st_mode))
413 {
563 if (mkdir (buf, SAVE_DIR_MODE)) { 414 if (mkdir (buf, SAVE_DIR_MODE))
415 {
564 LOG(llevError, "Cannot mkdir %s: %s\n", buf, strerror_local(errno)); 416 LOG (llevError, "Cannot mkdir %s: %s\n", buf, strerror (errno));
565 return; 417 return;
566 } 418 }
567 } 419 }
568 *cp = '/'; 420 *cp = '/';
569 } 421 }
570} 422}
571

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines