aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTharre <tharre3@gmail.com>2014-11-16 19:19:59 +0100
committerTharre <tharre3@gmail.com>2014-11-16 19:19:59 +0100
commitdf9bc5b9d048c7ecb96838123e39d5bc7c23aa18 (patch)
tree5432d5cc4a0e5a7550f7bae00964f09cb68b6361
parentb4c1b2145d6a0b1ec4219847dc26877046f84e8b (diff)
downloadredo-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.c97
-rw-r--r--src/build.h2
-rw-r--r--src/dbg.h7
-rw-r--r--src/filepath.c14
-rw-r--r--src/redo.c6
-rw-r--r--src/util.c45
-rw-r--r--src/util.h32
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
diff --git a/src/dbg.h b/src/dbg.h
index 28a6fae..ef86cac 100644
--- a/src/dbg.h
+++ b/src/dbg.h
@@ -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;
diff --git a/src/redo.c b/src/redo.c
index 53b5e43..a62f1a6 100644
--- a/src/redo.c
+++ b/src/redo.c
@@ -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[]) {
diff --git a/src/util.c b/src/util.c
index 797c84d..ce668fc 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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) {
diff --git a/src/util.h b/src/util.h
index 500ee6e..0cac914 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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