/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/util.c

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs · C · 570 lines · 496 code · 54 blank · 20 comment · 121 complexity · 5e9abb86fff5703928885efacb2627f2 MD5 · raw file

  1. /*
  2. util.c - general purpose utility routines
  3. Copyright (C) 2007, 2008 siliconforks.com
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #define _GNU_SOURCE
  17. #include <config.h>
  18. #include "util.h"
  19. #include <assert.h>
  20. #include <errno.h>
  21. #include <limits.h>
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include <stdint.h>
  25. #include <string.h>
  26. #include <strings.h>
  27. #include <dirent.h>
  28. #include <libgen.h>
  29. #include <sys/stat.h>
  30. #include <sys/types.h>
  31. #include <unistd.h>
  32. const char * program = NULL;
  33. void fatal(const char * format, ...) {
  34. fprintf(stderr, "%s: ", program);
  35. va_list ap;
  36. va_start(ap, format);
  37. vfprintf(stderr, format, ap);
  38. va_end(ap);
  39. fputc('\n', stderr);
  40. exit(EXIT_FAILURE);
  41. }
  42. void fatal_command_line(const char * format, ...) {
  43. fprintf(stderr, "%s: ", program);
  44. va_list ap;
  45. va_start(ap, format);
  46. vfprintf(stderr, format, ap);
  47. va_end(ap);
  48. fputc('\n', stderr);
  49. fprintf(stderr, "Try `%s --help' for more information.\n", program);
  50. exit(EXIT_FAILURE);
  51. }
  52. void fatal_source(const char * source_file, unsigned int line_number, const char * format, ...) {
  53. fprintf(stderr, "%s:%s:%u: ", program, source_file, line_number);
  54. va_list ap;
  55. va_start(ap, format);
  56. vfprintf(stderr, format, ap);
  57. va_end(ap);
  58. fputc('\n', stderr);
  59. exit(EXIT_FAILURE);
  60. }
  61. void warn_source(const char * source_file, unsigned int line_number, const char * format, ...) {
  62. fprintf(stderr, "%s:%s:%u: ", program, source_file, line_number);
  63. va_list ap;
  64. va_start(ap, format);
  65. vfprintf(stderr, format, ap);
  66. va_end(ap);
  67. fputc('\n', stderr);
  68. }
  69. void version(void) {
  70. printf("%s %s\n", program, VERSION);
  71. printf("Character encoding support: ");
  72. #if HAVE_ICONV
  73. printf("iconv\n");
  74. #elif HAVE_MULTIBYTETOWIDECHAR
  75. printf("MultiByteToWideChar\n");
  76. #else
  77. printf("none\n");
  78. #endif
  79. exit(EXIT_SUCCESS);
  80. }
  81. size_t addst(size_t x, size_t y) {
  82. if (SIZE_MAX - x < y) {
  83. fatal("integer overflow");
  84. }
  85. return x + y;
  86. }
  87. size_t mulst(size_t x, size_t y) {
  88. if (x == 0 || y == 0) {
  89. return 0;
  90. }
  91. if (SIZE_MAX / x < y) {
  92. fatal("integer overflow");
  93. }
  94. return x * y;
  95. }
  96. void * xmalloc(size_t size) {
  97. void * result = malloc(size);
  98. if (result == NULL) {
  99. fatal("out of memory");
  100. }
  101. return result;
  102. }
  103. void * xrealloc(void * p, size_t size) {
  104. void * result = realloc(p, size);
  105. if (result == NULL) {
  106. fatal("out of memory");
  107. }
  108. return result;
  109. }
  110. char * xstrdup(const char * s) {
  111. char * result = strdup(s);
  112. if (result == NULL) {
  113. fatal("out of memory");
  114. }
  115. return result;
  116. }
  117. char * xstrndup(const char * s, size_t size) {
  118. char * result = strndup(s, size);
  119. if (result == NULL) {
  120. fatal("out of memory");
  121. }
  122. return result;
  123. }
  124. int xasprintf(char ** s, const char * template, ...) {
  125. va_list a;
  126. va_start(a, template);
  127. int result = vasprintf(s, template, a);
  128. va_end(a);
  129. if (result < 0) {
  130. fatal("out of memory");
  131. }
  132. return result;
  133. }
  134. char * xgetcwd(void) {
  135. char * result = getcwd(NULL, 0);
  136. if (result == NULL) {
  137. fatal("out of memory");
  138. }
  139. return result;
  140. }
  141. FILE * xfopen(const char * file, const char * mode) {
  142. FILE * result = fopen(file, mode);
  143. if (result == NULL) {
  144. fatal("cannot open file: %s", file);
  145. }
  146. return result;
  147. }
  148. DIR * xopendir(const char * directory) {
  149. DIR * result = opendir(directory);
  150. if (result == NULL) {
  151. fatal("cannot open directory: %s", directory);
  152. }
  153. return result;
  154. }
  155. void xlstat(const char * file, struct stat * buf) {
  156. #ifdef _WIN32
  157. return xstat(file, buf);
  158. #else
  159. if (lstat(file, buf) == -1) {
  160. fatal("cannot stat file: %s", file);
  161. }
  162. #endif
  163. }
  164. void xstat(const char * file, struct stat * buf) {
  165. if (stat(file, buf) == -1) {
  166. fatal("cannot stat file: %s", file);
  167. }
  168. }
  169. void xmkdir(const char * directory) {
  170. int result;
  171. #ifdef _WIN32
  172. result = mkdir(directory);
  173. #else
  174. result = mkdir(directory, 0755);
  175. #endif
  176. if (result == -1) {
  177. fatal("cannot create directory: %s", directory);
  178. }
  179. }
  180. void mkdir_if_necessary(const char * directory) {
  181. struct stat buf;
  182. if (stat(directory, &buf) == 0) {
  183. if (! S_ISDIR(buf.st_mode)) {
  184. fatal("not a directory: %s", directory);
  185. }
  186. }
  187. else {
  188. if (errno == ENOENT) {
  189. xmkdir(directory);
  190. }
  191. else {
  192. fatal("cannot stat directory: %s", directory);
  193. }
  194. }
  195. }
  196. void mkdirs(const char * directory) {
  197. char * d = xmalloc(strlen(directory) + 1);
  198. for (const char * p = directory; *p != '\0'; p++) {
  199. if (*p == '/' && p > directory) {
  200. strncpy(d, directory, p - directory);
  201. d[p - directory] = '\0';
  202. mkdir_if_necessary(d);
  203. }
  204. }
  205. mkdir_if_necessary(directory);
  206. free(d);
  207. }
  208. void xchdir(const char * directory) {
  209. if (chdir(directory) == -1) {
  210. fatal("cannot change directory: %s", directory);
  211. }
  212. }
  213. bool str_starts_with(const char * string, const char * prefix) {
  214. const char * string_ptr = string;
  215. const char * prefix_ptr = prefix;
  216. while (*string_ptr != '\0' && *prefix_ptr != '\0') {
  217. if (*string_ptr != *prefix_ptr) {
  218. return false;
  219. }
  220. string_ptr++;
  221. prefix_ptr++;
  222. }
  223. if (*string_ptr == '\0' && *prefix_ptr != '\0') {
  224. return false;
  225. }
  226. return true;
  227. }
  228. bool str_ends_with(const char * string, const char * suffix) {
  229. size_t string_length = strlen(string);
  230. size_t suffix_length = strlen(suffix);
  231. if (string_length < suffix_length) {
  232. return false;
  233. }
  234. return strcmp(string + string_length - suffix_length, suffix) == 0;
  235. }
  236. char * make_path(const char * parent, const char * relative_path) {
  237. size_t parent_length = strlen(parent);
  238. size_t relative_path_length = strlen(relative_path);
  239. size_t result_length = addst(parent_length, relative_path_length);
  240. result_length = addst(result_length, 2);
  241. char * result = xmalloc(result_length);
  242. strcpy(result, parent);
  243. result[parent_length] = '/';
  244. strcpy(result + parent_length + 1, relative_path);
  245. return result;
  246. }
  247. char * make_canonical_path(const char * relative_path) {
  248. char * original_directory = xgetcwd();
  249. char * base = make_basename(relative_path);
  250. char * dir = make_dirname(relative_path);
  251. xchdir(dir);
  252. char * canonical_dir = xgetcwd();
  253. char * result = make_path(canonical_dir, base);
  254. free(canonical_dir);
  255. free(base);
  256. free(dir);
  257. xchdir(original_directory);
  258. free(original_directory);
  259. return result;
  260. }
  261. char * make_basename(const char * path) {
  262. char * copy = xstrdup(path);
  263. char * result = xstrdup(basename(copy));
  264. free(copy);
  265. return result;
  266. }
  267. char * make_dirname(const char * path) {
  268. char * copy = xstrdup(path);
  269. char * result = xstrdup(dirname(copy));
  270. free(copy);
  271. return result;
  272. }
  273. int is_same_file(const char * file1, const char * file2) {
  274. #ifdef _WIN32
  275. #define FILECMP strcasecmp
  276. #else
  277. #define FILECMP strcmp
  278. #endif
  279. if (FILECMP(file1, file2) == 0) {
  280. return 1;
  281. }
  282. char * canonical1 = make_canonical_path(file1);
  283. char * canonical2 = make_canonical_path(file2);
  284. int cmp = FILECMP(canonical1, canonical2);
  285. free(canonical1);
  286. free(canonical2);
  287. if (cmp == 0) {
  288. return 1;
  289. }
  290. #ifndef _WIN32
  291. struct stat buf1;
  292. if (stat(file1, &buf1) == -1) {
  293. if (errno == ENOENT) {
  294. return 0;
  295. }
  296. else {
  297. fatal("cannot stat file: %s", file1);
  298. }
  299. }
  300. struct stat buf2;
  301. if (stat(file2, &buf2) == -1) {
  302. if (errno == ENOENT) {
  303. return 0;
  304. }
  305. else {
  306. fatal("cannot stat file: %s", file2);
  307. }
  308. }
  309. if (buf1.st_dev == buf2.st_dev &&
  310. buf1.st_ino == buf2.st_ino) {
  311. return 1;
  312. }
  313. #endif
  314. return 0;
  315. #undef FILECMP
  316. }
  317. int contains_file(const char * file1, const char * file2) {
  318. int result = 0;
  319. char * ancestor = make_canonical_path(file1);
  320. char * d = make_canonical_path(file2);
  321. char * parent = make_dirname(d);
  322. while (strcmp(d, parent) != 0) {
  323. if (is_same_file(ancestor, parent)) {
  324. result = 1;
  325. break;
  326. }
  327. free(d);
  328. d = parent;
  329. parent = make_dirname(d);
  330. }
  331. free(d);
  332. free(parent);
  333. free(ancestor);
  334. return result;
  335. }
  336. void copy_stream(FILE * source, FILE * destination) {
  337. unsigned char buffer[8192];
  338. for (;;) {
  339. int bytes_read = fread(buffer, 1, sizeof(buffer), source);
  340. if (bytes_read == 0) {
  341. break;
  342. }
  343. fwrite(buffer, 1, bytes_read, destination);
  344. }
  345. }
  346. void copy_file(const char * source_file, const char * destination_file) {
  347. FILE * source = xfopen(source_file, "rb");
  348. FILE * destination = xfopen(destination_file, "wb");
  349. copy_stream(source, destination);
  350. #ifndef _WIN32
  351. /* copy permissions */
  352. struct stat buf;
  353. if (fstat(fileno(source), &buf) == -1) {
  354. fatal("cannot stat file: %s", source_file);
  355. }
  356. fchmod(fileno(destination), buf.st_mode);
  357. #endif
  358. fclose(source);
  359. fclose(destination);
  360. }
  361. bool directory_is_empty(const char * directory) {
  362. bool result = true;
  363. DIR * dir = xopendir(directory);
  364. struct dirent * e;
  365. while ((e = readdir(dir)) != NULL) {
  366. if (strcmp(e->d_name, ".") != 0 &&
  367. strcmp(e->d_name, "..") != 0) {
  368. result = false;
  369. break;
  370. }
  371. }
  372. closedir(dir);
  373. return result;
  374. }
  375. static struct DirListEntry * recursive_dir_list(const char * root, const char * directory_wrt_root, struct DirListEntry * head) {
  376. char * directory = directory_wrt_root == NULL? xstrdup(root): make_path(root, directory_wrt_root);
  377. DIR * dir = xopendir(directory);
  378. struct dirent * e;
  379. while ((e = readdir(dir)) != NULL) {
  380. if (strcmp(e->d_name, ".") == 0 ||
  381. strcmp(e->d_name, "..") == 0) {
  382. continue;
  383. }
  384. char * entry = make_path(directory, e->d_name);
  385. char * entry_wrt_root = directory_wrt_root == NULL? xstrdup(e->d_name): make_path(directory_wrt_root, e->d_name);
  386. struct stat buf;
  387. xlstat(entry, &buf);
  388. if (S_ISREG(buf.st_mode)) {
  389. struct DirListEntry * p = xmalloc(sizeof(struct DirListEntry));
  390. p->name = entry_wrt_root;
  391. p->next = head;
  392. head = p;
  393. }
  394. else if (S_ISDIR(buf.st_mode)) {
  395. head = recursive_dir_list(root, entry_wrt_root, head);
  396. free(entry_wrt_root);
  397. }
  398. #ifndef _WIN32
  399. else if (S_ISLNK(buf.st_mode)) {
  400. /* check what it points to */
  401. xstat(entry, &buf);
  402. if (S_ISREG(buf.st_mode)) {
  403. struct DirListEntry * p = xmalloc(sizeof(struct DirListEntry));
  404. p->name = entry_wrt_root;
  405. p->next = head;
  406. head = p;
  407. }
  408. else {
  409. fatal("refusing to follow symbolic link: %s", entry);
  410. }
  411. }
  412. #endif
  413. else {
  414. fatal("unknown file type: %s", entry);
  415. }
  416. free(entry);
  417. }
  418. closedir(dir);
  419. free(directory);
  420. return head;
  421. }
  422. struct DirListEntry * make_recursive_dir_list(const char * directory) {
  423. return recursive_dir_list(directory, NULL, NULL);
  424. }
  425. void free_dir_list(struct DirListEntry * list) {
  426. while (list != NULL) {
  427. struct DirListEntry * next = list->next;
  428. free(list->name);
  429. free(list);
  430. list = next;
  431. }
  432. }
  433. #ifndef HAVE_STRNDUP
  434. char * strndup(const char * s, size_t size) {
  435. size_t length = strlen(s);
  436. if (length > size) {
  437. char * result = xmalloc(size + 1);
  438. strncpy(result, s, size);
  439. result[size] = '\0';
  440. return result;
  441. }
  442. else {
  443. char * result = xmalloc(length + 1);
  444. strcpy(result, s);
  445. return result;
  446. }
  447. }
  448. #endif
  449. #ifndef HAVE_VASPRINTF
  450. int vasprintf(char ** s, const char * template, va_list a) {
  451. int size = 100;
  452. *s = malloc(size);
  453. if (*s == NULL) {
  454. return -1;
  455. }
  456. va_list copy;
  457. va_copy(copy, a);
  458. int result = vsnprintf(*s, size, template, copy);
  459. if (result >= size) {
  460. int new_size = result;
  461. if (new_size == INT_MAX) {
  462. free(*s);
  463. return -1;
  464. }
  465. new_size++;
  466. char * new_s = realloc(*s, new_size);
  467. if (new_s == NULL) {
  468. free(*s);
  469. return -1;
  470. }
  471. *s = new_s;
  472. size = new_size;
  473. va_copy(copy, a);
  474. result = vsnprintf(*s, size, template, copy);
  475. assert(result == size - 1);
  476. }
  477. else if (result == -1) {
  478. while (result == -1) {
  479. if (size == INT_MAX) {
  480. free(*s);
  481. return -1;
  482. }
  483. int new_size;
  484. if (size > INT_MAX / 2) {
  485. new_size = INT_MAX;
  486. }
  487. else {
  488. new_size = 2 * size;
  489. }
  490. char * new_s = realloc(*s, new_size);
  491. if (new_s == NULL) {
  492. free(*s);
  493. return -1;
  494. }
  495. *s = new_s;
  496. size = new_size;
  497. va_copy(copy, a);
  498. result = vsnprintf(*s, size, template, copy);
  499. }
  500. assert(result <= size - 1);
  501. }
  502. return result;
  503. }
  504. #endif
  505. #ifndef HAVE_ASPRINTF
  506. int asprintf(char ** s, const char * template, ...) {
  507. va_list a;
  508. va_start(a, template);
  509. int result = vasprintf(s, template, a);
  510. va_end(a);
  511. return result;
  512. }
  513. #endif