PageRenderTime 48ms CodeModel.GetById 2ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

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