Crossfire Server, Trunk  R22047
porting.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
23 #include <assert.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #ifdef WIN32 /* ---win32 exclude/include headers */
32 #include "process.h"
33 #else
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <sys/wait.h>
37 #endif
38 
39 /* Has to be after above includes so we don't redefine some values */
40 #include "global.h"
41 
42 /*****************************************************************************
43  * File related functions
44  ****************************************************************************/
45 
46 #if 0
47 #ifndef HAVE_TEMPNAM
48 
53 char *tempnam(const char *dir, const char *pfx) {
55  static unsigned int curtmp;
56 
57  char *name;
58  pid_t pid = getpid();
59 
60 /* HURD does not have a hard limit, but we do */
61 #ifndef MAXPATHLEN
62 #define MAXPATHLEN 4096
63 #endif
64 
65  if (!pfx)
66  pfx = "cftmp.";
67 
68  /* This is a pretty simple method - put the pid as a hex digit and
69  * just keep incrementing the last digit. Check to see if the file
70  * already exists - if so, we'll just keep looking - eventually we should
71  * find one that is free.
72  */
73  if (dir != NULL) {
74  if (!(name = (char *)malloc(MAXPATHLEN)))
75  return(NULL);
76  do {
77  snprintf(name, MAXPATHLEN, "%s/%s%x.%u", dir, pfx, (unsigned int)pid, curtmp);
78  curtmp++;
79  } while (access(name, F_OK) != -1);
80  return(name);
81  }
82  return(NULL);
83 }
84 #endif
85 #endif
86 
110 FILE *tempnam_secure(const char *dir, const char *pfx, char **filename) {
111  char *tempname = NULL;
112  int fd;
113  int i;
114  FILE *file = NULL;
115  const int maxretry = 10;
116 
117  /* Limit number of retries to MAXRETRY */
118  for (i = 0; i < maxretry; i++) {
119  tempname = tempnam(dir, pfx);
120  if (!tempname)
121  return NULL;
122 
123  fd = open(tempname, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
124  if (fd != -1)
125  break;
126  if (errno == EEXIST)
127  LOG(llevError, "Created file detected in tempnam_secure. Someone hoping for a race condition?\n");
128  free(tempname);
129  }
130  /* Check that we successfully got an fd. */
131  if (fd == -1)
132  return NULL;
133 
134  file = fdopen(fd, "w+");
135  if (!file) {
136  LOG(llevError, "fdopen() failed in tempnam_secure()!\n");
137  free(tempname);
138  return NULL;
139  }
140 
141  *filename = tempname;
142  return file;
143 }
144 
156 void remove_directory(const char *path) {
157  DIR *dirp;
158  char buf[MAX_BUF];
159  struct stat statbuf;
160  int status;
161 
162  if ((dirp = opendir(path)) != NULL) {
163  struct dirent *de;
164 
165  for (de = readdir(dirp); de; de = readdir(dirp)) {
166  /* Don't remove '.' or '..' In theory we should do a better
167  * check for .., but the directories we are removing are fairly
168  * limited and should not have dot files in them.
169  */
170  if (de->d_name[0] == '.')
171  continue;
172 
173  /* Linux actually has a type field in the dirent structure,
174  * but that is not portable - stat should be portable
175  */
176  status = stat(de->d_name, &statbuf);
177  if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
178  snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name);
179  remove_directory(buf);
180  continue;
181  }
182  snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name);
183  if (unlink(buf)) {
184  LOG(llevError, "Unable to remove %s\n", path);
185  }
186  }
187  closedir(dirp);
188  }
189  if (rmdir(path)) {
190  LOG(llevError, "Unable to remove directory %s\n", path);
191  }
192 }
193 
194 /*****************************************************************************
195  * String related function
196  ****************************************************************************/
197 
198 #if 0
199 #ifndef HAVE_STRDUP
200 
203 char *strdup(const char *str) {
204  char *c = (char *)malloc(strlen(str)+1);
205  if (c != NULL)
206  strcpy(c, str);
207  return c;
208 }
209 #endif
210 
211 #ifndef HAVE_STRNCASECMP
212 
227 int strncasecmp(const char *s1, const char *s2, int n) {
228  register int c1, c2;
229 
230  while (*s1 && *s2 && n) {
231  c1 = tolower(*s1);
232  c2 = tolower(*s2);
233  if (c1 != c2)
234  return (c1-c2);
235  s1++;
236  s2++;
237  n--;
238  }
239  if (!n)
240  return (0);
241  return (int)(*s1-*s2);
242 }
243 #endif
244 
245 #ifndef HAVE_STRCASECMP
246 
259 int strcasecmp(const char *s1, const char *s2) {
260  register int c1, c2;
261 
262  while (*s1 && *s2) {
263  c1 = tolower(*s1);
264  c2 = tolower(*s2);
265  if (c1 != c2)
266  return (c1-c2);
267  s1++;
268  s2++;
269  }
270  if (*s1 == '\0' && *s2 == '\0')
271  return 0;
272  return (int)(*s1-*s2);
273 }
274 #endif
275 
276 #ifndef HAVE_STRCASESTR
277 
287 char *strcasestr(const char *s, const char *find) {
288  char c, sc;
289  size_t len;
290 
291  if ((c = *find++) != 0) {
292  c = tolower(c);
293  len = strlen(find);
294  do {
295  do {
296  if ((sc = *s++) == 0)
297  return NULL;
298  } while (tolower(sc) != c);
299  } while (strncasecmp(s, find, len) != 0);
300  s--;
301  }
302  return s;
303 }
304 #endif
305 #endif
306 
316 void make_path_to_file(const char *filename) {
317  char buf[MAX_BUF], *cp = buf;
318  struct stat statbuf;
319 
320  if (!filename || !*filename)
321  return;
322 
323  safe_strncpy(buf, filename, sizeof(buf));
324  while ((cp = strchr(cp+1, (int)'/'))) {
325  *cp = '\0';
326  if (stat(buf, &statbuf) || !S_ISDIR(statbuf.st_mode)) {
327  LOG(llevDebug, "Was not dir: %s\n", buf);
328  if (mkdir(buf, SAVE_DIR_MODE)) {
329  LOG(llevError, "Cannot mkdir %s: %s\n", buf, strerror(errno));
330  return;
331  }
332  }
333  *cp = '/';
334  }
335 }
336 
350 void safe_strcat(char *dest, const char *orig, size_t *curlen, size_t maxlen) {
351  assert(curlen != NULL);
352  assert(*curlen < maxlen);
353 #ifdef HAVE_STRLCAT
354  *curlen = strlcat(dest, orig, maxlen);
355 #else
356  if (*curlen == (maxlen-1))
357  return;
358  strncpy(dest+*curlen, orig, maxlen-*curlen-1);
359  dest[maxlen-1] = 0;
360  *curlen += strlen(orig);
361 #endif
362  if (*curlen > (maxlen-1))
363  *curlen = maxlen-1;
364 }
365 
366 #ifndef HAVE_STRLCPY
367 
370 size_t strlcpy(char *dst, const char *src, size_t size) {
371  strncpy(dst, src, size - 1);
372  dst[size - 1] = '\0';
373  return strlen(src);
374 }
375 #endif
StringBuffer * buf
Definition: readable.c:1591
void make_path_to_file(const char *filename)
Definition: porting.c:316
void remove_directory(const char *path)
Definition: porting.c:156
DIR * opendir(const char *)
Definition: win32.c:37
#define F_OK
Definition: win32.h:65
#define mkdir(__a, __b)
Definition: win32.h:57
Definition: win32.h:110
#define safe_strncpy
Definition: compat.h:23
Definition: win32.h:120
#define snprintf
Definition: win32.h:46
FILE * tempnam_secure(const char *dir, const char *pfx, char **filename)
Definition: porting.c:110
int strcasecmp(const char *s1, const char *s2)
#define getpid()
Definition: win32.h:58
#define MAXPATHLEN
Definition: win32.h:50
char d_name[_MAX_FNAME+1]
Definition: win32.h:114
#define MAX_BUF
Definition: define.h:35
int strncasecmp(const char *s1, const char *s2, int n)
#define tolower(C)
Definition: c_new.c:30
void safe_strcat(char *dest, const char *orig, size_t *curlen, size_t maxlen)
Definition: porting.c:350
#define unlink(__a)
Definition: win32.h:56
struct dirent * readdir(DIR *)
Definition: win32.c:75
int closedir(DIR *)
Definition: win32.c:108
#define S_ISDIR(x)
Definition: win32.h:69
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
#define SAVE_DIR_MODE
Definition: config.h:567
#define S_IRUSR
Definition: win32.h:91
#define S_IWUSR
Definition: win32.h:82
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:370