diff options
author | Tharre <tharre3@gmail.com> | 2014-11-11 14:45:56 +0100 |
---|---|---|
committer | Tharre <tharre3@gmail.com> | 2014-11-11 22:06:54 +0100 |
commit | 19cba89127381d9dc06d1e823b123231496e9a3d (patch) | |
tree | 41512611f8fba3cde9cdb2f098156b4074ea9d17 | |
parent | 56f3fa373a76842275b199c9ce14fd8e626bd909 (diff) | |
download | redo-19cba89127381d9dc06d1e823b123231496e9a3d.tar.gz redo-19cba89127381d9dc06d1e823b123231496e9a3d.tar.xz redo-19cba89127381d9dc06d1e823b123231496e9a3d.zip |
Fix indentation
-rw-r--r-- | Redofile | 26 | ||||
-rw-r--r-- | src/build.c | 730 | ||||
-rw-r--r-- | src/dbg.h | 22 | ||||
-rw-r--r-- | src/filepath.c | 178 | ||||
-rw-r--r-- | src/redo-always.c | 8 | ||||
-rw-r--r-- | src/redo-ifchange.c | 32 | ||||
-rw-r--r-- | src/redo-ifcreate.c | 10 | ||||
-rw-r--r-- | src/redo.c | 58 | ||||
-rw-r--r-- | src/util.c | 72 |
9 files changed, 568 insertions, 568 deletions
@@ -8,19 +8,19 @@ export VERSION="pre-0.01" DESTDIR=${DESTDIR-/usr/bin} if [ "$1" = "all" ]; then - redo-ifchange $OUTDIR/redo $OUTDIR/redo-ifchange $OUTDIR/redo-ifcreate \ - $OUTDIR/redo-always + redo-ifchange $OUTDIR/redo $OUTDIR/redo-ifchange $OUTDIR/redo-ifcreate \ + $OUTDIR/redo-always elif [ "$1" = "clean" ]; then - rm -rf $OUTDIR/*.tmp $OUTDIR/*.o $OUTDIR/redo $OUTDIR/redo-ifchange \ - $OUTDIR/redo-ifcreate $OUTDIR/redo-always $OUTDIR/CC - # autoconf stuff - rm -rf autom4te.cache config.h.in configure config.status config.log config.h + rm -rf $OUTDIR/*.tmp $OUTDIR/*.o $OUTDIR/redo $OUTDIR/redo-ifchange \ + $OUTDIR/redo-ifcreate $OUTDIR/redo-always $OUTDIR/CC + # autoconf stuff + rm -rf autom4te.cache config.h.in configure config.status config.log config.h elif [ "$1" = "install" ]; then - redo-ifchange all - mkdir -p $DESTDIR - install $OUTDIR/redo $DESTDIR - install $OUTDIR/redo-ifchange $DESTDIR - install $OUTDIR/redo-ifcreate $DESTDIR - install $OUTDIR/redo-always $DESTDIR - echo "Finished installing." + redo-ifchange all + mkdir -p $DESTDIR + install $OUTDIR/redo $DESTDIR + install $OUTDIR/redo-ifchange $DESTDIR + install $OUTDIR/redo-ifcreate $DESTDIR + install $OUTDIR/redo-always $DESTDIR + echo "Finished installing." fi diff --git a/src/build.c b/src/build.c index 19c06f5..8b0ed94 100644 --- a/src/build.c +++ b/src/build.c @@ -39,443 +39,443 @@ static void write_dep_hash(const char *target); static bool dependencies_changed(char buf[], size_t read); struct do_attr { - char *specific; - char *general; - char *redofile; - char *chosen; + char *specific; + char *general; + char *redofile; + char *chosen; }; /* Build given target, using it's do-file. */ int 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) { - if (fexists(target)) { - /* if our target file has no do file associated but exists, - then we treat it as a source */ - write_dep_hash(target); - free_do_attr(dofiles); - return 0; - } - log_err("'%s' couldn't be built because no " - "suitable do-file exists\n", target); - free_do_attr(dofiles); - return 1; - } - - char *reltarget = get_relpath(target); - printf("redo %s\n", reltarget); - free(reltarget); - - /* remove old dependency file */ - char *dep_file = get_dep_path(target); - if (remove(dep_file)) - if (errno != ENOENT) - fatal(ERRM_REMOVE, dep_file); - free(dep_file); - - char *temp_output = concat(2, target, ".redoing.tmp"); - - pid_t pid = fork(); - if (pid == -1) { - /* failure */ - fatal(ERRM_FORK); - } else if (pid == 0) { - /* child */ - - /* change directory to our target */ - char *dirc = safe_strdup(target); - char *dtarget = dirname(dirc); - if (chdir(dtarget) == -1) - fatal(ERRM_CHDIR, dtarget); - - free(dirc); - - /* target is now in the cwd so change path accordingly */ - char *btarget = xbasename(target); - char *bdo_file = xbasename(dofiles->chosen); - char *btemp_output = xbasename(temp_output); - - char **argv = parse_shebang(btarget, bdo_file, btemp_output); - - /* set "REDO_PARENT_TARGET" */ - if (setenv("REDO_PARENT_TARGET", target, 1)) - fatal(ERRM_SETENV, "REDO_PARENT_TARGET", target); - - /* excelp() has nearly everything we want: automatic parsing of the - shebang line through execve() and fallback to /bin/sh if no valid - shebang could be found. However, it fails if the target doesn't have - the executeable bit set, which is something we don't want. For this - reason we parse the shebang line ourselves. */ - execv(argv[0], argv); - - /* execv should never return */ - fatal(ERRM_EXEC, argv[0]); - } - - /* parent */ - int status; - if (waitpid(pid, &status, 0) == -1) - fatal("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); - } else { - /* successful */ - - /* if the file is 0 bytes long we delete it */ - if (fsize(temp_output) > 0) - remove_temp = false; - } - } else { - /* something very wrong happened with the child */ - log_err("redo: invoked do-file did not terminate correctly\n"); - exit(EXIT_FAILURE); - } - - /* depend on the do-file */ - add_dep(dofiles->chosen, target, 'c'); - write_dep_hash(dofiles->chosen); - - /* redo-ifcreate on specific if general was chosen */ - if (dofiles->general == dofiles->chosen) - add_dep(dofiles->specific, target, 'e'); - - if (remove_temp) { - if (remove(temp_output)) - if (errno != ENOENT) - fatal(ERRM_REMOVE, temp_output); - } else { - if (rename(temp_output, target)) - fatal(ERRM_RENAME, temp_output, target); - - write_dep_hash(target); - } - - free(temp_output); - free_do_attr(dofiles); - - return 0; + /* get the do-file which we are going to execute */ + struct do_attr *dofiles = get_dofiles(target); + if (!dofiles->chosen) { + if (fexists(target)) { + /* if our target file has no do file associated but exists, + then we treat it as a source */ + write_dep_hash(target); + free_do_attr(dofiles); + return 0; + } + log_err("'%s' couldn't be built because no " + "suitable do-file exists\n", target); + free_do_attr(dofiles); + return 1; + } + + char *reltarget = get_relpath(target); + printf("redo %s\n", reltarget); + free(reltarget); + + /* remove old dependency file */ + char *dep_file = get_dep_path(target); + if (remove(dep_file)) + if (errno != ENOENT) + fatal(ERRM_REMOVE, dep_file); + free(dep_file); + + char *temp_output = concat(2, target, ".redoing.tmp"); + + pid_t pid = fork(); + if (pid == -1) { + /* failure */ + fatal(ERRM_FORK); + } else if (pid == 0) { + /* child */ + + /* change directory to our target */ + char *dirc = safe_strdup(target); + char *dtarget = dirname(dirc); + if (chdir(dtarget) == -1) + fatal(ERRM_CHDIR, dtarget); + + free(dirc); + + /* target is now in the cwd so change path accordingly */ + char *btarget = xbasename(target); + char *bdo_file = xbasename(dofiles->chosen); + char *btemp_output = xbasename(temp_output); + + char **argv = parse_shebang(btarget, bdo_file, btemp_output); + + /* set "REDO_PARENT_TARGET" */ + if (setenv("REDO_PARENT_TARGET", target, 1)) + fatal(ERRM_SETENV, "REDO_PARENT_TARGET", target); + + /* excelp() has nearly everything we want: automatic parsing of the + shebang line through execve() and fallback to /bin/sh if no valid + shebang could be found. However, it fails if the target doesn't have + the executeable bit set, which is something we don't want. For this + reason we parse the shebang line ourselves. */ + execv(argv[0], argv); + + /* execv should never return */ + fatal(ERRM_EXEC, argv[0]); + } + + /* parent */ + int status; + if (waitpid(pid, &status, 0) == -1) + fatal("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); + } else { + /* successful */ + + /* if the file is 0 bytes long we delete it */ + if (fsize(temp_output) > 0) + remove_temp = false; + } + } else { + /* something very wrong happened with the child */ + log_err("redo: invoked do-file did not terminate correctly\n"); + exit(EXIT_FAILURE); + } + + /* depend on the do-file */ + add_dep(dofiles->chosen, target, 'c'); + write_dep_hash(dofiles->chosen); + + /* redo-ifcreate on specific if general was chosen */ + if (dofiles->general == dofiles->chosen) + add_dep(dofiles->specific, target, 'e'); + + if (remove_temp) { + if (remove(temp_output)) + if (errno != ENOENT) + fatal(ERRM_REMOVE, temp_output); + } else { + if (rename(temp_output, target)) + fatal(ERRM_RENAME, 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 arguments. If no valid shebang could be found, assume "/bin/sh -e" instead. */ static char **parse_shebang(char *target, char *dofile, char *temp_output) { - FILE *fp = fopen(dofile, "rb"); - if (!fp) - fatal(ERRM_FOPEN, dofile); - - char buf[1024]; - - buf[ fread(buf, 1, sizeof(buf)-1, fp) ] = '\0'; - if (ferror(fp)) - fatal(ERRM_FREAD, dofile); - - fclose(fp); - - char **argv; - size_t i = 0; - if (buf[0] == '#' && buf[1] == '!') { - argv = parsecmd(&buf[2], &i, 5); - } else { - argv = safe_malloc(7 * sizeof(char*)); - argv[i++] = "/bin/sh"; - argv[i++] = "-e"; - } - - argv[i++] = dofile; - argv[i++] = (char*) target; - char *basename = remove_ext(target); - argv[i++] = basename; - argv[i++] = temp_output; - argv[i] = NULL; - - return argv; + FILE *fp = fopen(dofile, "rb"); + if (!fp) + fatal(ERRM_FOPEN, dofile); + + char buf[1024]; + + buf[ fread(buf, 1, sizeof(buf)-1, fp) ] = '\0'; + if (ferror(fp)) + fatal(ERRM_FREAD, dofile); + + fclose(fp); + + char **argv; + size_t i = 0; + if (buf[0] == '#' && buf[1] == '!') { + argv = parsecmd(&buf[2], &i, 5); + } else { + argv = safe_malloc(7 * sizeof(char*)); + argv[i++] = "/bin/sh"; + argv[i++] = "-e"; + } + + argv[i++] = dofile; + argv[i++] = (char*) target; + char *basename = remove_ext(target); + argv[i++] = basename; + argv[i++] = temp_output; + argv[i] = NULL; + + return argv; } /* 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)); - - dofiles->specific = concat(2, target, ".do"); - dofiles->general = concat(3, "default", take_extension(target), ".do"); - dofiles->redofile = safe_strdup("Redofile"); - - if (fexists(dofiles->specific)) - dofiles->chosen = dofiles->specific; - else if (fexists(dofiles->general)) - dofiles->chosen = dofiles->general; - else if (fexists(dofiles->redofile)) - dofiles->chosen = dofiles->redofile; - else - dofiles->chosen = NULL; - - return dofiles; + struct do_attr *dofiles = safe_malloc(sizeof(struct do_attr)); + + dofiles->specific = concat(2, target, ".do"); + dofiles->general = concat(3, "default", take_extension(target), ".do"); + dofiles->redofile = safe_strdup("Redofile"); + + if (fexists(dofiles->specific)) + dofiles->chosen = dofiles->specific; + else if (fexists(dofiles->general)) + dofiles->chosen = dofiles->general; + else if (fexists(dofiles->redofile)) + dofiles->chosen = dofiles->redofile; + else + dofiles->chosen = NULL; + + return dofiles; } /* Free the do_attr struct. */ static void free_do_attr(struct do_attr *thing) { - assert(thing); - free(thing->specific); - free(thing->general); - free(thing->redofile); - free(thing); + assert(thing); + free(thing->specific); + free(thing->general); + free(thing->redofile); + free(thing); } /* Breaks cmd at spaces and stores a pointer to each argument in the returned array. The index i is incremented to point to the next free pointer. The 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*)); - size_t j = 0; - bool prev_space = true; - for (;; ++j) { - switch (cmd[j]) { - case ' ': - cmd[j] = '\0'; - prev_space = true; - break; - case '\n': - case '\r': - cmd[j] = '\0'; - case '\0': - return argv; - default: - if (!prev_space) - break; - /* check if we have enough space */ - 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*)); - } - - prev_space = false; - argv[*i] = &cmd[j]; - ++*i; - } - } + size_t argv_len = 16; + char **argv = safe_malloc(argv_len * sizeof(char*)); + size_t j = 0; + bool prev_space = true; + for (;; ++j) { + switch (cmd[j]) { + case ' ': + cmd[j] = '\0'; + prev_space = true; + break; + case '\n': + case '\r': + cmd[j] = '\0'; + case '\0': + return argv; + default: + if (!prev_space) + break; + /* check if we have enough space */ + 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*)); + } + + prev_space = false; + argv[*i] = &cmd[j]; + ++*i; + } + } } /* 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 *dname = dirname(dirc); - char *absdir = realpath(dname, NULL); - if (!absdir) - return NULL; - char *abstarget = concat(3, absdir, "/", xbasename(path)); - - free(dirc); - free(absdir); - return abstarget; + char *dirc = safe_strdup(path); + char *dname = dirname(dirc); + char *absdir = realpath(dname, NULL); + if (!absdir) + return NULL; + char *abstarget = concat(3, absdir, "/", xbasename(path)); + + free(dirc); + free(absdir); + return abstarget; } /* Return the relative path against "REDO_ROOT" of target. */ static char *get_relpath(const char *target) { - assert(getenv("REDO_ROOT")); + assert(getenv("REDO_ROOT")); - char *root = getenv("REDO_ROOT"); - char *abstarget = xrealpath(target); + char *root = getenv("REDO_ROOT"); + char *abstarget = xrealpath(target); - if (!abstarget) - fatal(ERRM_REALPATH, target); + if (!abstarget) + fatal(ERRM_REALPATH, target); - char *relpath = safe_strdup(make_relative(root, abstarget)); - free(abstarget); - return relpath; + char *relpath = safe_strdup(make_relative(root, abstarget)); + free(abstarget); + return relpath; } /* Return the dependency file path of target. */ static char *get_dep_path(const char *target) { - assert(getenv("REDO_ROOT")); + assert(getenv("REDO_ROOT")); - 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 *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); - free(reltarget); - free(safe_target); - return dep_path; + free(reltarget); + free(safe_target); + return dep_path; } /* Add the dependency target, with the identifier ident. If parent is NULL, the * value of the environment variable REDO_PARENT will be taken instead. */ void add_dep(const char *target, const char *parent, int ident) { - if (!parent) { - assert(getenv("REDO_PARENT_TARGET")); - parent = getenv("REDO_PARENT_TARGET"); - } - - char *dep_path = get_dep_path(parent); - - FILE *fp = fopen(dep_path, "rb+"); - if (!fp) { - if (errno == ENOENT) { - fp = fopen(dep_path, "w"); - if (!fp) - fatal(ERRM_FOPEN, 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); - } - } else { - fseek(fp, 0L, SEEK_END); - } - - char *reltarget = get_relpath(target); - - putc(ident, fp); - fputs(reltarget, fp); - putc('\0', fp); - - if (ferror(fp)) - fatal(ERRM_WRITE, dep_path); - - if (fclose(fp)) - fatal(ERRM_FCLOSE, dep_path); - free(dep_path); - free(reltarget); + if (!parent) { + assert(getenv("REDO_PARENT_TARGET")); + parent = getenv("REDO_PARENT_TARGET"); + } + + char *dep_path = get_dep_path(parent); + + FILE *fp = fopen(dep_path, "rb+"); + if (!fp) { + if (errno == ENOENT) { + fp = fopen(dep_path, "w"); + if (!fp) + fatal(ERRM_FOPEN, 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); + } + } else { + fseek(fp, 0L, SEEK_END); + } + + char *reltarget = get_relpath(target); + + putc(ident, fp); + fputs(reltarget, fp); + putc('\0', fp); + + if (ferror(fp)) + fatal(ERRM_WRITE, dep_path); + + if (fclose(fp)) + fatal(ERRM_FCLOSE, dep_path); + free(dep_path); + free(reltarget); } /* Hash target, storing the result in hash. */ static void hash_file(const char *target, unsigned char *hash) { - FILE *in = fopen(target, "rb"); - if (!in) - fatal(ERRM_FOPEN, target); - - SHA_CTX context; - unsigned char data[8192]; - size_t read; - - SHA1_Init(&context); - while ((read = fread(data, 1, sizeof data, in))) - SHA1_Update(&context, data, read); - - if (ferror(in)) - fatal(ERRM_FREAD, target); - SHA1_Final(hash, &context); - fclose(in); + FILE *in = fopen(target, "rb"); + if (!in) + fatal(ERRM_FOPEN, target); + + SHA_CTX context; + unsigned char data[8192]; + size_t read; + + SHA1_Init(&context); + while ((read = fread(data, 1, sizeof data, in))) + SHA1_Update(&context, data, read); + + if (ferror(in)) + fatal(ERRM_FREAD, target); + SHA1_Final(hash, &context); + fclose(in); } /* Calculate and store the hash of target in the right dependency file. */ static void write_dep_hash(const char *target) { - assert(getenv("REDO_MAGIC")); + assert(getenv("REDO_MAGIC")); - unsigned char hash[HASHSIZE]; - unsigned magic = atoi(getenv("REDO_MAGIC")); + unsigned char hash[HASHSIZE]; + unsigned magic = atoi(getenv("REDO_MAGIC")); - hash_file(target, hash); + hash_file(target, hash); - 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); + 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); - if (write(out, &magic, sizeof(unsigned)) < (ssize_t) sizeof(unsigned)) - fatal("redo: failed to write magic number to '%s'", dep_path); + if (write(out, &magic, sizeof(unsigned)) < (ssize_t) sizeof(unsigned)) + fatal("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); + if (write(out, hash, sizeof hash) < (ssize_t) sizeof hash) + fatal("redo: failed to write hash to '%s'", dep_path); - if (close(out)) - fatal(ERRM_FCLOSE, dep_path); - free(dep_path); + if (close(out)) + fatal(ERRM_FCLOSE, dep_path); + free(dep_path); } /* Parse the dependency information from the dependency record and check if those are up-to-date. */ static bool dependencies_changed(char buf[], size_t read) { - char *root = getenv("REDO_ROOT"); - char *ptr = buf; - - for (size_t i = 0; i < read; ++i) { - if (buf[i]) - continue; - if (is_absolute(&ptr[1])) { - if (has_changed(&ptr[1], ptr[0], true)) - return true; - } else { - char *abs = concat(3, root, "/", &ptr[1]); - if (has_changed(abs, ptr[0], true)) { - free(abs); - return true; - } - free(abs); - } - ptr = &buf[i+1]; - } - return false; + char *root = getenv("REDO_ROOT"); + char *ptr = buf; + + for (size_t i = 0; i < read; ++i) { + if (buf[i]) + continue; + if (is_absolute(&ptr[1])) { + if (has_changed(&ptr[1], ptr[0], true)) + return true; + } else { + char *abs = concat(3, root, "/", &ptr[1]); + if (has_changed(abs, ptr[0], true)) { + free(abs); + return true; + } + free(abs); + } + ptr = &buf[i+1]; + } + return false; } /* Checks if a target should be rebuild, given it's identifier. */ bool has_changed(const char *target, int ident, bool is_sub_dependency) { - switch(ident) { - case 'a': return true; - case 'e': return fexists(target); - case 'c': + switch(ident) { + case 'a': return true; + case 'e': return fexists(target); + case 'c': #define HEADERSIZE HASHSIZE + sizeof(unsigned) - if (!fexists(target)) - return true; - - char *dep_path = get_dep_path(target); - - FILE *fp = fopen(dep_path, "rb"); - if (!fp) { - if (errno == ENOENT) { - /* dependency file does not exist */ - return true; - } else { - fatal(ERRM_FOPEN, dep_path); - } - } - - char buf[8096]; - if (fread(buf, 1, HEADERSIZE, fp) < HEADERSIZE) - fatal("redo: failed to read %zu bytes from %s", HEADERSIZE, dep_path); - - free(dep_path); - - if (*(unsigned *) buf == (unsigned) atoi(getenv("REDO_MAGIC"))) - return is_sub_dependency; - - unsigned char hash[HASHSIZE]; - hash_file(target, hash); - if (memcmp(hash, buf+sizeof(unsigned), HASHSIZE)) { - /*debug("Hash doesn't match for %s\n", target);*/ - return true; - } - - while (!feof(fp)) { - size_t read = fread(buf, 1, sizeof buf, fp); - - if (ferror(fp)) - fatal("redo: failed to read %zu bytes from file descriptor", sizeof buf); - - if (dependencies_changed(buf, read)) { - fclose(fp); - return true; - } - } - - fclose(fp); - return false; - - default: - log_err("Unknown identifier '%c'\n", ident); - exit(EXIT_FAILURE); - } + if (!fexists(target)) + return true; + + char *dep_path = get_dep_path(target); + + FILE *fp = fopen(dep_path, "rb"); + if (!fp) { + if (errno == ENOENT) { + /* dependency file does not exist */ + return true; + } else { + fatal(ERRM_FOPEN, dep_path); + } + } + + char buf[8096]; + if (fread(buf, 1, HEADERSIZE, fp) < HEADERSIZE) + fatal("redo: failed to read %zu bytes from %s", HEADERSIZE, dep_path); + + free(dep_path); + + if (*(unsigned *) buf == (unsigned) atoi(getenv("REDO_MAGIC"))) + return is_sub_dependency; + + unsigned char hash[HASHSIZE]; + hash_file(target, hash); + if (memcmp(hash, buf+sizeof(unsigned), HASHSIZE)) { + /*debug("Hash doesn't match for %s\n", target);*/ + return true; + } + + while (!feof(fp)) { + size_t read = fread(buf, 1, sizeof buf, fp); + + if (ferror(fp)) + fatal("redo: failed to read %zu bytes from file descriptor", sizeof buf); + + if (dependencies_changed(buf, read)) { + fclose(fp); + return true; + } + } + + fclose(fp); + return false; + + default: + log_err("Unknown identifier '%c'\n", ident); + exit(EXIT_FAILURE); + } } bool environment_sane() { - return getenv("REDO_ROOT") && getenv("REDO_PARENT_TARGET") && getenv("REDO_MAGIC"); + return getenv("REDO_ROOT") && getenv("REDO_PARENT_TARGET") && getenv("REDO_MAGIC"); } @@ -24,7 +24,7 @@ #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__) + fprintf(stderr, "(%s:%u): " M ": %s\n", f, l, __VA_ARGS__) #ifdef NDEBUG #define debug(...) @@ -34,22 +34,22 @@ #define log_err(...) LOG_HELPER(_FILENAME, __LINE__, __VA_ARGS__) #define fatal(...) \ - ({FATAL_HELPER(__VA_ARGS__, strerror(errno)); exit(EXIT_FAILURE);}) + ({FATAL_HELPER(__VA_ARGS__, strerror(errno)); exit(EXIT_FAILURE);}) #define fatal_(f,l,...) \ - ({FATAL_HELPER_(f, l, __VA_ARGS__, strerror(errno)); exit(EXIT_FAILURE);}) + ({FATAL_HELPER_(f, l, __VA_ARGS__, strerror(errno)); exit(EXIT_FAILURE);}) #define assert_str_equal(a,b) ({ \ - if (strcmp(a, b)) { \ - log_err("Assertion error: '%s' == '%s'\n", a, b); \ - abort(); \ - } \ + if (strcmp(a, b)) { \ + log_err("Assertion error: '%s' == '%s'\n", a, b); \ + abort(); \ + } \ }) #define assert_int_equal(a,b) ({ \ - if (a != b) { \ - log_err("Assertion error: '%d' == '%d'\n", a, b); \ - abort(); \ - } \ + if (a != b) { \ + log_err("Assertion error: '%d' == '%d'\n", a, b); \ + abort(); \ + } \ }) /* A neat macro that silences unused parameter warnings compiler independant */ diff --git a/src/filepath.c b/src/filepath.c index ff1b476..7d73b60 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -19,135 +19,135 @@ /* Check if the given path is absolute. */ bool is_absolute(const char* path) { - return path[0] == '/'; + return path[0] == '/'; } /* Returns a new copy of str with the extension removed, where the extension is everything behind the last dot, including the dot. */ char *remove_ext(const char *str) { - assert(str); - size_t len; - char *ret, *dot = NULL; + assert(str); + size_t len; + char *ret, *dot = NULL; - for (len = 0; str[len]; ++len) - if (str[len] == '.') - dot = (char*) &str[len]; + for (len = 0; str[len]; ++len) + if (str[len] == '.') + dot = (char*) &str[len]; - if (dot) /* recalculate length to only reach just before the last dot */ - len = dot - str; + if (dot) /* recalculate length to only reach just before the last dot */ + len = dot - str; - ret = safe_malloc(len+1); - memcpy(ret, str, len); - ret[len] = '\0'; + ret = safe_malloc(len+1); + memcpy(ret, str, len); + ret[len] = '\0'; - return ret; + return ret; } /* Returns the extension of the target or the empty string if none was found. */ char *take_extension(const char *target) { - assert(target); - char *temp = strrchr(target, '.'); - if (temp) - return temp; - else - return ""; + assert(target); + char *temp = strrchr(target, '.'); + if (temp) + return temp; + else + return ""; } /* Make one path relative to another i.e. some/path to some/path/a/b/c would yield a/b/c as result. Prints '.' if the 2 paths match. */ // TODO: nameing, requires absolute paths, doesn't MALLOC const char *make_relative(const char *target, const char *to) { - int i; - for (i = 0; target[i] && to[i]; ++i) - if (target[i] != to[i]) { - /* the paths do not match */ - return to; - } - - if (!target[i] && !to[i]) { - /* both paths match completely */ - return "."; - } - - /* skip any leading seperators */ - while (to[i] == '/') - ++i; - - return &to[i]; + int i; + for (i = 0; target[i] && to[i]; ++i) + if (target[i] != to[i]) { + /* the paths do not match */ + return to; + } + + if (!target[i] && !to[i]) { + /* both paths match completely */ + return "."; + } + + /* skip any leading seperators */ + while (to[i] == '/') + ++i; + + return &to[i]; } /* Transforms target into a safe filename, replacing all '/' with '!'. */ char *transform_path(const char *target) { - char *ptr = (char*) target; - size_t escape = 0, i = 0; - while (*ptr++) - if (*ptr == '!') escape++; - - ptr = safe_malloc((ptr-target) + escape + 1); - do { - if (*target == '/') - ptr[i++] = '!'; - else if (*target == '!') { - ptr[i++] = '!'; - ptr[i++] = '!'; - } else - ptr[i++] = *target; - } while (*target++); - - ptr[i] = '\0'; - return ptr; + char *ptr = (char*) target; + size_t escape = 0, i = 0; + while (*ptr++) + if (*ptr == '!') escape++; + + ptr = safe_malloc((ptr-target) + escape + 1); + do { + if (*target == '/') + ptr[i++] = '!'; + else if (*target == '!') { + ptr[i++] = '!'; + ptr[i++] = '!'; + } else + ptr[i++] = *target; + } while (*target++); + + ptr[i] = '\0'; + return ptr; } /* Sane and portable basename implementation. */ char *xbasename(const char *path) { - assert(path); - char *ptr = strrchr(path, '/'); - return ptr? ptr+1 : (char*) path; + assert(path); + char *ptr = strrchr(path, '/'); + return ptr? ptr+1 : (char*) path; } /* Checks if target exists and prints a debug message if access() failed except if it failed with ENOENT. */ bool fexists(const char *target) { - assert(target); - if (!access(target, F_OK)) - return true; - if (errno != ENOENT) - debug("Failed to access %s: %s\n", target, strerror(errno)); - return false; + assert(target); + if (!access(target, F_OK)) + return true; + if (errno != ENOENT) + debug("Failed to access %s: %s\n", target, strerror(errno)); + return false; } /* Returns the size of fn, or -1 if the file doesn't exist. */ off_t fsize(const char *fn) { - struct stat st; - if (stat(fn, &st)) { - if (errno != ENOENT) - fatal(ERRM_STAT, fn); - return -1; - } - - return st.st_size; + struct stat st; + if (stat(fn, &st)) { + if (errno != ENOENT) + fatal(ERRM_STAT, fn); + return -1; + } + + return st.st_size; } /* Create the directory dir, while removing other 'files' with the same name. Returns true if the directory had to be created or false if it existed */ // TODO: fix confusing name bool mkdirp(const char *dir) { - struct stat st; - if (stat(dir, &st)) { - /* dir doesn't exist or stat failed */ - if (errno != ENOENT) - fatal(ERRM_STAT, dir); - if (mkdir(dir, 0755)) - fatal(ERRM_MKDIR, dir); - return 1; - } else { - if (!S_ISDIR(st.st_mode)) { - if (remove(dir)) - fatal(ERRM_REMOVE, dir); - if (mkdir(dir, 0755)) - fatal(ERRM_MKDIR, dir); - return 1; - } - return 0; - } + struct stat st; + if (stat(dir, &st)) { + /* dir doesn't exist or stat failed */ + if (errno != ENOENT) + fatal(ERRM_STAT, dir); + if (mkdir(dir, 0755)) + fatal(ERRM_MKDIR, dir); + return 1; + } else { + if (!S_ISDIR(st.st_mode)) { + if (remove(dir)) + fatal(ERRM_REMOVE, dir); + if (mkdir(dir, 0755)) + fatal(ERRM_MKDIR, dir); + return 1; + } + return 0; + } } diff --git a/src/redo-always.c b/src/redo-always.c index 352e6c8..5f0c24c 100644 --- a/src/redo-always.c +++ b/src/redo-always.c @@ -11,8 +11,8 @@ #include "build.h" int main(int argc, char *argv[]) { - for (int i = 1; i < argc; ++i) { - build_target(argv[i]); - add_dep(argv[i], NULL, 'a'); - } + for (int i = 1; i < argc; ++i) { + build_target(argv[i]); + add_dep(argv[i], NULL, 'a'); + } } diff --git a/src/redo-ifchange.c b/src/redo-ifchange.c index 75bd984..cfc017b 100644 --- a/src/redo-ifchange.c +++ b/src/redo-ifchange.c @@ -13,22 +13,22 @@ #include "dbg.h" int main(int argc, char *argv[]) { - if (!environment_sane()) { - fprintf(stderr, "redo: environment variables are missing, \ - please use %s only in do scripts.\n", argv[0]); - exit(1); - } + if (!environment_sane()) { + fprintf(stderr, "redo: environment variables are missing, \ + please use %s only in do scripts.\n", argv[0]); + exit(1); + } - for (int i = 1; i < argc; ++i) { - /*debug("Testing if %s is up-to-date ...\n", argv[i]);*/ - if (has_changed(argv[i], 'c', false)) { - /*printf("=> no\n");*/ - build_target(argv[i]); - } else { - /*printf("=> yes\n");*/ - } - add_dep(argv[i], NULL, 'c'); - } + for (int i = 1; i < argc; ++i) { + /*debug("Testing if %s is up-to-date ...\n", argv[i]);*/ + if (has_changed(argv[i], 'c', false)) { + /*printf("=> no\n");*/ + build_target(argv[i]); + } else { + /*printf("=> yes\n");*/ + } + add_dep(argv[i], NULL, 'c'); + } - return 0; + return 0; } diff --git a/src/redo-ifcreate.c b/src/redo-ifcreate.c index 955ffdc..eba1c6b 100644 --- a/src/redo-ifcreate.c +++ b/src/redo-ifcreate.c @@ -11,9 +11,9 @@ #include "build.h" int main(int argc, char *argv[]) { - for (int i = 1; i < argc; ++i) { - if (has_changed(argv[i], 'e', false)) - build_target(argv[i]); - add_dep(argv[i], NULL, 'e'); - } + for (int i = 1; i < argc; ++i) { + if (has_changed(argv[i], 'e', false)) + build_target(argv[i]); + add_dep(argv[i], NULL, 'e'); + } } @@ -23,39 +23,39 @@ /* Returns the amount of digits a number n has in decimal. */ static inline unsigned digits(unsigned n) { - return n ? 1 + digits(n/10) : n; + return n ? 1 + digits(n/10) : n; } void prepare_env() { - /* create the dependency store if it doesn't already exist */ - if (mkdirp(".redo") && mkdirp(".redo/deps")) - fprintf(stderr, "redo: creating dependency store ...\n"); - - /* set REDO_ROOT */ - char *cwd = getcwd(NULL, 0); - if (!cwd) - fatal("redo: failed to obtain cwd"); - if (setenv("REDO_ROOT", cwd, 0)) - fatal("redo: failed to setenv REDO_ROOT to %s", cwd); - free(cwd); - - /* set REDO_MAGIC */ - srand(time(NULL)); - char magic_str[digits(UINT_MAX) + 1]; - sprintf(magic_str, "%u", rand()); - if (setenv("REDO_MAGIC", magic_str, 0)) - fatal("setenv()"); + /* create the dependency store if it doesn't already exist */ + if (mkdirp(".redo") && mkdirp(".redo/deps")) + fprintf(stderr, "redo: creating dependency store ...\n"); + + /* set REDO_ROOT */ + char *cwd = getcwd(NULL, 0); + if (!cwd) + fatal("redo: failed to obtain cwd"); + if (setenv("REDO_ROOT", cwd, 0)) + fatal("redo: failed to setenv REDO_ROOT to %s", cwd); + free(cwd); + + /* set REDO_MAGIC */ + srand(time(NULL)); + char magic_str[digits(UINT_MAX) + 1]; + sprintf(magic_str, "%u", rand()); + if (setenv("REDO_MAGIC", magic_str, 0)) + fatal("setenv()"); } int main(int argc, char *argv[]) { - prepare_env(); - - if (argc < 2) { - build_target("all"); - } else { - int i; - for (i = 1; i < argc; ++i) { - build_target(argv[i]); - } - } + prepare_env(); + + if (argc < 2) { + build_target("all"); + } else { + int i; + for (i = 1; i < argc; ++i) { + build_target(argv[i]); + } + } } @@ -16,54 +16,54 @@ void *safe_malloc_(size_t size, const char *file, unsigned line) { - assert(size > 0); - void *ptr = malloc(size); - if (!ptr) - fatal_(file, line, ERRM_MALLOC, size); + assert(size > 0); + void *ptr = malloc(size); + if (!ptr) + fatal_(file, line, ERRM_MALLOC, size); - return ptr; + return ptr; } void *safe_realloc_(void *ptr, size_t size, const char *file, unsigned line) { - assert(size > 0 && ptr); - void *ptr2 = realloc(ptr, size); - if (!ptr2) - fatal_(file, line, ERRM_REALLOC, size); + assert(size > 0 && ptr); + void *ptr2 = realloc(ptr, size); + if (!ptr2) + fatal_(file, line, ERRM_REALLOC, size); - return ptr2; + return ptr2; } char *safe_strdup_(const char *str, const char *file, unsigned line) { - assert(str); - size_t len = strlen(str) + 1; - char *ptr = malloc(len); - if (!ptr) - fatal_(file, line, ERRM_MALLOC, len); + assert(str); + size_t len = strlen(str) + 1; + char *ptr = malloc(len); + if (!ptr) + fatal_(file, line, ERRM_MALLOC, len); - return memcpy(ptr, str, len); + return memcpy(ptr, str, len); } /* For concating multiple strings into a single larger one. */ char *concat(size_t count, ...) { - assert(count > 0); - va_list ap, ap2; - va_start(ap, count); - va_copy(ap2, ap); - size_t i, size = 0, args_len[count]; - for (i = 0; i < count; ++i) { - args_len[i] = strlen(va_arg(ap, char*)); - size += args_len[i]; - } - ++size; - char *result = safe_malloc(size); - /* debug("Allocated %zu bytes at %p\n", size, result); */ - uintptr_t offset = 0; - for (i = 0; i < count; ++i) { - strcpy(&result[offset], va_arg(ap2, char*)); - offset += args_len[i]; - } - va_end(ap); - va_end(ap2); - return result; + assert(count > 0); + va_list ap, ap2; + va_start(ap, count); + va_copy(ap2, ap); + size_t i, size = 0, args_len[count]; + for (i = 0; i < count; ++i) { + args_len[i] = strlen(va_arg(ap, char*)); + size += args_len[i]; + } + ++size; + char *result = safe_malloc(size); + /* debug("Allocated %zu bytes at %p\n", size, result); */ + uintptr_t offset = 0; + for (i = 0; i < count; ++i) { + strcpy(&result[offset], va_arg(ap2, char*)); + offset += args_len[i]; + } + va_end(ap); + va_end(ap2); + return result; } |