|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00034 #include <global.h> 00035 00037 static uint32 curtmp = 0; 00038 00047 char *tempnam_local(const char *dir, const char *pfx) 00048 { 00049 char *name; 00050 pid_t pid = getpid(); 00051 00052 if (!pfx) 00053 { 00054 pfx = "tmp."; 00055 } 00056 00057 /* This is a pretty simple method - put the pid as a hex digit and 00058 * just keep incrementing the last digit. Check to see if the file 00059 * already exists - if so, we'll just keep looking - eventually we 00060 * should find one that is free. */ 00061 if (dir) 00062 { 00063 if (!(name = (char *) malloc(MAXPATHLEN))) 00064 { 00065 return NULL; 00066 } 00067 00068 do 00069 { 00070 snprintf(name, MAXPATHLEN, "%s/%s%hx.%d", dir, pfx, pid, curtmp); 00071 curtmp++; 00072 } 00073 while (access(name, F_OK) != -1); 00074 00075 return name; 00076 } 00077 00078 return NULL; 00079 } 00080 00087 char *strdup_local(const char *str) 00088 { 00089 size_t len = strlen(str) + 1; 00090 void *new = malloc(len); 00091 00092 if (!new) 00093 { 00094 return NULL; 00095 } 00096 00097 return (char *) memcpy(new, str, len); 00098 } 00099 00105 char *strerror_local(int errnum) 00106 { 00107 #if defined(HAVE_STRERROR) 00108 return strerror(errnum); 00109 #else 00110 # error Missing strerror(). 00111 #endif 00112 } 00113 00118 unsigned long isqrt(unsigned long n) 00119 { 00120 unsigned long op = n, res = 0, one; 00121 00122 /* "one" starts at the highest power of four <= than the argument. */ 00123 one = 1 << 30; 00124 00125 while (one > op) 00126 { 00127 one >>= 2; 00128 } 00129 00130 while (one != 0) 00131 { 00132 if (op >= res + one) 00133 { 00134 op -= res + one; 00135 /* Faster than 2 * one. */ 00136 res += one << 1; 00137 } 00138 00139 res >>= 1; 00140 one >>= 2; 00141 } 00142 00143 return res; 00144 } 00145 00153 char *uncomp[NROF_COMPRESS_METHODS][3] = 00154 { 00155 {NULL, NULL, NULL}, 00156 {".Z", UNCOMPRESS, COMPRESS}, 00157 {".gz", GUNZIP, GZIP}, 00158 {".bz2", BUNZIP, BZIP} 00159 }; 00160 00172 static FILE *open_and_uncompress_file(const char *ext, const char *uncompressor, const char *name, int flag, int *compressed) 00173 { 00174 struct stat st; 00175 char buf[MAX_BUF], buf2[MAX_BUF]; 00176 int ret; 00177 00178 if (!ext) 00179 { 00180 ext = ""; 00181 } 00182 00183 if (strlen(name) + strlen(ext) >= sizeof(buf)) 00184 { 00185 /* File name too long */ 00186 errno = ENAMETOOLONG; 00187 return NULL; 00188 } 00189 00190 snprintf(buf, sizeof(buf), "%s%s", name, ext); 00191 00192 if (stat(buf, &st) != 0) 00193 { 00194 return NULL; 00195 } 00196 00197 if (!S_ISREG(st.st_mode)) 00198 { 00199 /* Not a regular file */ 00200 errno = EISDIR; 00201 return NULL; 00202 } 00203 00204 if (uncompressor == NULL) 00205 { 00206 /* Open without uncompression */ 00207 return fopen(buf, "rb"); 00208 } 00209 00210 /* The file name buf (and its substring name) is passed as an argument to a 00211 * shell command, therefore check for characters that could confuse the 00212 * shell. */ 00213 if (strpbrk(buf, "'\\\r\n") != NULL) 00214 { 00215 /* Pretend the file does not exist */ 00216 errno = ENOENT; 00217 return NULL; 00218 } 00219 00220 if (!flag) 00221 { 00222 /* Uncompress via pipe */ 00223 if (strlen(uncompressor) + 4 + strlen(buf) + 1 >= sizeof(buf2)) 00224 { 00225 /* File name too long */ 00226 errno = ENAMETOOLONG; 00227 return NULL; 00228 } 00229 00230 snprintf(buf2, sizeof(buf2), "%s < '%s'", uncompressor, buf); 00231 return popen(buf2, "r"); 00232 } 00233 00234 /* Remove compression from file, then open file */ 00235 if (stat(name, &st) == 0 && !S_ISREG(st.st_mode)) 00236 { 00237 errno = EISDIR; 00238 return NULL; 00239 } 00240 00241 if (strlen(uncompressor) + 4 + strlen(buf) + 5 + strlen(name) + 1 >= sizeof(buf2)) 00242 { 00243 /* File name too long */ 00244 errno = ENAMETOOLONG; 00245 return NULL; 00246 } 00247 00248 snprintf(buf2, sizeof(buf2), "%s < '%s' > '%s'", uncompressor, buf, name); 00249 00250 ret = system(buf2); 00251 00252 if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) 00253 { 00254 LOG(llevBug, "system(%s) returned %d\n", buf2, ret); 00255 errno = ENOENT; 00256 return NULL; 00257 } 00258 00259 /* Delete the original */ 00260 unlink(buf); 00261 /* Change to "uncompressed file" */ 00262 *compressed = 0; 00263 /* Copy access mode from compressed file */ 00264 chmod(name, st.st_mode); 00265 00266 return fopen(name, "rb"); 00267 } 00268 00279 FILE *open_and_uncompress(const char *name, int flag, int *compressed) 00280 { 00281 size_t i; 00282 FILE *fp; 00283 00284 for (i = 0; i < NROF_COMPRESS_METHODS; i++) 00285 { 00286 *compressed = i; 00287 fp = open_and_uncompress_file(uncomp[i][0], uncomp[i][1], name, flag, compressed); 00288 00289 if (fp) 00290 { 00291 return fp; 00292 } 00293 } 00294 00295 errno = ENOENT; 00296 return NULL; 00297 } 00298 00303 void close_and_delete(FILE *fp, int compressed) 00304 { 00305 if (compressed) 00306 { 00307 pclose(fp); 00308 } 00309 else 00310 { 00311 fclose(fp); 00312 } 00313 } 00314 00319 void make_path_to_file(char *filename) 00320 { 00321 char buf[MAX_BUF], *cp = buf; 00322 struct stat statbuf; 00323 00324 if (!filename || !*filename) 00325 { 00326 return; 00327 } 00328 00329 strcpy(buf, filename); 00330 00331 while ((cp = strchr(cp + 1, '/'))) 00332 { 00333 *cp = '\0'; 00334 00335 if (stat(buf, &statbuf) || !S_ISDIR(statbuf.st_mode)) 00336 { 00337 if (mkdir(buf, 0777)) 00338 { 00339 LOG(llevBug, "Cannot mkdir %s: %s\n", buf, strerror_local(errno)); 00340 return; 00341 } 00342 } 00343 00344 *cp = '/'; 00345 } 00346 } 00347 00353 const char *strcasestr_local(const char *s, const char *find) 00354 { 00355 char c, sc; 00356 size_t len; 00357 00358 if ((c = *find++) != 0) 00359 { 00360 c = tolower(c); 00361 len = strlen(find); 00362 00363 do 00364 { 00365 do 00366 { 00367 if ((sc = *s++) == 0) 00368 { 00369 return NULL; 00370 } 00371 } 00372 while (tolower(sc) != c); 00373 } 00374 while (strncasecmp(s, find, len) != 0); 00375 00376 s--; 00377 } 00378 00379 return s; 00380 } 00381
1.7.4