#include #include #include #include #include #include "util.h" /* This isn't a 1:1 wrapper around fgets. It also removes that annoying * trailing \n automatically */ char * xfgets(char *s, size_t size, FILE *stream) { char *p; if ((s = fgets(s, size, stream))) { if ((p = strchr(s, '\n'))) *p = '\0'; } else if (ferror(stream)) { fprintf(stderr, "fgets: %s\n", strerror(errno)); exit(1); } return s; } FILE * xfopen(const char *pathname, const char *mode) { FILE *f; if ((f = fopen(pathname, mode)) == NULL) { fprintf(stderr, "%s: %s\n", pathname, strerror(errno)); exit(1); } return f; } int xfputs(const char *s, FILE *stream) { int d; if ((d = fputs(s, stream)) == EOF) { fprintf(stderr, "fputs: %s\n", strerror(errno)); exit(1); } return d; } void * xmalloc(size_t size) { void *n; if ((n = malloc(size)) == NULL) { fprintf(stderr, "malloc: %s\n", strerror(errno)); exit(1); } return n; } void * xrealloc(void *ptr, size_t size) { void *n; if ((n = realloc(ptr, size)) == NULL) { fprintf(stderr, "malloc: %s\n", strerror(errno)); exit(1); } return n; } int mkparentdirs(const char *path) { char part[512]; int i; if (!path[0]) return 0; my_strlcpy(part, path, sizeof(part)); for (i = 1; part[i]; i++) { if (part[i] == '/' && part[i + 1] != '/' && part[i + 1]) { part[i] = '\0'; if (mkdir(part, 0755) < 0 && errno != EEXIST) { fprintf(stderr, "mkdir %s: %s\n", part, strerror(errno)); return 0; } part[i] = '/'; } } return 1; } /* strlcpy is unportable, and strncpy is a mess. So we define our own strlcpy * instead. */ size_t my_strlcpy(char *dst, const char *src, size_t size) { const char *p2; char *p1, *stop; p1 = dst; p2 = src; stop = dst + size; while (*p2 && p1 != stop) *p1++ = *p2++; *p1 = '\0'; return (size_t)(p1 - dst); }