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

Annotation of /trunk/util.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.24