Crossfire Server, Trunk  1.75.0
porting.cpp
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 #ifndef CF_MXE_CROSS_COMPILE
35 #include <sys/param.h>
36 #include <sys/stat.h>
37 #include <sys/wait.h>
38 #endif
39 #endif
40 
41 /* Has to be after above includes so we don't redefine some values */
42 #include "global.h"
43 
44 /*****************************************************************************
45  * File related functions
46  ****************************************************************************/
47 
71 FILE *tempnam_secure(const char *dir, const char *pfx, char **filename) {
72  char *tempname = NULL;
73  int fd;
74  int i;
75  FILE *file = NULL;
76  const int maxretry = 10;
77 
78  /* Limit number of retries to MAXRETRY */
79  for (i = 0; i < maxretry; i++) {
80  tempname = tempnam(dir, pfx);
81  if (!tempname)
82  return NULL;
83 
84  fd = open(tempname, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
85  if (fd != -1)
86  break;
87  if (errno == EEXIST)
88  LOG(llevError, "Created file detected in tempnam_secure. Someone hoping for a race condition?\n");
89  free(tempname);
90  }
91  /* Check that we successfully got an fd. */
92  if (fd == -1)
93  return NULL;
94 
95  file = fdopen(fd, "w+");
96  if (!file) {
97  LOG(llevError, "fdopen() failed in tempnam_secure()!\n");
98  free(tempname);
99  return NULL;
100  }
101 
102  *filename = tempname;
103  return file;
104 }
105 
117 void remove_directory(const char *path) {
118  DIR *dirp;
119  char buf[strlen(path) + sizeof(dirent::d_name) + 1];
120  struct stat statbuf;
121  int status;
122 
123  if ((dirp = opendir(path)) != NULL) {
124  struct dirent *de;
125 
126  for (de = readdir(dirp); de; de = readdir(dirp)) {
127  /* Don't remove '.' or '..' In theory we should do a better
128  * check for .., but the directories we are removing are fairly
129  * limited and should not have dot files in them.
130  */
131  if (de->d_name[0] == '.')
132  continue;
133 
134  /* Linux actually has a type field in the dirent structure,
135  * but that is not portable - stat should be portable
136  */
137  status = stat(de->d_name, &statbuf);
138  if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
139  snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name);
141  continue;
142  }
143  snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name);
144  if (unlink(buf)) {
145  LOG(llevError, "Unable to remove %s\n", path);
146  }
147  }
148  closedir(dirp);
149  }
150  if (rmdir(path)) {
151  LOG(llevError, "Unable to remove directory %s\n", path);
152  }
153 }
154 
168 bool make_path_to_file(const char *filename) {
169  char buf[MAX_BUF], *cp = buf;
170  struct stat statbuf;
171 
172  if (!filename || !*filename)
173  return true;
174 
175  safe_strncpy(buf, filename, sizeof(buf));
176  while ((cp = strchr(cp+1, (int)'/'))) {
177  *cp = '\0';
178  if (stat(buf, &statbuf) || !S_ISDIR(statbuf.st_mode)) {
179  LOG(llevDebug, "Was not dir: %s\n", buf);
180 #ifdef WIN32
181  if (mkdir(buf)) {
182 #else
183  if (mkdir(buf, SAVE_DIR_MODE)) {
184 #endif
185  LOG(llevError, "Cannot mkdir %s: %s\n", buf, strerror(errno));
186  return false;
187  }
188  }
189  *cp = '/';
190  }
191 
192  return true;
193 }
194 
208 void safe_strcat(char *dest, const char *orig, size_t *curlen, size_t maxlen) {
209  assert(curlen != NULL);
210  assert(*curlen < maxlen);
211 #ifdef HAVE_STRLCAT
212  *curlen = strlcat(dest, orig, maxlen);
213 #else
214  if (*curlen == (maxlen-1))
215  return;
216  strncpy(dest+*curlen, orig, maxlen-*curlen-1);
217  dest[maxlen-1] = 0;
218  *curlen += strlen(orig);
219 #endif
220  if (*curlen > (maxlen-1))
221  *curlen = maxlen-1;
222 }
223 
224 #ifndef HAVE_STRLCPY
225 
228 size_t strlcpy(char *dst, const char *src, size_t size) {
229  strncpy(dst, src, size - 1);
230  dst[size - 1] = '\0';
231  return strlen(src);
232 }
233 #endif
234 
235 #ifdef WIN32
236 #include <string.h>
237 #include <ctype.h>
238 const char *strcasestr(const char *s, const char *find)
239 {
240  char c, sc;
241  size_t len;
242 
243  if ((c = *find++) != 0) {
244  c = tolower((unsigned char) c);
245  len = strlen(find);
246  do {
247  do {
248  if ((sc = *s++) == 0)
249  return (NULL);
250  }
251  while ((char) tolower((unsigned char) sc) != c);
252  }
253  while (strncasecmp(s, find, len) != 0);
254  s--;
255  }
256  return s;
257 }
258 #endif
S_IWUSR
#define S_IWUSR
Definition: win32.h:47
global.h
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
llevError
@ llevError
Problems requiring server admin to fix.
Definition: logger.h:11
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:82
safe_strcat
void safe_strcat(char *dest, const char *orig, size_t *curlen, size_t maxlen)
Simple function we use below to keep adding to the same string but also make sure we don't overwrite ...
Definition: porting.cpp:208
c
static event_registration c
Definition: citylife.cpp:427
tolower
#define tolower(C)
Simple macro to convert a letter to lowercase.
Definition: c_new.cpp:30
SAVE_DIR_MODE
#define SAVE_DIR_MODE
Definition: config.h:563
buf
StringBuffer * buf
Definition: readable.cpp:1564
remove_directory
void remove_directory(const char *path)
This function removes everything in the directory, and the directory itself.
Definition: porting.cpp:117
opendir
DIR * opendir(const char *)
sc
Player Stats effect how well a character can survie and interact inside the crossfire world This section discusses the various what they and how they effect the player s actions Also in this section are the stat modifiers that specific classes professions bring Player and sps the current and maximum the Current and Maximum The Current Sp can go somewhat negative When Sp is negative not all spells can be and a more negative Sp makes spell casting less likey to succeed can affect Damage and how the characters as well as how often the character can attack this affects the prices when buying and selling items if this drops the player will start losing hit points wd Cleric or Dwarf sm Elf wd Fireborn sc
Definition: stats.txt:96
readdir
struct dirent * readdir(DIR *)
strcasestr
const char * strcasestr(const char *s, const char *find)
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Portable implementation of strlcpy(3).
Definition: porting.cpp:228
make_path_to_file
bool make_path_to_file(const char *filename)
Recursively creates missing directories in the path to filename until the last directory separator '/...
Definition: porting.cpp:168
tempnam_secure
FILE * tempnam_secure(const char *dir, const char *pfx, char **filename)
A replacement for the tempnam_local() function since that one is not very secure.
Definition: porting.cpp:71
S_IRUSR
#define S_IRUSR
Definition: win32.h:56
closedir
int closedir(DIR *)
llevDebug
@ llevDebug
Only for debugging purposes.
Definition: logger.h:15