diff options
author | Tharre <tharre3@gmail.com> | 2014-11-16 19:19:59 +0100 |
---|---|---|
committer | Tharre <tharre3@gmail.com> | 2014-11-16 19:19:59 +0100 |
commit | df9bc5b9d048c7ecb96838123e39d5bc7c23aa18 (patch) | |
tree | 5432d5cc4a0e5a7550f7bae00964f09cb68b6361 | |
parent | b4c1b2145d6a0b1ec4219847dc26877046f84e8b (diff) | |
download | redo-df9bc5b9d048c7ecb96838123e39d5bc7c23aa18.tar.gz redo-df9bc5b9d048c7ecb96838123e39d5bc7c23aa18.tar.xz redo-df9bc5b9d048c7ecb96838123e39d5bc7c23aa18.zip |
Refactor error handling system by using die()
Defined error messages have also been replaced with string literals.
-rw-r--r-- | src/build.c | 97 | ||||
-rw-r--r-- | src/build.h | 2 | ||||
-rw-r--r-- | src/dbg.h | 7 | ||||
-rw-r--r-- | src/filepath.c | 14 | ||||
-rw-r--r-- | src/redo.c | 6 | ||||
-rw-r--r-- | src/util.c | 45 | ||||
-rw-r--r-- | src/util.h | 32 |
7 files changed, 91 insertions, 112 deletions
diff --git a/src/build.c b/src/build.c index c002cc8..072451b 100644 --- a/src/build.c +++ b/src/build.c @@ -46,7 +46,7 @@ struct do_attr { /* Build given target, using it's do-file. */ -int build_target(const char *target) { +void build_target(const char *target) { /* get the do-file which we are going to execute */ struct do_attr *dofiles = get_dofiles(target); if (!dofiles->chosen) { @@ -55,12 +55,10 @@ int build_target(const char *target) { then we treat it as a source */ write_dep_hash(target); free_do_attr(dofiles); - return 0; + return; } - log_err("'%s' couldn't be built because no " - "suitable do-file exists\n", target); - free_do_attr(dofiles); - return 1; + + die("%s couldn't be built as no suitable do-file exists\n", target); } char *reltarget = get_relpath(target); @@ -71,7 +69,7 @@ int build_target(const char *target) { char *dep_file = get_dep_path(target); if (remove(dep_file)) if (errno != ENOENT) - fatal(ERRM_REMOVE, dep_file); + diem("redo: failed to remove %s", dep_file); free(dep_file); char *temp_output = concat(2, target, ".redoing.tmp"); @@ -79,15 +77,15 @@ int build_target(const char *target) { pid_t pid = fork(); if (pid == -1) { /* failure */ - fatal(ERRM_FORK); + diem("redo: failed to fork() new process"); } else if (pid == 0) { /* child */ /* change directory to our target */ - char *dirc = safe_strdup(target); + char *dirc = xstrdup(target); char *dtarget = dirname(dirc); if (chdir(dtarget) == -1) - fatal(ERRM_CHDIR, dtarget); + diem("redo: failed to change directory to %s", dtarget); free(dirc); @@ -100,7 +98,7 @@ int build_target(const char *target) { /* set "REDO_PARENT_TARGET" */ if (setenv("REDO_PARENT_TARGET", target, 1)) - fatal(ERRM_SETENV, "REDO_PARENT_TARGET", target); + diem("redo: failed to setenv() REDO_PARENT_TARGET to %s", target); /* excelp() has nearly everything we want: automatic parsing of the shebang line through execve() and fallback to /bin/sh if no valid @@ -110,20 +108,19 @@ int build_target(const char *target) { execv(argv[0], argv); /* execv should never return */ - fatal(ERRM_EXEC, argv[0]); + diem("redo: failed to replace child process with %s", argv[0]); } /* parent */ int status; if (waitpid(pid, &status, 0) == -1) - fatal("waitpid() failed: "); + diem("waitpid() failed: "); bool remove_temp = true; if (WIFEXITED(status)) { if (WEXITSTATUS(status)) { - log_err("redo: invoked do-file %s failed: %d\n", - dofiles->chosen, WEXITSTATUS(status)); - exit(EXIT_FAILURE); + die("redo: invoked do-file %s failed: %d\n", dofiles->chosen, + WEXITSTATUS(status)); } else { /* successful */ @@ -133,8 +130,7 @@ int build_target(const char *target) { } } else { /* something very wrong happened with the child */ - log_err("redo: invoked do-file did not terminate correctly\n"); - exit(EXIT_FAILURE); + die("redo: invoked do-file did not terminate correctly\n"); } /* depend on the do-file */ @@ -153,18 +149,16 @@ int build_target(const char *target) { if (remove_temp) { if (remove(temp_output)) if (errno != ENOENT) - fatal(ERRM_REMOVE, temp_output); + diem("redo: failed to remove %s", temp_output); } else { if (rename(temp_output, target)) - fatal(ERRM_RENAME, temp_output, target); + diem("redo: failed to rename %s to %s", temp_output, target); write_dep_hash(target); } free(temp_output); free_do_attr(dofiles); - - return 0; } /* Read and parse shebang and return an argv-like pointer array containing the @@ -172,13 +166,13 @@ int build_target(const char *target) { static char **parse_shebang(char *target, char *dofile, char *temp_output) { FILE *fp = fopen(dofile, "rb"); if (!fp) - fatal(ERRM_FOPEN, dofile); + diem("redo: failed to open %s", dofile); char buf[1024]; buf[ fread(buf, 1, sizeof(buf)-1, fp) ] = '\0'; if (ferror(fp)) - fatal(ERRM_FREAD, dofile); + diem("redo: failed to read from %s", dofile); fclose(fp); @@ -187,13 +181,13 @@ static char **parse_shebang(char *target, char *dofile, char *temp_output) { if (buf[0] == '#' && buf[1] == '!') { argv = parsecmd(&buf[2], &i, 5); } else { - argv = safe_malloc(7 * sizeof(char*)); + argv = xmalloc(7 * sizeof(char*)); argv[i++] = "/bin/sh"; argv[i++] = "-e"; } argv[i++] = dofile; - argv[i++] = (char*) target; + argv[i++] = target; char *basename = remove_ext(target); argv[i++] = basename; argv[i++] = temp_output; @@ -204,14 +198,14 @@ static char **parse_shebang(char *target, char *dofile, char *temp_output) { /* Return a struct with all the possible do-files, and the chosen one. */ static struct do_attr *get_dofiles(const char *target) { - struct do_attr *dofiles = safe_malloc(sizeof(struct do_attr)); + struct do_attr *dofiles = xmalloc(sizeof(struct do_attr)); dofiles->specific = concat(2, target, ".do"); if (!is_absolute(target)) { dofiles->general = concat(3, "default", take_extension(target), ".do"); - dofiles->redofile = safe_strdup("Redofile"); + dofiles->redofile = xstrdup("Redofile"); } else { - char *dirc = safe_strdup(target); + char *dirc = xstrdup(target); char *dt = dirname(dirc); dofiles->general = concat(4, dt, "/default", take_extension(target), ".do"); @@ -244,7 +238,7 @@ static void free_do_attr(struct do_attr *thing) { returned array is guaranteed to have at least keep_free entries left. */ static char **parsecmd(char *cmd, size_t *i, size_t keep_free) { size_t argv_len = 16; - char **argv = safe_malloc(argv_len * sizeof(char*)); + char **argv = xmalloc(argv_len * sizeof(char*)); size_t j = 0; bool prev_space = true; for (;; ++j) { @@ -265,7 +259,7 @@ static char **parsecmd(char *cmd, size_t *i, size_t keep_free) { while (*i+keep_free >= argv_len) { argv_len *= 2; debug("Reallocating memory (now %zu elements)\n", argv_len); - argv = safe_realloc(argv, argv_len * sizeof(char*)); + argv = xrealloc(argv, argv_len * sizeof(char*)); } prev_space = false; @@ -278,7 +272,7 @@ static char **parsecmd(char *cmd, size_t *i, size_t keep_free) { /* Custom version of realpath that doesn't fail if the last part of path doesn't exist and allocates memory for the result itself. */ static char *xrealpath(const char *path) { - char *dirc = safe_strdup(path); + char *dirc = xstrdup(path); char *dname = dirname(dirc); char *absdir = realpath(dname, NULL); if (!absdir) @@ -298,9 +292,9 @@ static char *get_relpath(const char *target) { char *abstarget = xrealpath(target); if (!abstarget) - fatal(ERRM_REALPATH, target); + diem("redo: failed to get realpath() of %s", target); - char *relpath = safe_strdup(make_relative(root, abstarget)); + char *relpath = xstrdup(make_relative(root, abstarget)); free(abstarget); return relpath; } @@ -311,11 +305,11 @@ static char *get_dep_path(const char *target) { char *root = getenv("REDO_ROOT"); char *reltarget = get_relpath(target); - char *safe_target = transform_path(reltarget); - char *dep_path = concat(3, root, "/.redo/deps/", safe_target); + char *xtarget = transform_path(reltarget); + char *dep_path = concat(3, root, "/.redo/deps/", xtarget); free(reltarget); - free(safe_target); + free(xtarget); return dep_path; } @@ -334,11 +328,11 @@ void add_dep(const char *target, const char *parent, int ident) { if (errno == ENOENT) { fp = fopen(dep_path, "w"); if (!fp) - fatal(ERRM_FOPEN, dep_path); + diem("redo: failed to open %s", dep_path); /* skip the first n bytes that are reserved for the hash + magic number */ fseek(fp, HASHSIZE + sizeof(unsigned int), SEEK_SET); } else { - fatal(ERRM_FOPEN, dep_path); + diem("redo: failed to open %s", dep_path); } } else { fseek(fp, 0L, SEEK_END); @@ -351,10 +345,10 @@ void add_dep(const char *target, const char *parent, int ident) { putc('\0', fp); if (ferror(fp)) - fatal(ERRM_WRITE, dep_path); + diem("redo: failed to write to %s", dep_path); if (fclose(fp)) - fatal(ERRM_FCLOSE, dep_path); + diem("redo: failed to close %s", dep_path); free(dep_path); free(reltarget); } @@ -363,7 +357,7 @@ void add_dep(const char *target, const char *parent, int ident) { static void hash_file(const char *target, unsigned char *hash) { FILE *in = fopen(target, "rb"); if (!in) - fatal(ERRM_FOPEN, target); + diem("redo: failed to open %s", target); SHA_CTX context; unsigned char data[8192]; @@ -374,7 +368,7 @@ static void hash_file(const char *target, unsigned char *hash) { SHA1_Update(&context, data, read); if (ferror(in)) - fatal(ERRM_FREAD, target); + diem("redo: failed to read from %s", target); SHA1_Final(hash, &context); fclose(in); } @@ -391,16 +385,16 @@ static void write_dep_hash(const char *target) { char *dep_path = get_dep_path(target); int out = open(dep_path, O_WRONLY | O_CREAT, 0644); if (out < 0) - fatal(ERRM_FOPEN, dep_path); + diem("redo: failed to open %s", dep_path); if (write(out, &magic, sizeof(unsigned)) < (ssize_t) sizeof(unsigned)) - fatal("redo: failed to write magic number to '%s'", dep_path); + diem("redo: failed to write magic number to '%s'", dep_path); if (write(out, hash, sizeof hash) < (ssize_t) sizeof hash) - fatal("redo: failed to write hash to '%s'", dep_path); + diem("redo: failed to write hash to '%s'", dep_path); if (close(out)) - fatal(ERRM_FCLOSE, dep_path); + diem("redo: failed to close %s", dep_path); free(dep_path); } @@ -437,13 +431,13 @@ int update_target(const char *target, int ident) { build_target(target); return 1; } else { - fatal(ERRM_FOPEN, dep_path); + diem("redo: failed to open %s", dep_path); } } char buf[8096]; if (fread(buf, 1, HEADERSIZE, fp) < HEADERSIZE) - fatal("redo: failed to read %zu bytes from %s", HEADERSIZE, dep_path); + diem("redo: failed to read %zu bytes from %s", HEADERSIZE, dep_path); free(dep_path); @@ -466,7 +460,7 @@ int update_target(const char *target, int ident) { size_t read = fread(buf, 1, sizeof buf, fp); if (ferror(fp)) - fatal("redo: failed to read %zu bytes from file descriptor", sizeof buf); + diem("redo: failed to read %zu bytes from file descriptor", sizeof buf); char *ptr = buf; for (size_t i = 0; i < read; ++i) { @@ -501,8 +495,7 @@ int update_target(const char *target, int ident) { return 0; default: - log_err("Unknown identifier '%c'\n", ident); - exit(EXIT_FAILURE); + die("redo: unknown identiier '%c'\n", ident); } } diff --git a/src/build.h b/src/build.h index e4ef626..0eae0f3 100644 --- a/src/build.h +++ b/src/build.h @@ -13,7 +13,7 @@ extern void add_dep(const char *target, const char *parent, int ident); extern int update_target(const char *target, int ident); -extern int build_target(const char *target); +extern void build_target(const char *target); extern bool environment_sane(); #endif @@ -22,9 +22,6 @@ /* helper functions which help in replacing the GNU extension ##__VA_ARGS__ */ #define STRINGIFY(x) #x #define LOG_HELPER(f,l,...) fprintf(stderr, "("f":"STRINGIFY(l)"): "__VA_ARGS__) -#define FATAL_HELPER(M, ...) log_err(M ": %s\n", __VA_ARGS__) -#define FATAL_HELPER_(f,l,M,...) \ - fprintf(stderr, "(%s:%u): " M ": %s\n", f, l, __VA_ARGS__) #ifdef NDEBUG #define debug(...) @@ -33,10 +30,6 @@ #endif #define log_err(...) LOG_HELPER(_FILENAME, __LINE__, __VA_ARGS__) -#define fatal(...) \ - ({FATAL_HELPER(__VA_ARGS__, strerror(errno)); exit(EXIT_FAILURE);}) -#define fatal_(f,l,...) \ - ({FATAL_HELPER_(f, l, __VA_ARGS__, strerror(errno)); exit(EXIT_FAILURE);}) #define assert_str_equal(a,b) ({ \ if (strcmp(a, b)) { \ diff --git a/src/filepath.c b/src/filepath.c index 7d73b60..6aca4a7 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -36,7 +36,7 @@ char *remove_ext(const char *str) { if (dot) /* recalculate length to only reach just before the last dot */ len = dot - str; - ret = safe_malloc(len+1); + ret = xmalloc(len+1); memcpy(ret, str, len); ret[len] = '\0'; @@ -83,7 +83,7 @@ char *transform_path(const char *target) { while (*ptr++) if (*ptr == '!') escape++; - ptr = safe_malloc((ptr-target) + escape + 1); + ptr = xmalloc((ptr-target) + escape + 1); do { if (*target == '/') ptr[i++] = '!'; @@ -121,7 +121,7 @@ off_t fsize(const char *fn) { struct stat st; if (stat(fn, &st)) { if (errno != ENOENT) - fatal(ERRM_STAT, fn); + diem("redo: failed to aquire stat() information about %s", fn); return -1; } @@ -136,16 +136,16 @@ bool mkdirp(const char *dir) { if (stat(dir, &st)) { /* dir doesn't exist or stat failed */ if (errno != ENOENT) - fatal(ERRM_STAT, dir); + diem("redo: failed to aquire stat() information about %s", dir); if (mkdir(dir, 0755)) - fatal(ERRM_MKDIR, dir); + diem("redo: failed to mkdir() '%s'", dir); return 1; } else { if (!S_ISDIR(st.st_mode)) { if (remove(dir)) - fatal(ERRM_REMOVE, dir); + diem("redo: failed to remove %s", dir); if (mkdir(dir, 0755)) - fatal(ERRM_MKDIR, dir); + diem("redo: failed to mkdir() '%s'", dir); return 1; } return 0; @@ -34,9 +34,9 @@ void prepare_env() { /* set REDO_ROOT */ char *cwd = getcwd(NULL, 0); if (!cwd) - fatal("redo: failed to obtain cwd"); + diem("redo: failed to obtain cwd"); if (setenv("REDO_ROOT", cwd, 0)) - fatal("redo: failed to setenv REDO_ROOT to %s", cwd); + diem("redo: failed to setenv REDO_ROOT to %s", cwd); free(cwd); /* set REDO_MAGIC */ @@ -44,7 +44,7 @@ void prepare_env() { char magic_str[digits(UINT_MAX) + 1]; sprintf(magic_str, "%u", rand()); if (setenv("REDO_MAGIC", magic_str, 0)) - fatal("setenv()"); + diem("redo: failed to setenv() REDO_MAGIC to %s", magic_str); } int main(int argc, char *argv[]) { @@ -6,44 +6,57 @@ * of the MIT license. See the LICENSE file for details. */ +#define _XOPEN_SOURCE 500 +#include <assert.h> +#include <errno.h> #include <stdarg.h> #include <stdint.h> -#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include "util.h" #define _FILENAME "util.c" #include "dbg.h" -void *safe_malloc_(size_t size, const char *file, unsigned line) { +/* Print a given formated error message and die. */ +extern void __attribute__((noreturn)) die(const char *err, ...) { + assert(err); + va_list ap; + va_start(ap, err); + + vfprintf(stderr, err, ap); + + va_end(ap); + exit(EXIT_FAILURE); +} + +void *xmalloc(size_t size) { assert(size > 0); void *ptr = malloc(size); if (!ptr) - fatal_(file, line, ERRM_MALLOC, size); + diem("Cannot allocate %zu bytes", size); return ptr; } -void *safe_realloc_(void *ptr, size_t size, const char *file, unsigned line) { +void *xrealloc(void *ptr, size_t size) { assert(size > 0 && ptr); - void *ptr2 = realloc(ptr, size); - if (!ptr2) - fatal_(file, line, ERRM_REALLOC, size); + if (!(ptr = realloc(ptr, size))) + diem("Cannot reallocate %zu bytes", size); - return ptr2; + return ptr; } -char *safe_strdup_(const char *str, const char *file, unsigned line) { +char *xstrdup(const char *str) { assert(str); - size_t len = strlen(str) + 1; - char *ptr = malloc(len); - if (!ptr) - fatal_(file, line, ERRM_MALLOC, len); + if (!(str = strdup(str))) + diem("Insufficient memory for string allocation"); - return memcpy(ptr, str, len); + return (char*) str; } - /* For concating multiple strings into a single larger one. */ char *concat(size_t count, ...) { assert(count > 0); @@ -56,7 +69,7 @@ char *concat(size_t count, ...) { size += args_len[i]; } ++size; - char *result = safe_malloc(size); + char *result = xmalloc(size); /* debug("Allocated %zu bytes at %p\n", size, result); */ uintptr_t offset = 0; for (i = 0; i < count; ++i) { @@ -9,35 +9,15 @@ #ifndef __RUTIL_H__ #define __RUTIL_H__ -#include <stdbool.h> #include <stddef.h> -/* standard error messages */ -#define _PROGNAME "redo" +#define DIE_HELPER(M, ...) die(M ": %s\n", __VA_ARGS__) +#define diem(...) DIE_HELPER(__VA_ARGS__, strerror(errno)) -#define ERRM_MALLOC _PROGNAME": cannot allocate %zu bytes" -#define ERRM_REALLOC _PROGNAME": cannot reallocate %zu bytes" -#define ERRM_FOPEN _PROGNAME": failed to open %s" -#define ERRM_FREAD _PROGNAME": failed to read from %s" -#define ERRM_FCLOSE _PROGNAME": failed to close %s" -#define ERRM_WRITE _PROGNAME": failed to write to %s" -#define ERRM_CHDIR _PROGNAME": failed to change directory to %s" -#define ERRM_SETENV _PROGNAME": failed to setenv %s to %s" -#define ERRM_EXEC _PROGNAME": failed to replace child process with %s" -#define ERRM_REMOVE _PROGNAME": failed to remove %s" -#define ERRM_RENAME _PROGNAME": failed to rename %s to %s" -#define ERRM_FORK _PROGNAME": failed to fork() new process" -#define ERRM_REALPATH _PROGNAME": failed to get realpath() of %s" -#define ERRM_STAT _PROGNAME": failed to aquire stat() information about %s" -#define ERRM_MKDIR _PROGNAME": failed to mkdir() '%s'" - -#define safe_malloc(size) safe_malloc_(size, _FILENAME, __LINE__) -#define safe_realloc(ptr, size) safe_realloc_(ptr, size, _FILENAME, __LINE__) -#define safe_strdup(str) safe_strdup_(str, _FILENAME, __LINE__) - -extern void *safe_malloc_(size_t size, const char *file, unsigned line); -extern void *safe_realloc_(void *ptr, size_t size, const char *file, unsigned line); -extern char *safe_strdup_(const char *str, const char *file, unsigned line); +extern void __attribute__((noreturn)) die(const char *err, ...); +extern void *xmalloc(size_t size); +extern void *xrealloc(void *ptr, size_t size); +extern char *xstrdup(const char *str); extern char *concat(size_t count, ...); #endif |