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 
165 bool make_path_to_file(const char *filename) {
166  char buf[MAX_BUF], *cp = buf;
167  struct stat statbuf;
168 
169  if (!filename || !*filename)
170  return true;
171 
172  safe_strncpy(buf, filename, sizeof(buf));
173  while ((cp = strchr(cp+1, (int)'/'))) {
174  *cp = '\0';
175  if (stat(buf, &statbuf) || !S_ISDIR(statbuf.st_mode)) {
176  LOG(llevDebug, "Was not dir: %s\n", buf);
177 #ifdef WIN32
178  if (mkdir(buf)) {
179 #else
180  if (mkdir(buf, SAVE_DIR_MODE)) {
181 #endif
182  LOG(llevError, "Cannot mkdir %s: %s\n", buf, strerror(errno));
183  return false;
184  }
185  }
186  *cp = '/';
187  }
188 
189  return true;
190 }
191 
205 void safe_strcat(char *dest, const char *orig, size_t *curlen, size_t maxlen) {
206  assert(curlen != NULL);
207  assert(*curlen < maxlen);
208 #ifdef HAVE_STRLCAT
209  *curlen = strlcat(dest, orig, maxlen);
210 #else
211  if (*curlen == (maxlen-1))
212  return;
213  strncpy(dest+*curlen, orig, maxlen-*curlen-1);
214  dest[maxlen-1] = 0;
215  *curlen += strlen(orig);
216 #endif
217  if (*curlen > (maxlen-1))
218  *curlen = maxlen-1;
219 }
220 
221 #ifndef HAVE_STRLCPY
222 
225 size_t strlcpy(char *dst, const char *src, size_t size) {
226  strncpy(dst, src, size - 1);
227  dst[size - 1] = '\0';
228  return strlen(src);
229 }
230 #endif
231 
232 #ifdef WIN32
233 #include <string.h>
234 #include <ctype.h>
235 const char *strcasestr(const char *s, const char *find)
236 {
237  char c, sc;
238  size_t len;
239 
240  if ((c = *find++) != 0) {
241  c = tolower((unsigned char) c);
242  len = strlen(find);
243  do {
244  do {
245  if ((sc = *s++) == 0)
246  return (NULL);
247  }
248  while ((char) tolower((unsigned char) sc) != c);
249  }
250  while (strncasecmp(s, find, len) != 0);
251  s--;
252  }
253  return s;
254 }
255 #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:205
c
static event_registration c
Definition: citylife.cpp:424
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:225
make_path_to_file
bool make_path_to_file(const char *filename)
Checks if any directories in the given path doesn't exist, and creates if necessary.
Definition: porting.cpp:165
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