/[jscoverage]/trunk/util.c
ViewVC logotype

Annotation of /trunk/util.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 125 - (hide annotations)
Mon Jun 2 17:52:38 2008 UTC (10 years, 5 months ago) by siliconforks
File MIME type: text/plain
File size: 11535 byte(s)
Fixes for compiling with MinGW.

1 siliconforks 2 /*
2     util.c - general purpose utility routines
3 siliconforks 87 Copyright (C) 2007, 2008 siliconforks.com
4 siliconforks 2
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 siliconforks 106 #define _GNU_SOURCE
21    
22     #include <config.h>
23    
24 siliconforks 2 #include "util.h"
25    
26     #include <assert.h>
27     #include <errno.h>
28 siliconforks 99 #include <limits.h>
29 siliconforks 2 #include <stdarg.h>
30     #include <stdio.h>
31 siliconforks 106 #include <stdint.h>
32 siliconforks 2 #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    
41     const char * program = NULL;
42    
43     void 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     fprintf(stderr, "Try `%s --help' for more information.\n", program);
51     exit(EXIT_FAILURE);
52     }
53    
54 siliconforks 106 size_t addst(size_t x, size_t y) {
55     if (SIZE_MAX - x < y) {
56     fatal("integer overflow");
57     }
58     return x + y;
59     }
60    
61     size_t mulst(size_t x, size_t y) {
62     if (x == 0 || y == 0) {
63     return 0;
64     }
65     if (SIZE_MAX / x < y) {
66     fatal("integer overflow");
67     }
68     return x * y;
69     }
70    
71 siliconforks 2 void * xmalloc(size_t size) {
72     void * result = malloc(size);
73     if (result == NULL) {
74     fatal("out of memory");
75     }
76     return result;
77     }
78    
79 siliconforks 91 void * xrealloc(void * p, size_t size) {
80     void * result = realloc(p, size);
81     if (result == NULL) {
82     fatal("out of memory");
83     }
84     return result;
85     }
86    
87 siliconforks 2 char * xstrdup(const char * s) {
88     char * result = strdup(s);
89     if (result == NULL) {
90     fatal("out of memory");
91     }
92     return result;
93     }
94    
95 siliconforks 106 char * xstrndup(const char * s, size_t size) {
96     char * result = strndup(s, size);
97     if (result == NULL) {
98     fatal("out of memory");
99     }
100     return result;
101     }
102    
103     int xasprintf(char ** s, const char * template, ...) {
104     va_list a;
105     va_start(a, template);
106     int result = vasprintf(s, template, a);
107     va_end(a);
108     if (result < 0) {
109     fatal("out of memory");
110     }
111     return result;
112     }
113    
114 siliconforks 2 char * xgetcwd(void) {
115     char * result = getcwd(NULL, 0);
116     if (result == NULL) {
117     fatal("out of memory");
118     }
119     return result;
120     }
121    
122     FILE * xfopen(const char * file, const char * mode) {
123     FILE * result = fopen(file, mode);
124     if (result == NULL) {
125     fatal("cannot open file: %s", file);
126     }
127     return result;
128     }
129    
130     DIR * xopendir(const char * directory) {
131     DIR * result = opendir(directory);
132     if (result == NULL) {
133     fatal("cannot open directory: %s", directory);
134     }
135     return result;
136     }
137    
138     void xlstat(const char * file, struct stat * buf) {
139     #ifdef _WIN32
140     return xstat(file, buf);
141     #else
142     if (lstat(file, buf) == -1) {
143     fatal("cannot stat file: %s", file);
144     }
145     #endif
146     }
147    
148     void xstat(const char * file, struct stat * buf) {
149     if (stat(file, buf) == -1) {
150     fatal("cannot stat file: %s", file);
151     }
152     }
153    
154     void xmkdir(const char * directory) {
155     int result;
156     #ifdef _WIN32
157     result = mkdir(directory);
158     #else
159     result = mkdir(directory, 0755);
160     #endif
161     if (result == -1) {
162     fatal("cannot create directory: %s", directory);
163     }
164     }
165    
166     void mkdir_if_necessary(const char * directory) {
167     struct stat buf;
168     if (stat(directory, &buf) == 0) {
169     if (! S_ISDIR(buf.st_mode)) {
170     fatal("not a directory: %s", directory);
171     }
172     }
173     else {
174     if (errno == ENOENT) {
175     xmkdir(directory);
176     }
177     else {
178     fatal("cannot stat directory: %s", directory);
179     }
180     }
181     }
182    
183     void mkdirs(const char * directory) {
184     char * d = xmalloc(strlen(directory) + 1);
185     for (const char * p = directory; *p != '\0'; p++) {
186     if (*p == '/' && p > directory) {
187     strncpy(d, directory, p - directory);
188     d[p - directory] = '\0';
189     mkdir_if_necessary(d);
190     }
191     }
192     mkdir_if_necessary(directory);
193     free(d);
194     }
195    
196     void xchdir(const char * directory) {
197     if (chdir(directory) == -1) {
198     fatal("cannot change directory: %s", directory);
199     }
200     }
201    
202 siliconforks 106 bool str_starts_with(const char * string, const char * prefix) {
203     const char * string_ptr = string;
204     const char * prefix_ptr = prefix;
205     while (*string_ptr != '\0' && *prefix_ptr != '\0') {
206     if (*string_ptr != *prefix_ptr) {
207     return false;
208     }
209     string_ptr++;
210     prefix_ptr++;
211     }
212     if (*string_ptr == '\0' && *prefix_ptr != '\0') {
213     return false;
214     }
215     return true;
216     }
217    
218     bool str_ends_with(const char * string, const char * suffix) {
219     size_t string_length = strlen(string);
220     size_t suffix_length = strlen(suffix);
221     if (string_length < suffix_length) {
222     return false;
223     }
224     return strcmp(string + string_length - suffix_length, suffix) == 0;
225     }
226    
227 siliconforks 2 char * make_path(const char * parent, const char * relative_path) {
228     size_t parent_length = strlen(parent);
229     size_t relative_path_length = strlen(relative_path);
230 siliconforks 106 size_t result_length = addst(parent_length, relative_path_length);
231     result_length = addst(result_length, 2);
232     char * result = xmalloc(result_length);
233 siliconforks 2 strcpy(result, parent);
234     result[parent_length] = '/';
235     strcpy(result + parent_length + 1, relative_path);
236     return result;
237     }
238    
239     char * make_canonical_path(const char * relative_path) {
240     char * original_directory = xgetcwd();
241     char * base = make_basename(relative_path);
242     char * dir = make_dirname(relative_path);
243    
244     xchdir(dir);
245     char * canonical_dir = xgetcwd();
246     char * result = make_path(canonical_dir, base);
247    
248     free(canonical_dir);
249     free(base);
250     free(dir);
251     xchdir(original_directory);
252     free(original_directory);
253    
254     return result;
255     }
256    
257     char * make_basename(const char * path) {
258     char * copy = xstrdup(path);
259     char * result = xstrdup(basename(copy));
260     free(copy);
261     return result;
262     }
263    
264     char * make_dirname(const char * path) {
265     char * copy = xstrdup(path);
266     char * result = xstrdup(dirname(copy));
267     free(copy);
268     return result;
269     }
270    
271     int is_same_file(const char * file1, const char * file2) {
272     #ifdef _WIN32
273     #define FILECMP strcasecmp
274     #else
275     #define FILECMP strcmp
276     #endif
277     if (FILECMP(file1, file2) == 0) {
278     return 1;
279     }
280    
281     char * canonical1 = make_canonical_path(file1);
282     char * canonical2 = make_canonical_path(file2);
283     int cmp = FILECMP(canonical1, canonical2);
284     free(canonical1);
285     free(canonical2);
286     if (cmp == 0) {
287     return 1;
288     }
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    
318     int contains_file(const char * file1, const char * file2) {
319     int result = 0;
320     char * ancestor = make_canonical_path(file1);
321     char * d = make_canonical_path(file2);
322     char * parent = make_dirname(d);
323     while (strcmp(d, parent) != 0) {
324     if (is_same_file(ancestor, parent)) {
325     result = 1;
326     break;
327     }
328     free(d);
329     d = parent;
330     parent = make_dirname(d);
331     }
332     free(d);
333     free(parent);
334     free(ancestor);
335     return result;
336     }
337    
338     void copy_stream(FILE * source, FILE * destination) {
339     unsigned char buffer[8192];
340     for (;;) {
341     int bytes_read = fread(buffer, 1, sizeof(buffer), source);
342     if (bytes_read == 0) {
343     break;
344     }
345     fwrite(buffer, 1, bytes_read, destination);
346     }
347     }
348    
349     void copy_file(const char * source_file, const char * destination_file) {
350     FILE * source = xfopen(source_file, "rb");
351     FILE * destination = xfopen(destination_file, "wb");
352    
353     copy_stream(source, destination);
354    
355     fclose(source);
356     fclose(destination);
357     }
358    
359 siliconforks 106 bool directory_is_empty(const char * directory) {
360     bool result = true;
361 siliconforks 2 DIR * dir = xopendir(directory);
362     struct dirent * e;
363     while ((e = readdir(dir)) != NULL) {
364     if (strcmp(e->d_name, ".") != 0 &&
365     strcmp(e->d_name, "..") != 0) {
366 siliconforks 106 result = false;
367     break;
368 siliconforks 2 }
369     }
370     closedir(dir);
371 siliconforks 106 return result;
372 siliconforks 2 }
373    
374     static struct DirListEntry * recursive_dir_list(const char * root, const char * directory_wrt_root, struct DirListEntry * head) {
375     char * directory = directory_wrt_root == NULL? xstrdup(root): make_path(root, directory_wrt_root);
376     DIR * dir = xopendir(directory);
377     struct dirent * e;
378     while ((e = readdir(dir)) != NULL) {
379     if (strcmp(e->d_name, ".") == 0 ||
380     strcmp(e->d_name, "..") == 0) {
381     continue;
382     }
383     char * entry = make_path(directory, e->d_name);
384     char * entry_wrt_root = directory_wrt_root == NULL? xstrdup(e->d_name): make_path(directory_wrt_root, e->d_name);
385     struct stat buf;
386     xlstat(entry, &buf);
387     if (S_ISREG(buf.st_mode)) {
388     struct DirListEntry * p = xmalloc(sizeof(struct DirListEntry));
389     p->name = entry_wrt_root;
390     p->next = head;
391     head = p;
392     }
393     else if (S_ISDIR(buf.st_mode)) {
394     head = recursive_dir_list(root, entry_wrt_root, head);
395     free(entry_wrt_root);
396     }
397     else {
398     fatal("unknown file type: %s", entry);
399     }
400     free(entry);
401     }
402     closedir(dir);
403     free(directory);
404     return head;
405     }
406    
407     struct DirListEntry * make_recursive_dir_list(const char * directory) {
408     return recursive_dir_list(directory, NULL, NULL);
409     }
410    
411     void free_dir_list(struct DirListEntry * list) {
412     while (list != NULL) {
413     struct DirListEntry * next = list->next;
414     free(list->name);
415     free(list);
416     list = next;
417     }
418     }
419 siliconforks 99
420 siliconforks 125 #ifndef HAVE_STRNDUP
421     char * strndup(const char * s, size_t size) {
422     size_t length = strlen(s);
423     if (length > size) {
424     char * result = xmalloc(size + 1);
425     strncpy(result, s, size);
426     result[size] = '\0';
427     return result;
428     }
429     else {
430     char * result = xmalloc(length + 1);
431     strcpy(result, s);
432     return result;
433     }
434 siliconforks 106 }
435     #endif
436    
437 siliconforks 99 #ifndef HAVE_VASPRINTF
438     int vasprintf(char ** s, const char * template, va_list a) {
439     int size = 100;
440     *s = malloc(size);
441     if (*s == NULL) {
442     return -1;
443     }
444    
445     va_list copy;
446     va_copy(copy, a);
447     int result = vsnprintf(*s, size, template, copy);
448     if (result >= size) {
449     int new_size = result;
450     if (new_size == INT_MAX) {
451     free(*s);
452 siliconforks 106 return -1;
453 siliconforks 99 }
454     new_size++;
455     char * new_s = realloc(*s, new_size);
456     if (new_s == NULL) {
457     free(*s);
458     return -1;
459     }
460     *s = new_s;
461     size = new_size;
462     va_copy(copy, a);
463     result = vsnprintf(*s, size, template, copy);
464     assert(result == size - 1);
465     }
466     else if (result == -1) {
467     while (result == -1) {
468 siliconforks 106 if (size == INT_MAX) {
469 siliconforks 99 free(*s);
470 siliconforks 106 return -1;
471 siliconforks 99 }
472 siliconforks 106 int new_size;
473     if (size > INT_MAX / 2) {
474     new_size = INT_MAX;
475     }
476     else {
477     new_size = 2 * size;
478     }
479 siliconforks 99 char * new_s = realloc(*s, new_size);
480     if (new_s == NULL) {
481     free(*s);
482     return -1;
483     }
484     *s = new_s;
485     size = new_size;
486     va_copy(copy, a);
487     result = vsnprintf(*s, size, template, copy);
488     }
489     assert(result <= size - 1);
490     }
491    
492     return result;
493     }
494     #endif
495    
496     #ifndef HAVE_ASPRINTF
497     int asprintf(char ** s, const char * template, ...) {
498     va_list a;
499     va_start(a, template);
500     int result = vasprintf(s, template, a);
501     va_end(a);
502     return result;
503     }
504     #endif

  ViewVC Help
Powered by ViewVC 1.1.24