Bug Summary

File:util.c
Location:line 1196, column 2
Description:Value stored to 'ret' is never read

Annotated Source Code

1/*
2 * Copyright (C) 2002 Andrew Tridgell
3 * Copyright (C) 2009-2013 Joel Rosdahl
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 3 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 51
17 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "ccache.h"
21
22#include <zlib.h>
23
24#ifdef HAVE_PWD_H1
25#include <pwd.h>
26#endif
27#ifdef HAVE_SYS_TIME_H1
28#include <sys/time.h>
29#endif
30
31#ifdef _WIN32
32#include <windows.h>
33#include <sys/locking.h>
34#endif
35
36static FILE *logfile;
37
38static bool_Bool
39init_log(void)
40{
41 extern char *cache_logfile;
42
43 if (logfile) {
44 return true1;
45 }
46 if (!cache_logfile) {
47 return false0;
48 }
49 logfile = fopen(cache_logfile, "a");
50 if (logfile) {
51 int fd = fileno(logfile);
52 int flags = fcntl(fd, F_GETFD1, 0);
53 if (flags >= 0) {
54 fcntl(fd, F_SETFD2, flags | FD_CLOEXEC1);
55 }
56 return true1;
57 } else {
58 return false0;
59 }
60}
61
62static void
63log_prefix(void)
64{
65#ifdef HAVE_GETTIMEOFDAY1
66 char timestamp[100];
67 struct timeval tv;
68 struct tm *tm;
69
70 gettimeofday(&tv, NULL((void*)0));
71#ifdef __MINGW64_VERSION_MAJOR
72 tm = _localtime32(&tv.tv_sec);
73#else
74 tm = localtime(&tv.tv_sec);
75#endif
76 strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S", tm);
77 fprintf(logfile, "[%s.%06d %-5d] ", timestamp, (int)tv.tv_usec,
78 (int)getpid());
79#else
80 fprintf(logfile, "[%-5d] ", (int)getpid());
81#endif
82}
83
84/*
85 * Write a message to the CCACHE_LOGFILE location (adding a newline).
86 */
87void
88cc_log(const char *format, ...)
89{
90 va_list ap;
91
92 if (!init_log()) {
93 return;
94 }
95
96 log_prefix();
97 va_start(ap, format)__builtin_va_start(ap, format);
98 vfprintf(logfile, format, ap);
99 va_end(ap)__builtin_va_end(ap);
100 fprintf(logfile, "\n");
101 fflush(logfile);
102}
103
104/*
105 * Log an executed command to the CCACHE_LOGFILE location.
106 */
107void
108cc_log_argv(const char *prefix, char **argv)
109{
110 if (!init_log()) {
111 return;
112 }
113
114 log_prefix();
115 fputs(prefix, logfile);
116 print_command(logfile, argv);
117 fflush(logfile);
118}
119
120/* something went badly wrong! */
121void
122fatal(const char *format, ...)
123{
124 va_list ap;
125 char msg[1000];
126
127 va_start(ap, format)__builtin_va_start(ap, format);
128 vsnprintf(msg, sizeof(msg), format, ap);
129 va_end(ap)__builtin_va_end(ap);
130
131 cc_log("FATAL: %s", msg);
132 fprintf(stderrstderr, "ccache: FATAL: %s\n", msg);
133
134 exit(1);
135}
136
137/*
138 * Copy all data from fd_in to fd_out, decompressing data from fd_in if needed.
139 */
140void
141copy_fd(int fd_in, int fd_out)
142{
143 char buf[10240];
144 int n;
145 gzFile gz_in;
146
147 gz_in = gzdopen(dup(fd_in), "rb");
148
149 if (!gz_in) {
150 fatal("Failed to copy fd");
151 }
152
153 while ((n = gzread(gz_in, buf, sizeof(buf))) > 0) {
154 ssize_t count, written = 0;
155 do {
156 count = write(fd_out, buf + written, n - written);
157 if (count == -1) {
158 if (errno(*__errno_location ()) != EAGAIN11 && errno(*__errno_location ()) != EINTR4) {
159 fatal("Failed to copy fd");
160 }
161 } else {
162 written += count;
163 }
164 } while (written < n);
165 }
166
167 gzclose(gz_in);
168}
169
170#ifndef HAVE_MKSTEMP1
171/* cheap and nasty mkstemp replacement */
172int
173mkstemp(char *template)
174{
175 mktemp(template);
176 return open(template, O_RDWR02 | O_CREAT0100 | O_EXCL0200 | O_BINARY0, 0600);
177}
178#endif
179
180/*
181 * Copy src to dest, decompressing src if needed. compress_dest decides whether
182 * dest will be compressed.
183 */
184int
185copy_file(const char *src, const char *dest, int compress_dest)
186{
187 int fd_in = -1, fd_out = -1;
188 gzFile gz_in = NULL((void*)0), gz_out = NULL((void*)0);
189 char buf[10240];
190 int n, written;
191 char *tmp_name;
192#ifndef _WIN32
193 mode_t mask;
194#endif
195 struct stat st;
196 int errnum;
197
198 tmp_name = format("%s.%s.XXXXXX", dest, tmp_string());
199 cc_log("Copying %s to %s via %s (%s)",
200 src, dest, tmp_name, compress_dest ? "compressed": "uncompressed");
201
202 /* open source file */
203 fd_in = open(src, O_RDONLY00 | O_BINARY0);
204 if (fd_in == -1) {
205 cc_log("open error: %s", strerror(errno(*__errno_location ())));
206 return -1;
207 }
208
209 gz_in = gzdopen(fd_in, "rb");
210 if (!gz_in) {
211 cc_log("gzdopen(src) error: %s", strerror(errno(*__errno_location ())));
212 close(fd_in);
213 return -1;
214 }
215
216 /* open destination file */
217 fd_out = mkstemp(tmp_name);
218 if (fd_out == -1) {
219 cc_log("mkstemp error: %s", strerror(errno(*__errno_location ())));
220 goto error;
221 }
222
223 if (compress_dest) {
224 /*
225 * A gzip file occupies at least 20 bytes, so it will always
226 * occupy an entire filesystem block, even for empty files.
227 * Turn off compression for empty files to save some space.
228 */
229 if (fstat(fd_in, &st) != 0) {
230 cc_log("fstat error: %s", strerror(errno(*__errno_location ())));
231 goto error;
232 }
233 if (file_size(&st) == 0) {
234 compress_dest = 0;
235 }
236 }
237
238 if (compress_dest) {
239 gz_out = gzdopen(dup(fd_out), "wb");
240 if (!gz_out) {
241 cc_log("gzdopen(dest) error: %s", strerror(errno(*__errno_location ())));
242 goto error;
243 }
244 }
245
246 while ((n = gzread(gz_in, buf, sizeof(buf))) > 0) {
247 if (compress_dest) {
248 written = gzwrite(gz_out, buf, n);
249 } else {
250 ssize_t count;
251 written = 0;
252 do {
253 count = write(fd_out, buf + written, n - written);
254 if (count == -1 && errno(*__errno_location ()) != EINTR4) {
255 break;
256 }
257 written += count;
258 } while (written < n);
259 }
260 if (written != n) {
261 if (compress_dest) {
262 cc_log("gzwrite error: %s (errno: %s)",
263 gzerror(gz_in, &errnum),
264 strerror(errno(*__errno_location ())));
265 } else {
266 cc_log("write error: %s", strerror(errno(*__errno_location ())));
267 }
268 goto error;
269 }
270 }
271
272 /*
273 * gzeof won't tell if there's an error in the trailing CRC, so we must check
274 * gzerror before considering everything OK.
275 */
276 gzerror(gz_in, &errnum);
277 if (!gzeof(gz_in) || (errnum != Z_OK0 && errnum != Z_STREAM_END1)) {
278 cc_log("gzread error: %s (errno: %s)",
279 gzerror(gz_in, &errnum), strerror(errno(*__errno_location ())));
280 gzclose(gz_in);
281 if (gz_out) {
282 gzclose(gz_out);
283 }
284 close(fd_out);
285 tmp_unlink(tmp_name);
286 free(tmp_name);
287 return -1;
288 }
289
290 gzclose(gz_in);
291 gz_in = NULL((void*)0);
292 if (gz_out) {
293 gzclose(gz_out);
294 gz_out = NULL((void*)0);
295 }
296
297#ifndef _WIN32
298 /* get perms right on the tmp file */
299 mask = umask(0);
300 fchmod(fd_out, 0666 & ~mask);
301 umask(mask);
302#endif
303
304 /* the close can fail on NFS if out of space */
305 if (close(fd_out) == -1) {
306 cc_log("close error: %s", strerror(errno(*__errno_location ())));
307 goto error;
308 }
309
310 if (x_rename(tmp_name, dest) == -1) {
311 cc_log("rename error: %s", strerror(errno(*__errno_location ())));
312 goto error;
313 }
314
315 free(tmp_name);
316
317 return 0;
318
319error:
320 if (gz_in) {
321 gzclose(gz_in);
322 }
323 if (gz_out) {
324 gzclose(gz_out);
325 }
326 if (fd_out != -1) {
327 close(fd_out);
328 }
329 tmp_unlink(tmp_name);
330 free(tmp_name);
331 return -1;
332}
333
334/* Run copy_file() and, if successful, delete the source file. */
335int
336move_file(const char *src, const char *dest, int compress_dest)
337{
338 int ret;
339
340 ret = copy_file(src, dest, compress_dest);
341 if (ret != -1) {
342 x_unlink(src);
343 }
344 return ret;
345}
346
347/*
348 * Like move_file(), but assumes that src is uncompressed and that src and dest
349 * are on the same file system.
350 */
351int
352move_uncompressed_file(const char *src, const char *dest, int compress_dest)
353{
354 if (compress_dest) {
355 return move_file(src, dest, compress_dest);
356 } else {
357 return x_rename(src, dest);
358 }
359}
360
361/* test if a file is zlib compressed */
362bool_Bool
363file_is_compressed(const char *filename)
364{
365 FILE *f;
366
367 f = fopen(filename, "rb");
368 if (!f) {
369 return false0;
370 }
371
372 /* test if file starts with 1F8B, which is zlib's
373 * magic number */
374 if ((fgetc(f) != 0x1f) || (fgetc(f) != 0x8b)) {
375 fclose(f);
376 return false0;
377 }
378
379 fclose(f);
380 return true1;
381}
382
383/* make sure a directory exists */
384int
385create_dir(const char *dir)
386{
387 struct stat st;
388 if (stat(dir, &st) == 0) {
389 if (S_ISDIR(st.st_mode)((((st.st_mode)) & 0170000) == (0040000))) {
390 return 0;
391 }
392 errno(*__errno_location ()) = ENOTDIR20;
393 return 1;
394 }
395 if (mkdir(dir, 0777) != 0 && errno(*__errno_location ()) != EEXIST17) {
396 return 1;
397 }
398 return 0;
399}
400
401/*
402 * Return a static string with the current hostname.
403 */
404const char *
405get_hostname(void)
406{
407 static char hostname[200] = "";
408
409 if (!hostname[0]) {
410 strcpy(hostname, "unknown");
411#if HAVE_GETHOSTNAME1
412 gethostname(hostname, sizeof(hostname)-1);
413#endif
414 hostname[sizeof(hostname)-1] = 0;
415 }
416
417 return hostname;
418}
419
420/*
421 * Return a string to be used to distinguish temporary files. Also tries to
422 * cope with NFS by adding the local hostname.
423 */
424const char *
425tmp_string(void)
426{
427 static char *ret;
428
429 if (!ret) {
430 ret = format("%s.%u", get_hostname(), (unsigned)getpid());
431 }
432
433 return ret;
434}
435
436/* Return the hash result as a hex string. Caller frees. */
437char *
438format_hash_as_string(const unsigned char *hash, unsigned size)
439{
440 char *ret;
441 int i;
442
443 ret = x_malloc(53);
444 for (i = 0; i < 16; i++) {
445 sprintf(&ret[i*2], "%02x", (unsigned) hash[i]);
446 }
447 sprintf(&ret[i*2], "-%u", size);
448
449 return ret;
450}
451
452char const CACHEDIR_TAG[] =
453 "Signature: 8a477f597d28d172789f06886806bc55\n"
454 "# This file is a cache directory tag created by ccache.\n"
455 "# For information about cache directory tags, see:\n"
456 "# http://www.brynosaurus.com/cachedir/\n";
457
458int
459create_cachedirtag(const char *dir)
460{
461 struct stat st;
462 FILE *f;
463 char *filename = format("%s/CACHEDIR.TAG", dir);
464 if (stat(filename, &st) == 0) {
465 if (S_ISREG(st.st_mode)((((st.st_mode)) & 0170000) == (0100000))) {
466 goto success;
467 }
468 errno(*__errno_location ()) = EEXIST17;
469 goto error;
470 }
471 f = fopen(filename, "w");
472 if (!f) goto error;
473 if (fwrite(CACHEDIR_TAG, sizeof(CACHEDIR_TAG)-1, 1, f) != 1) {
474 fclose(f);
475 goto error;
476 }
477 if (fclose(f)) goto error;
478success:
479 free(filename);
480 return 0;
481error:
482 free(filename);
483 return 1;
484}
485
486/* Construct a string according to a format. Caller frees. */
487char *
488format(const char *format, ...)
489{
490 va_list ap;
491 char *ptr = NULL((void*)0);
492
493 va_start(ap, format)__builtin_va_start(ap, format);
494 if (vasprintf(&ptr, format, ap) == -1) {
495 fatal("Out of memory in format");
496 }
497 va_end(ap)__builtin_va_end(ap);
498
499 if (!*ptr) fatal("Internal error in format");
500 return ptr;
501}
502
503/*
504 this is like strdup() but dies if the malloc fails
505*/
506char *
507x_strdup(const char *s)
508{
509 char *ret;
510 ret = strdup(s)(__extension__ (__builtin_constant_p (s) && ((size_t)
(const void *)((s) + 1) - (size_t)(const void *)(s) == 1) ? (
((const char *) (s))[0] == '\0' ? (char *) calloc ((size_t) 1
, (size_t) 1) : ({ size_t __len = strlen (s) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, s, __len); __retval; })) : __strdup
(s)))
;
511 if (!ret) {
512 fatal("Out of memory in x_strdup");
513 }
514 return ret;
515}
516
517/*
518 this is like strndup() but dies if the malloc fails
519*/
520char *
521x_strndup(const char *s, size_t n)
522{
523 char *ret;
524#ifndef HAVE_STRNDUP1
525 size_t m;
526
527 if (!s)
528 return NULL((void*)0);
529 m = 0;
530 while (m < n && s[m]) {
531 m++;
532 }
533 ret = malloc(m + 1);
534 if (ret) {
535 memcpy(ret, s, m);
536 ret[m] = '\0';
537 }
538#else
539 ret = strndup(s, n)(__extension__ (__builtin_constant_p (s) && ((size_t)
(const void *)((s) + 1) - (size_t)(const void *)(s) == 1) ? (
((const char *) (s))[0] == '\0' ? (char *) calloc ((size_t) 1
, (size_t) 1) : ({ size_t __len = strlen (s) + 1; size_t __n =
(n); char *__retval; if (__n < __len) __len = __n + 1; __retval
= (char *) malloc (__len); if (__retval != ((void*)0)) { __retval
[__len - 1] = '\0'; __retval = (char *) memcpy (__retval, s, __len
- 1); } __retval; })) : __strndup (s, n)))
;
540#endif
541 if (!ret) {
542 fatal("x_strndup: Could not allocate %lu bytes", (unsigned long)n);
543 }
544 return ret;
545}
546
547/*
548 this is like malloc() but dies if the malloc fails
549*/
550void *
551x_malloc(size_t size)
552{
553 void *ret;
554 if (size == 0) {
555 /*
556 * malloc() may return NULL if size is zero, so always do this to make sure
557 * that the code handles it regardless of platform.
558 */
559 return NULL((void*)0);
560 }
561 ret = malloc(size);
562 if (!ret) {
563 fatal("x_malloc: Could not allocate %lu bytes", (unsigned long)size);
564 }
565 return ret;
566}
567
568/* This is like calloc() but dies if the allocation fails. */
569void *
570x_calloc(size_t nmemb, size_t size)
571{
572 void *ret;
573 if (nmemb * size == 0) {
574 /*
575 * calloc() may return NULL if nmemb or size is 0, so always do this to
576 * make sure that the code handles it regardless of platform.
577 */
578 return NULL((void*)0);
579 }
580 ret = calloc(nmemb, size);
581 if (!ret) {
582 fatal("x_calloc: Could not allocate %lu bytes", (unsigned long)size);
583 }
584 return ret;
585}
586
587/*
588 this is like realloc() but dies if the malloc fails
589*/
590void *
591x_realloc(void *ptr, size_t size)
592{
593 void *p2;
594 if (!ptr) return x_malloc(size);
595 p2 = realloc(ptr, size);
596 if (!p2) {
597 fatal("x_realloc: Could not allocate %lu bytes", (unsigned long)size);
598 }
599 return p2;
600}
601
602
603/*
604 * This is like x_asprintf() but frees *ptr if *ptr != NULL.
605 */
606void
607x_asprintf2(char **ptr, const char *format, ...)
608{
609 char *saved = *ptr;
610 va_list ap;
611
612 *ptr = NULL((void*)0);
613 va_start(ap, format)__builtin_va_start(ap, format);
614 if (vasprintf(ptr, format, ap) == -1) {
615 fatal("Out of memory in x_asprintf2");
616 }
617 va_end(ap)__builtin_va_end(ap);
618
619 if (!ptr) fatal("Out of memory in x_asprintf2");
620 if (saved) {
621 free(saved);
622 }
623}
624
625/*
626 * Recursive directory traversal. fn() is called on all entries in the tree.
627 */
628void
629traverse(const char *dir, void (*fn)(const char *, struct stat *))
630{
631 DIR *d;
632 struct dirent *de;
633
634 d = opendir(dir);
635 if (!d) return;
636
637 while ((de = readdir(d))) {
638 char *fname;
639 struct stat st;
640
641 if (str_eq(de->d_name, ".")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((de->d_name)) && __builtin_constant_p ((".")) &&
(__s1_len = strlen ((de->d_name)), __s2_len = strlen (("."
)), (!((size_t)(const void *)(((de->d_name)) + 1) - (size_t
)(const void *)((de->d_name)) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(((".")) + 1) - (size_t)(const void
*)((".")) == 1) || __s2_len >= 4)) ? __builtin_strcmp ((de
->d_name), (".")) : (__builtin_constant_p ((de->d_name)
) && ((size_t)(const void *)(((de->d_name)) + 1) -
(size_t)(const void *)((de->d_name)) == 1) && (__s1_len
= strlen ((de->d_name)), __s1_len < 4) ? (__builtin_constant_p
((".")) && ((size_t)(const void *)(((".")) + 1) - (size_t
)(const void *)((".")) == 1) ? __builtin_strcmp ((de->d_name
), (".")) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ((".")); int __result = (((const
unsigned char *) (const char *) ((de->d_name)))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((de->d_name))
)[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((de->
d_name)))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ((
de->d_name)))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
((".")) && ((size_t)(const void *)(((".")) + 1) - (size_t
)(const void *)((".")) == 1) && (__s2_len = strlen ((
".")), __s2_len < 4) ? (__builtin_constant_p ((de->d_name
)) && ((size_t)(const void *)(((de->d_name)) + 1) -
(size_t)(const void *)((de->d_name)) == 1) ? __builtin_strcmp
((de->d_name), (".")) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ((de->
d_name)); int __result = (((const unsigned char *) (const char
*) ((".")))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(".")))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(".")))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ((
".")))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (
(de->d_name), ("."))))); }) == 0)
) continue;
642 if (str_eq(de->d_name, "..")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((de->d_name)) && __builtin_constant_p (("..")) &&
(__s1_len = strlen ((de->d_name)), __s2_len = strlen ((".."
)), (!((size_t)(const void *)(((de->d_name)) + 1) - (size_t
)(const void *)((de->d_name)) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((("..")) + 1) - (size_t)(const void
*)(("..")) == 1) || __s2_len >= 4)) ? __builtin_strcmp ((
de->d_name), ("..")) : (__builtin_constant_p ((de->d_name
)) && ((size_t)(const void *)(((de->d_name)) + 1) -
(size_t)(const void *)((de->d_name)) == 1) && (__s1_len
= strlen ((de->d_name)), __s1_len < 4) ? (__builtin_constant_p
(("..")) && ((size_t)(const void *)((("..")) + 1) - (
size_t)(const void *)(("..")) == 1) ? __builtin_strcmp ((de->
d_name), ("..")) : (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) (("..")); int __result
= (((const unsigned char *) (const char *) ((de->d_name))
)[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((de->
d_name)))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(de->d_name)))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((de->d_name)))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(("..")) && ((size_t)(const void *)((("..")) + 1) - (
size_t)(const void *)(("..")) == 1) && (__s2_len = strlen
(("..")), __s2_len < 4) ? (__builtin_constant_p ((de->
d_name)) && ((size_t)(const void *)(((de->d_name))
+ 1) - (size_t)(const void *)((de->d_name)) == 1) ? __builtin_strcmp
((de->d_name), ("..")) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ((de->
d_name)); int __result = (((const unsigned char *) (const char
*) (("..")))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
("..")))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
("..")))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ((
"..")))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
((de->d_name), (".."))))); }) == 0)
) continue;
643
644 if (strlen(de->d_name) == 0) continue;
645
646 fname = format("%s/%s", dir, de->d_name);
647 if (lstat(fname, &st)) {
648 if (errno(*__errno_location ()) != ENOENT2) {
649 perror(fname);
650 }
651 free(fname);
652 continue;
653 }
654
655 if (S_ISDIR(st.st_mode)((((st.st_mode)) & 0170000) == (0040000))) {
656 traverse(fname, fn);
657 }
658
659 fn(fname, &st);
660 free(fname);
661 }
662
663 closedir(d);
664}
665
666
667/* return the base name of a file - caller frees */
668char *
669basename(const char *s)
670{
671 char *p;
672 p = strrchr(s, '/');
673 if (p) s = p + 1;
674#ifdef _WIN32
675 p = strrchr(s, '\\');
676 if (p) s = p + 1;
677#endif
678
679 return x_strdup(s);
680}
681
682/* return the dir name of a file - caller frees */
683char *
684dirname(char *s)
685{
686 char *p;
687 char *p2 = NULL((void*)0);
688 s = x_strdup(s);
689 p = strrchr(s, '/');
690#ifdef _WIN32
691 p2 = strrchr(s, '\\');
692#endif
693 if (p < p2)
694 p = p2;
695 if (p) {
696 *p = 0;
697 return s;
698 } else {
699 free(s);
700 return x_strdup(".");
701 }
702}
703
704/*
705 * Return the file extension (including the dot) of a path as a pointer into
706 * path. If path has no file extension, the empty string and the end of path is
707 * returned.
708 */
709const char *
710get_extension(const char *path)
711{
712 size_t len = strlen(path);
713 const char *p;
714
715 for (p = &path[len - 1]; p >= path; --p) {
716 if (*p == '.') {
717 return p;
718 }
719 if (*p == '/') {
720 break;
721 }
722 }
723 return &path[len];
724}
725
726/*
727 * Return a string containing the given path without the filename extension.
728 * Caller frees.
729 */
730char *
731remove_extension(const char *path)
732{
733 return x_strndup(path, strlen(path) - strlen(get_extension(path)));
734}
735
736/* return size on disk of a file */
737size_t
738file_size(struct stat *st)
739{
740#ifdef _WIN32
741 return (st->st_size + 1023) & ~1023;
742#else
743 size_t size = st->st_blocks * 512;
744 if ((size_t)st->st_size > size) {
745 /* probably a broken stat() call ... */
746 size = (st->st_size + 1023) & ~1023;
747 }
748 return size;
749#endif
750}
751
752/* a safe open/create for read-write */
753int
754safe_open(const char *fname)
755{
756 int fd = open(fname, O_RDWR02|O_BINARY0);
757 if (fd == -1 && errno(*__errno_location ()) == ENOENT2) {
758 fd = open(fname, O_RDWR02|O_CREAT0100|O_EXCL0200|O_BINARY0, 0666);
759 if (fd == -1 && errno(*__errno_location ()) == EEXIST17) {
760 fd = open(fname, O_RDWR02|O_BINARY0);
761 }
762 }
763 return fd;
764}
765
766/* Format a size (in KiB) as a human-readable string. Caller frees. */
767char *
768format_size(size_t v)
769{
770 char *s;
771 if (v >= 1024*1024) {
772 s = format("%.1f Gbytes", v/((double)(1024*1024)));
773 } else if (v >= 1024) {
774 s = format("%.1f Mbytes", v/((double)(1024)));
775 } else {
776 s = format("%.0f Kbytes", (double)v);
777 }
778 return s;
779}
780
781/* return a value in multiples of 1024 give a string that can end
782 in K, M or G
783*/
784size_t
785value_units(const char *s)
786{
787 char m;
788 double v = atof(s);
789 m = s[strlen(s)-1];
790 switch (m) {
791 case 'G':
792 case 'g':
793 default:
794 v *= 1024*1024;
795 break;
796 case 'M':
797 case 'm':
798 v *= 1024;
799 break;
800 case 'K':
801 case 'k':
802 v *= 1;
803 break;
804 }
805 return (size_t)v;
806}
807
808#ifndef _WIN32
809static long
810path_max(const char *path)
811{
812#ifdef PATH_MAX4096
813 (void)path;
814 return PATH_MAX4096;
815#elif defined(MAXPATHLEN)
816 (void)path;
817 return MAXPATHLEN;
818#elif defined(_PC_PATH_MAX_PC_PATH_MAX)
819 long maxlen = pathconf(path, _PC_PATH_MAX_PC_PATH_MAX);
820 if (maxlen >= 4096) {
821 return maxlen;
822 } else {
823 return 4096;
824 }
825#endif
826}
827
828/*
829 a sane realpath() function, trying to cope with stupid path limits and
830 a broken API
831*/
832char *
833x_realpath(const char *path)
834{
835 long maxlen = path_max(path);
836 char *ret, *p;
837
838 ret = x_malloc(maxlen);
839
840#if HAVE_REALPATH1
841 p = realpath(path, ret);
842#else
843 /* yes, there are such systems. This replacement relies on
844 the fact that when we call x_realpath we only care about symlinks */
845 {
846 int len = readlink(path, ret, maxlen-1);
847 if (len == -1) {
848 free(ret);
849 return NULL((void*)0);
850 }
851 ret[len] = 0;
852 p = ret;
853 }
854#endif
855 if (p) {
856 p = x_strdup(p);
857 free(ret);
858 return p;
859 }
860 free(ret);
861 return NULL((void*)0);
862}
863#endif /* !_WIN32 */
864
865/* a getcwd that will returns an allocated buffer */
866char *
867gnu_getcwd(void)
868{
869 unsigned size = 128;
870
871 while (1) {
872 char *buffer = (char *)x_malloc(size);
873 if (getcwd(buffer, size) == buffer) {
874 return buffer;
875 }
876 free(buffer);
877 if (errno(*__errno_location ()) != ERANGE34) {
878 cc_log("getcwd error: %d (%s)", errno(*__errno_location ()), strerror(errno(*__errno_location ())));
879 return NULL((void*)0);
880 }
881 size *= 2;
882 }
883}
884
885/* create an empty file */
886int
887create_empty_file(const char *fname)
888{
889 int fd;
890
891 fd = open(fname, O_WRONLY01|O_CREAT0100|O_TRUNC01000|O_EXCL0200|O_BINARY0, 0666);
892 if (fd == -1) {
893 return -1;
894 }
895 close(fd);
896 return 0;
897}
898
899/*
900 * Return current user's home directory, or NULL if it can't be determined.
901 */
902const char *
903get_home_directory(void)
904{
905 const char *p = getenv("HOME");
906 if (p) {
907 return p;
908 }
909#ifdef HAVE_GETPWUID1
910 {
911 struct passwd *pwd = getpwuid(getuid());
912 if (pwd) {
913 return pwd->pw_dir;
914 }
915 }
916#endif
917 return NULL((void*)0);
918}
919
920/*
921 * Get the current directory by reading $PWD. If $PWD isn't sane, gnu_getcwd()
922 * is used. Caller frees.
923 */
924char *
925get_cwd(void)
926{
927 char *pwd;
928 char *cwd;
929 struct stat st_pwd;
930 struct stat st_cwd;
931
932 cwd = gnu_getcwd();
933 if (!cwd) {
934 return NULL((void*)0);
935 }
936 pwd = getenv("PWD");
937 if (!pwd) {
938 return cwd;
939 }
940 if (stat(pwd, &st_pwd) != 0) {
941 return cwd;
942 }
943 if (stat(cwd, &st_cwd) != 0) {
944 return cwd;
945 }
946 if (st_pwd.st_dev == st_cwd.st_dev && st_pwd.st_ino == st_cwd.st_ino) {
947 free(cwd);
948 return x_strdup(pwd);
949 } else {
950 return cwd;
951 }
952}
953
954/*
955 * Check whether s1 and s2 have the same executable name.
956 */
957bool_Bool
958same_executable_name(const char *s1, const char *s2)
959{
960#ifdef _WIN32
961 bool_Bool eq = strcasecmp(s1, s2) == 0;
962 if (!eq) {
963 char *tmp = format("%s.exe", s2);
964 eq = strcasecmp(s1, tmp) == 0;
965 free(tmp);
966 }
967 return eq;
968#else
969 return str_eq(s1, s2)(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((s1)) && __builtin_constant_p ((s2)) && (__s1_len
= strlen ((s1)), __s2_len = strlen ((s2)), (!((size_t)(const
void *)(((s1)) + 1) - (size_t)(const void *)((s1)) == 1) || __s1_len
>= 4) && (!((size_t)(const void *)(((s2)) + 1) - (
size_t)(const void *)((s2)) == 1) || __s2_len >= 4)) ? __builtin_strcmp
((s1), (s2)) : (__builtin_constant_p ((s1)) && ((size_t
)(const void *)(((s1)) + 1) - (size_t)(const void *)((s1)) ==
1) && (__s1_len = strlen ((s1)), __s1_len < 4) ? (
__builtin_constant_p ((s2)) && ((size_t)(const void *
)(((s2)) + 1) - (size_t)(const void *)((s2)) == 1) ? __builtin_strcmp
((s1), (s2)) : (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) ((s2)); int __result =
(((const unsigned char *) (const char *) ((s1)))[0] - __s2[0
]); if (__s1_len > 0 && __result == 0) { __result =
(((const unsigned char *) (const char *) ((s1)))[1] - __s2[1
]); if (__s1_len > 1 && __result == 0) { __result =
(((const unsigned char *) (const char *) ((s1)))[2] - __s2[2
]); if (__s1_len > 2 && __result == 0) __result = (
((const unsigned char *) (const char *) ((s1)))[3] - __s2[3])
; } } __result; }))) : (__builtin_constant_p ((s2)) &&
((size_t)(const void *)(((s2)) + 1) - (size_t)(const void *)
((s2)) == 1) && (__s2_len = strlen ((s2)), __s2_len <
4) ? (__builtin_constant_p ((s1)) && ((size_t)(const
void *)(((s1)) + 1) - (size_t)(const void *)((s1)) == 1) ? __builtin_strcmp
((s1), (s2)) : (- (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) ((s1)); int __result
= (((const unsigned char *) (const char *) ((s2)))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((s2)))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((s2)))[2] - __s2
[2]); if (__s2_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) ((s2)))[3] - __s2[3
]); } } __result; })))) : __builtin_strcmp ((s1), (s2))))); }
) == 0)
;
970#endif
971}
972
973/*
974 * Compute the length of the longest directory path that is common to two
975 * paths. s1 is assumed to be the path to a directory.
976 */
977size_t
978common_dir_prefix_length(const char *s1, const char *s2)
979{
980 const char *p1 = s1;
981 const char *p2 = s2;
982
983 while (*p1 && *p2 && *p1 == *p2) {
984 ++p1;
985 ++p2;
986 }
987 if (*p2 == '/') {
988 /* s2 starts with "s1/". */
989 return p1 - s1;
990 }
991 if (!*p2) {
992 /* s2 is equal to s1. */
993 if (p2 == s2 + 1) {
994 /* Special case for s1 and s2 both being "/". */
995 return 0;
996 } else {
997 return p1 - s1;
998 }
999 }
1000 /* Compute the common directory prefix */
1001 while (p1 > s1 && *p1 != '/') {
1002 p1--;
1003 p2--;
1004 }
1005 return p1 - s1;
1006}
1007
1008/*
1009 * Compute a relative path from from (an absolute path to a directory) to to (a
1010 * path). Assumes that both from and to are well-formed and canonical. Caller
1011 * frees.
1012 */
1013char *
1014get_relative_path(const char *from, const char *to)
1015{
1016 size_t common_prefix_len;
1017 int i;
1018 const char *p;
1019 char *result;
1020
1021 assert(from && from[0] == '/')((from && from[0] == '/') ? (void) (0) : __assert_fail
("from && from[0] == '/'", "util.c", 1021, __PRETTY_FUNCTION__
))
;
1022 assert(to)((to) ? (void) (0) : __assert_fail ("to", "util.c", 1022, __PRETTY_FUNCTION__
))
;
1023
1024 if (!*to || *to != '/') {
1025 return x_strdup(to);
1026 }
1027
1028 result = x_strdup("");
1029 common_prefix_len = common_dir_prefix_length(from, to);
1030 if (common_prefix_len > 0 || !str_eq(from, "/")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((from)) && __builtin_constant_p (("/")) && (
__s1_len = strlen ((from)), __s2_len = strlen (("/")), (!((size_t
)(const void *)(((from)) + 1) - (size_t)(const void *)((from)
) == 1) || __s1_len >= 4) && (!((size_t)(const void
*)((("/")) + 1) - (size_t)(const void *)(("/")) == 1) || __s2_len
>= 4)) ? __builtin_strcmp ((from), ("/")) : (__builtin_constant_p
((from)) && ((size_t)(const void *)(((from)) + 1) - (
size_t)(const void *)((from)) == 1) && (__s1_len = strlen
((from)), __s1_len < 4) ? (__builtin_constant_p (("/")) &&
((size_t)(const void *)((("/")) + 1) - (size_t)(const void *
)(("/")) == 1) ? __builtin_strcmp ((from), ("/")) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (("/")); int __result = (((const unsigned char *) (const
char *) ((from)))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((from)))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((from)))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((from)))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(("/")) && ((size_t)(const void *)((("/")) + 1) - (size_t
)(const void *)(("/")) == 1) && (__s2_len = strlen ((
"/")), __s2_len < 4) ? (__builtin_constant_p ((from)) &&
((size_t)(const void *)(((from)) + 1) - (size_t)(const void *
)((from)) == 1) ? __builtin_strcmp ((from), ("/")) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((from)); int __result = (((const unsigned char *) (
const char *) (("/")))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (("/")))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (("/")))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (("/")))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
((from), ("/"))))); }) == 0)
) {
1031 for (p = from + common_prefix_len; *p; p++) {
1032 if (*p == '/') {
1033 x_asprintf2(&result, "../%s", result);
1034 }
1035 }
1036 }
1037 if (strlen(to) > common_prefix_len) {
1038 x_asprintf2(&result, "%s%s", result, to + common_prefix_len + 1);
1039 }
1040 i = strlen(result) - 1;
1041 while (i >= 0 && result[i] == '/') {
1042 result[i] = '\0';
1043 i--;
1044 }
1045 if (str_eq(result, "")(__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((result)) && __builtin_constant_p (("")) &&
(__s1_len = strlen ((result)), __s2_len = strlen (("")), (!(
(size_t)(const void *)(((result)) + 1) - (size_t)(const void *
)((result)) == 1) || __s1_len >= 4) && (!((size_t)
(const void *)((("")) + 1) - (size_t)(const void *)(("")) == 1
) || __s2_len >= 4)) ? __builtin_strcmp ((result), ("")) :
(__builtin_constant_p ((result)) && ((size_t)(const void
*)(((result)) + 1) - (size_t)(const void *)((result)) == 1) &&
(__s1_len = strlen ((result)), __s1_len < 4) ? (__builtin_constant_p
(("")) && ((size_t)(const void *)((("")) + 1) - (size_t
)(const void *)(("")) == 1) ? __builtin_strcmp ((result), (""
)) : (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (("")); int __result = (((const unsigned
char *) (const char *) ((result)))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ((result)))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) ((result)))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ((result)))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (("")) && ((size_t)(const
void *)((("")) + 1) - (size_t)(const void *)(("")) == 1) &&
(__s2_len = strlen (("")), __s2_len < 4) ? (__builtin_constant_p
((result)) && ((size_t)(const void *)(((result)) + 1
) - (size_t)(const void *)((result)) == 1) ? __builtin_strcmp
((result), ("")) : (- (__extension__ ({ const unsigned char *
__s2 = (const unsigned char *) (const char *) ((result)); int
__result = (((const unsigned char *) (const char *) (("")))[
0] - __s2[0]); if (__s2_len > 0 && __result == 0) {
__result = (((const unsigned char *) (const char *) (("")))[
1] - __s2[1]); if (__s2_len > 1 && __result == 0) {
__result = (((const unsigned char *) (const char *) (("")))[
2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (("")))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp ((result), (""))
))); }) == 0)
) {
1046 free(result);
1047 result = x_strdup(".");
1048 }
1049 return result;
1050}
1051
1052/*
1053 * Return whether path is absolute.
1054 */
1055bool_Bool
1056is_absolute_path(const char *path)
1057{
1058#ifdef _WIN32
1059 return path[0] && path[1] == ':';
1060#else
1061 return path[0] == '/';
1062#endif
1063}
1064
1065/*
1066 * Return whether the argument is a full path.
1067 */
1068bool_Bool
1069is_full_path(const char *path)
1070{
1071 if (strchr(path, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p
(path) && ('/') == '\0' ? (char *) __rawmemchr (path
, '/') : __builtin_strchr (path, '/')))
)
1072 return 1;
1073#ifdef _WIN32
1074 if (strchr(path, '\\')(__extension__ (__builtin_constant_p ('\\') && !__builtin_constant_p
(path) && ('\\') == '\0' ? (char *) __rawmemchr (path
, '\\') : __builtin_strchr (path, '\\')))
)
1075 return 1;
1076#endif
1077 return 0;
1078}
1079
1080/*
1081 * Update the modification time of a file in the cache to save it from LRU
1082 * cleanup.
1083 */
1084void
1085update_mtime(const char *path)
1086{
1087#ifdef HAVE_UTIMES1
1088 utimes(path, NULL((void*)0));
1089#else
1090 utime(path, NULL((void*)0));
1091#endif
1092}
1093
1094/*
1095 * Rename oldpath to newpath (deleting newpath).
1096 */
1097int
1098x_rename(const char *oldpath, const char *newpath)
1099{
1100#ifdef _WIN32
1101 /* Windows' rename() refuses to overwrite an existing file. */
1102 unlink(newpath); /* not x_unlink, as x_unlink calls x_rename */
1103#endif
1104 return rename(oldpath, newpath);
1105}
1106
1107/*
1108 * Remove path, NFS hazardous. Use only for temporary files that will not exist
1109 * on other systems. That is, the path should include tmp_string().
1110 */
1111int
1112tmp_unlink(const char *path)
1113{
1114 cc_log("Unlink %s (as-tmp)", path);
1115 return unlink(path);
1116}
1117
1118/*
1119 * Remove path, NFS safe.
1120 */
1121int
1122x_unlink(const char *path)
1123{
1124 /*
1125 * If path is on an NFS share, unlink isn't atomic, so we rename to a temp
1126 * file. We don't care if the temp file is trashed, so it's always safe to
1127 * unlink it first.
1128 */
1129 char *tmp_name = format("%s.tmp.rm.%s", path, tmp_string());
1130 int result = 0;
1131 cc_log("Unlink %s via %s", path, tmp_name);
1132 if (x_rename(path, tmp_name) == -1) {
1133 result = -1;
1134 goto out;
1135 }
1136 if (unlink(tmp_name) == -1) {
1137 result = -1;
1138 }
1139out:
1140 free(tmp_name);
1141 return result;
1142}
1143
1144#ifndef _WIN32
1145/* Like readlink() but returns the string or NULL on failure. Caller frees. */
1146char *
1147x_readlink(const char *path)
1148{
1149 long maxlen = path_max(path);
1150 ssize_t len;
1151 char *buf;
1152#ifdef PATH_MAX4096
1153 maxlen = PATH_MAX4096;
1154#elif defined(MAXPATHLEN)
1155 maxlen = MAXPATHLEN;
1156#elif defined(_PC_PATH_MAX_PC_PATH_MAX)
1157 maxlen = pathconf(path, _PC_PATH_MAX_PC_PATH_MAX);
1158#endif
1159 if (maxlen < 4096) maxlen = 4096;
1160
1161 buf = x_malloc(maxlen);
1162 len = readlink(path, buf, maxlen-1);
1163 if (len == -1) {
1164 free(buf);
1165 return NULL((void*)0);
1166 }
1167 buf[len] = 0;
1168 return buf;
1169}
1170#endif
1171
1172/*
1173 * Reads the content of a file. Size hint 0 means no hint. Returns true on
1174 * success, otherwise false.
1175 */
1176bool_Bool
1177read_file(const char *path, size_t size_hint, char **data, size_t *size)
1178{
1179 int fd, ret;
1180 size_t pos = 0, allocated;
1181
1182 if (size_hint == 0) {
1183 struct stat st;
1184 if (stat(path, &st) == 0) {
1185 size_hint = st.st_size;
1186 }
1187 }
1188 size_hint = (size_hint < 1024) ? 1024 : size_hint;
1189
1190 fd = open(path, O_RDONLY00);
1191 if (fd == -1) {
1192 return false0;
1193 }
1194 allocated = size_hint;
1195 *data = x_malloc(allocated);
1196 ret = 0;
Value stored to 'ret' is never read
1197 while (true1) {
1198 if (pos > allocated / 2) {
1199 allocated *= 2;
1200 *data = x_realloc(*data, allocated);
1201 }
1202 ret = read(fd, *data + pos, allocated - pos);
1203 if (ret == 0 || (ret == -1 && errno(*__errno_location ()) != EINTR4)) {
1204 break;
1205 }
1206 if (ret > 0) {
1207 pos += ret;
1208 }
1209 }
1210 close(fd);
1211 if (ret == -1) {
1212 cc_log("Failed reading %s", path);
1213 free(*data);
1214 *data = NULL((void*)0);
1215 return false0;
1216 }
1217
1218 *size = pos;
1219 return true1;
1220}
1221
1222/*
1223 * Return the content (with NUL termination) of a text file, or NULL on error.
1224 * Caller frees.
1225 */
1226char *
1227read_text_file(const char *path)
1228{
1229 size_t size;
1230 char *data;
1231
1232 if (read_file(path, 0, &data, &size)) {
1233 data = x_realloc(data, size + 1);
1234 data[size] = '\0';
1235 return data;
1236 } else {
1237 return NULL((void*)0);
1238 }
1239}