2 Copyright (C) Andrew Tridgell 2002
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.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* log a message to the UCFRONT_LOGFILE location */
24 void cc_log(const char *format, ...)
27 extern char *cache_logfile;
29 if (!cache_logfile) return;
32 if (strcmp(cache_logfile, "stderr") == 0)
34 else if (strcmp(cache_logfile, "stdout") == 0)
37 logfile = fopen(cache_logfile, "a");
44 vfprintf(logfile, format, ap);
49 /* something went badly wrong! */
50 void fatal(const char *format, ...)
54 fprintf(stderr, "FATAL: ");
55 va_start(args, format);
56 vfprintf(stderr, format, args);
58 fprintf(stderr, "\n");
62 /* copy all data from one file descriptor to another */
63 void copy_fd(int fd_in, int fd_out)
68 while ((n = read(fd_in, buf, sizeof(buf))) > 0) {
69 if (write(fd_out, buf, n) != n) {
70 fatal("Failed to copy fd");
75 /* copy a file - used when hard links don't work
76 the copy is done via a temporary file and atomic rename
78 int copy_file(const char *src, const char *dest)
86 x_asprintf(&tmp_name, "%s.XXXXXX", dest);
88 fd1 = open(src, O_RDONLY);
94 fd2 = mkstemp(tmp_name);
101 while ((n = read(fd1, buf, sizeof(buf))) > 0) {
102 if (write(fd2, buf, n) != n) {
113 /* get perms right on the tmp file */
115 fchmod(fd2, 0666 & ~mask);
118 /* the close can fail on NFS if out of space */
119 if (close(fd2) == -1) {
127 if (rename(tmp_name, dest) == -1) {
139 /* make sure a directory exists */
140 int create_dir(const char *dir)
143 if (stat(dir, &st) == 0) {
144 if (S_ISDIR(st.st_mode)) {
150 if (mkdir(dir, 0777) != 0 && errno != EEXIST) {
157 this is like asprintf() but dies if the malloc fails
158 here we just use vasprintf() to do the work for us.
160 void x_asprintf(char **ptr, const char *format, ...)
165 va_start(ap, format);
166 if (vasprintf(ptr, format, ap) == -1) {
167 fatal("out of memory in x_asprintf");
174 this is like strdup() but dies if the malloc fails
176 char *x_strdup(const char *s)
181 fatal("out of memory in strdup\n");
187 this is like malloc() but dies if the malloc fails
189 void *x_malloc(size_t size)
194 fatal("out of memory in malloc\n");
200 this is like realloc() but dies if the malloc fails
202 void *x_realloc(void *ptr, size_t size)
205 if (!ptr) return x_malloc(size);
208 fatal("out of memory in x_realloc");
211 memcpy(p2, ptr, size);
219 revsusive directory traversal - used for cleanup
220 fn() is called on all files/dirs in the tree
222 void traverse(const char *dir, void (*fn)(const char *, struct stat *))
230 while ((de = readdir(d))) {
234 if (strcmp(de->d_name,".") == 0) continue;
235 if (strcmp(de->d_name,"..") == 0) continue;
237 if (strlen(de->d_name) == 0) continue;
239 x_asprintf(&fname, "%s/%s", dir, de->d_name);
240 if (lstat(fname, &st)) {
241 if (errno != ENOENT) {
248 if (S_ISDIR(st.st_mode)) {
260 /* return the base name of a file - caller frees */
261 char *str_basename(const char *s)
263 char *p = strrchr(s, '/');
265 return x_strdup(p+1);
271 /* return the dir name of a file - caller frees */
272 char *dirname(char *s)
289 fl.l_whence = SEEK_SET;
294 /* not sure why we would be getting a signal here,
295 but one user claimed it is possible */
297 ret = fcntl(fd, F_SETLKW, &fl);
298 } while (ret == -1 && errno == EINTR);
302 /* return size on disk of a file */
303 size_t file_size(struct stat *st)
305 size_t size = st->st_blocks * 512;
306 if ((size_t)st->st_size > size) {
307 /* probably a broken stat() call ... */
308 size = (st->st_size + 1023) & ~1023;
314 /* a safe open/create for read-write */
315 int safe_open(const char *fname)
317 int fd = open(fname, O_RDWR);
318 if (fd == -1 && errno == ENOENT) {
319 fd = open(fname, O_RDWR|O_CREAT|O_EXCL, 0666);
320 if (fd == -1 && errno == EEXIST) {
321 fd = open(fname, O_RDWR);
327 /* display a kilobyte unsigned value in M, k or G */
328 void display_size(unsigned v)
331 printf("%8.1f Gbytes", v/((double)(1024*1024)));
332 } else if (v > 1024) {
333 printf("%8.1f Mbytes", v/((double)(1024)));
335 printf("%8u Kbytes", v);
339 /* return a value in multiples of 1024 give a string that can end
342 size_t value_units(const char *s)
367 a sane realpath() function, trying to cope with stupid path limits and
370 char *x_realpath(const char *path)
376 #elif defined(MAXPATHLEN)
378 #elif defined(_PC_PATH_MAX)
379 maxlen = pathconf(path, _PC_PATH_MAX);
381 if (maxlen < 4096) maxlen = 4096;
383 ret = x_malloc(maxlen);
386 p = realpath(path, ret);
388 /* yes, there are such systems. This replacement relies on
389 the fact that when we call x_realpath we only care about symlinks */
391 int len = readlink(path, ret, maxlen-1);
409 /* a getcwd that will returns an allocated buffer */
410 char *gnu_getcwd(void)
415 char *buffer = (char *)x_malloc(size);
416 if (getcwd(buffer, size) == buffer) {
420 if (errno != ERANGE) {
428 /* cheap and nasty mkstemp replacement */
429 int mkstemp(char *template)
432 return open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
437 /* create an empty file */
438 int create_empty_file(const char *fname)
442 fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0666);