diff options
Diffstat (limited to 'src')
| -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  | 
