From 66b2c35aa2466aaba421f8cd13502eeddd3bce1a Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 12:42:16 +0100 Subject: [PATCH 01/15] bee-dep: add regular_file_exists() helper function regular_file_exists(filename) returns: 1 : file exists and is a regular file 0 : file is not a regular file or does not exist check errno for EEXIST : file exists but is not a regular file ENOENT : file does not exist -1 : error; check errno see(stat(2)) --- src/bee-dep.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/bee-dep.c b/src/bee-dep.c index 65f53a0..2a95f09 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -41,6 +41,9 @@ #define CACHENAME "index.db" +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + static void usage(void) { printf("bee-dep v%s 2011\n" @@ -192,6 +195,39 @@ int mkdirp(char *path, mode_t mode) return 0; } +/* + * checks if given filename is a regular file + * returns: + * + * 1 : file exists and is a regular file + * 0 : file is not a regular file or does not exist + * check errno for + * EEXIST : file exists but is not a regular file + * ENOENT : file does not exist + * -1 : error; check errno see(stat(2)) + */ +int regular_file_exists(char *fname) +{ + struct stat st; + int ret; + + ret = stat(fname, &st); + + if(likely(ret == 0)) { + if(likely(S_ISREG(st.st_mode))) + return 1; + + /* set errno for file exists but is not a regular file */ + errno = EEXIST; + return 0; + } + + if (likely(errno == ENOENT)) + return 0; + + return -1; +} + int main(int argc, char *argv[]) { int c, help, rebuild, update, remove, print, options; From 83f6eedf68d6a7a1baff248a79e6991c2e7a53b4 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 13:30:19 +0100 Subject: [PATCH 02/15] bee-dep: use regular_file_exists() to check for cachefile --- src/bee-dep.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 2a95f09..ff13b38 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -231,6 +231,7 @@ int regular_file_exists(char *fname) int main(int argc, char *argv[]) { int c, help, rebuild, update, remove, print, options; + int ret; char found; char cachefile[PATH_MAX + 1], path[PATH_MAX + 1], tmp[PATH_MAX + 1]; char *bee_metadir, *bee_cachedir, *pkgname; @@ -313,8 +314,6 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - found = (stat(cachefile, &st) != -1 && S_ISREG(st.st_mode)); - graph = hash_new(); if (rebuild) { @@ -331,7 +330,12 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, cache, EXIT_SUCCESS); } - if (found) { + ret = regular_file_exists(cachefile); + + if (ret == -1 || (ret == 0 && errno != ENOENT)) { + perror("bee-dep: regular_file_exists(cachefile)"); + cleanup_and_exit(graph, cache, EXIT_FAILURE); + } else if (ret) { cache = open_and_lock(cachefile, "r"); if (load_cache(graph, cache) == EXIT_FAILURE) From 410539462af77f8aa2c3678ac6f96cf03f7c0cad Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 14:20:57 +0100 Subject: [PATCH 03/15] bee-dep: do not exit in hash_new() --- src/bee-dep.c | 5 ++++- src/hash.c | 6 ++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index ff13b38..dfb4955 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -314,7 +314,10 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - graph = hash_new(); + if(!(graph = hash_new())) { + perror("bee-dep: hash_new"); + exit(EXIT_FAILURE); + } if (rebuild) { if (init_cache(graph, bee_metadir, tmp) == EXIT_FAILURE) diff --git a/src/hash.c b/src/hash.c index f3b137e..54101cd 100644 --- a/src/hash.c +++ b/src/hash.c @@ -34,10 +34,8 @@ struct hash *hash_new(void) struct hash *h; unsigned long i; - if ((h = calloc(1, sizeof(struct hash))) == NULL) { - perror("bee-dep: hash_new: calloc"); - exit(EXIT_FAILURE); - } + if (!(h = calloc(1, sizeof(struct hash)))) + return NULL; for (i = 0; i < TBLSIZE; i++) h->tbl[i] = tree_new(); From 59f8e57d01f15502567e03834a27a69f08525935 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 14:45:51 +0100 Subject: [PATCH 04/15] bee-dep: use asprintf in main() --- src/bee-dep.c | 116 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 24 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index dfb4955..5c5e8c7 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -24,6 +24,8 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. */ +#define _GNU_SOURCE + #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> @@ -232,8 +234,10 @@ int main(int argc, char *argv[]) { int c, help, rebuild, update, remove, print, options; int ret; + char *cachefile = NULL; + char *tmpfile = NULL; + char *depfile = NULL; char found; - char cachefile[PATH_MAX + 1], path[PATH_MAX + 1], tmp[PATH_MAX + 1]; char *bee_metadir, *bee_cachedir, *pkgname; struct hash *graph; struct stat st; @@ -303,12 +307,6 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if (sprintf(cachefile, "%s/%s", bee_cachedir, CACHENAME) < 0 - || sprintf(tmp, "%s/index.tmp", bee_cachedir) < 0) { - perror("bee-dep: sprintf"); - exit(EXIT_FAILURE); - } - if (mkdirp(bee_cachedir, 0755) == -1) { perror("bee-dep: mkdirp"); exit(EXIT_FAILURE); @@ -319,17 +317,35 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + if(asprintf(&cachefile, "%s/%s", bee_cachedir, CACHENAME) == -1) { + perror("bee-dep: asprintf"); + exit(EXIT_FAILURE); + } + + if(asprintf(&tmpfile, "%s/index.tmp", bee_cachedir) == -1) { + perror("bee-dep: asprintf"); + free(cachefile); + exit(EXIT_FAILURE); + } + if (rebuild) { - if (init_cache(graph, bee_metadir, tmp) == EXIT_FAILURE) + if (init_cache(graph, bee_metadir, tmpfile) == EXIT_FAILURE) { + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, NULL, EXIT_FAILURE); + } cache = open_and_lock(cachefile, "w"); - if (rename(tmp, cachefile) == -1) { + if (rename(tmpfile, cachefile) == -1) { perror("bee-dep: rename"); + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_SUCCESS); } @@ -337,20 +353,30 @@ int main(int argc, char *argv[]) if (ret == -1 || (ret == 0 && errno != ENOENT)) { perror("bee-dep: regular_file_exists(cachefile)"); + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } else if (ret) { cache = open_and_lock(cachefile, "r"); - if (load_cache(graph, cache) == EXIT_FAILURE) + if (load_cache(graph, cache) == EXIT_FAILURE) { + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); + } } else { - if (init_cache(graph, bee_metadir, tmp) == EXIT_FAILURE) + if (init_cache(graph, bee_metadir, tmpfile) == EXIT_FAILURE) { + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, NULL, EXIT_FAILURE); + } cache = open_and_lock(cachefile, "w"); - if (rename(tmp, cachefile) == -1) { + if (rename(tmpfile, cachefile) == -1) { perror("bee-dep: rename"); + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } } @@ -358,71 +384,113 @@ int main(int argc, char *argv[]) if (update) { found = !!hash_search(graph, pkgname); - if (sprintf(path, "%s/%s/DEPENDENCIES", - bee_metadir, pkgname) < 0) { - perror("bee-dep: sprintf"); + if (asprintf(&depfile, "%s/%s/DEPENDENCIES", + bee_metadir, pkgname) == -1) { + perror("bee-dep: asprintf"); + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } - if (stat(path, &st) != -1) { + if (stat(depfile, &st) != -1) { if (found) { fprintf(stderr, "bee-dep: package '%s' is " "already in the cache\n", pkgname); + free(cachefile); + free(tmpfile); + free(depfile); cleanup_and_exit(graph, cache, EXIT_SUCCESS); } - if (graph_insert_nodes(graph, path) == EXIT_FAILURE) + if (graph_insert_nodes(graph, depfile) == EXIT_FAILURE) { + free(cachefile); + free(tmpfile); + free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); + } } else { if (!found) { fprintf(stderr, "bee-dep: unknown package '%s'\n", pkgname); + free(cachefile); + free(tmpfile); + free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } if ((h = hash_search(graph, pkgname)) == NULL || !IS_PKG(h)) { fprintf(stderr, "bee-dep: unknown package '%s'\n", pkgname); + free(cachefile); + free(tmpfile); + free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } if (remove_package(graph, pkgname) == EXIT_FAILURE) + free(cachefile); + free(tmpfile); + free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } - if (save_cache(graph, tmp) == EXIT_FAILURE) + if (save_cache(graph, tmpfile) == EXIT_FAILURE) { + free(cachefile); + free(tmpfile); + free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); - - if (rename(tmp, cachefile) == -1) { + } + if (rename(tmpfile, cachefile) == -1) { perror("bee-dep: rename"); + free(cachefile); + free(tmpfile); + free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } + free(cachefile); + free(tmpfile); + free(depfile); cleanup_and_exit(graph, cache, EXIT_SUCCESS); } if ((h = hash_search(graph, pkgname)) == NULL || !IS_PKG(h)) { fprintf(stderr, "bee-dep: unknown package '%s'\n", pkgname); + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } if (print) { - if (print_removable(graph, pkgname) == EXIT_FAILURE) + if (print_removable(graph, pkgname) == EXIT_FAILURE) { + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); + } } if (remove) { - if (remove_package(graph, pkgname) == EXIT_FAILURE) + if (remove_package(graph, pkgname) == EXIT_FAILURE) { + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); + } - if (save_cache(graph, tmp) == EXIT_FAILURE) + if (save_cache(graph, tmpfile) == EXIT_FAILURE) { + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); + } - if (rename(tmp, cachefile) == -1) { + if (rename(tmpfile, cachefile) == -1) { perror("bee-dep: rename"); + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } } + free(cachefile); + free(tmpfile); cleanup_and_exit(graph, cache, EXIT_SUCCESS); return EXIT_FAILURE; From 7a1c800b3b3d53dc880decd40b12413556025dfc Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 14:52:08 +0100 Subject: [PATCH 05/15] bee-dep: save_cache(), init_cache() return 1 on success and 0 on failure --- src/bee-dep.c | 16 ++++++++-------- src/graph.c | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 5c5e8c7..c172e62 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -72,7 +72,7 @@ int init_cache(struct hash *graph, char *bee_metadir, char *filename) if ((pkg_cnt = scandir(bee_metadir, &package, 0, alphasort)) < 0) { perror("bee-dep: create_cache: scandir"); - return EXIT_FAILURE; + return 0; } /* skip . and .. */ @@ -84,7 +84,7 @@ int init_cache(struct hash *graph, char *bee_metadir, char *filename) if (stat(path, &st) == -1) { perror("bee-dep: create_cache: stat"); - return EXIT_FAILURE; + return 0; } if (S_ISDIR(st.st_mode)) { @@ -95,11 +95,11 @@ int init_cache(struct hash *graph, char *bee_metadir, char *filename) "bee-dep: create_cache: missing " "DEPENDENCIES file for package '%s'\n", package[i]->d_name); - return EXIT_FAILURE; + return 0; } if (graph_insert_nodes(graph, path) == EXIT_FAILURE) - return EXIT_FAILURE; + return 0; } free(package[i]); @@ -329,7 +329,7 @@ int main(int argc, char *argv[]) } if (rebuild) { - if (init_cache(graph, bee_metadir, tmpfile) == EXIT_FAILURE) { + if (!init_cache(graph, bee_metadir, tmpfile)) { free(cachefile); free(tmpfile); cleanup_and_exit(graph, NULL, EXIT_FAILURE); @@ -365,7 +365,7 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, cache, EXIT_FAILURE); } } else { - if (init_cache(graph, bee_metadir, tmpfile) == EXIT_FAILURE) { + if (!init_cache(graph, bee_metadir, tmpfile)) { free(cachefile); free(tmpfile); cleanup_and_exit(graph, NULL, EXIT_FAILURE); @@ -433,7 +433,7 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, cache, EXIT_FAILURE); } - if (save_cache(graph, tmpfile) == EXIT_FAILURE) { + if (!save_cache(graph, tmpfile)) { free(cachefile); free(tmpfile); free(depfile); @@ -475,7 +475,7 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, cache, EXIT_FAILURE); } - if (save_cache(graph, tmpfile) == EXIT_FAILURE) { + if (!save_cache(graph, tmpfile)) { free(cachefile); free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); diff --git a/src/graph.c b/src/graph.c index 0643d26..82e40f1 100644 --- a/src/graph.c +++ b/src/graph.c @@ -504,13 +504,13 @@ int save_cache(struct hash *hash, char *path) if ((file = fopen(path, "w")) == NULL) { perror("bee-dep: save_cache: fopen"); - return EXIT_FAILURE; + return 0; } index = 0; if (hash->cnt == 0) - return EXIT_SUCCESS; + return 1; for (i = 0; i < TBLSIZE; i++) { if (hash->tbl[i]->root) { @@ -555,10 +555,10 @@ int save_cache(struct hash *hash, char *path) if (fclose(file) == EOF) { perror("bee-dep: save_cache: fclose"); - return EXIT_FAILURE; + return 0; } - return EXIT_SUCCESS; + return 1; } int load_cache(struct hash *hash, FILE *file) From f3880fb6b2a112d1a039785514bec84dd668d15f Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 14:54:21 +0100 Subject: [PATCH 06/15] bee-dep: rebuild: don't lock file which gets renamed in next step --- src/bee-dep.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index c172e62..0cbf967 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -241,7 +241,7 @@ int main(int argc, char *argv[]) char *bee_metadir, *bee_cachedir, *pkgname; struct hash *graph; struct stat st; - FILE *cache; + FILE *cache = NULL; struct node *h; struct option long_options[] = { @@ -335,8 +335,6 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, NULL, EXIT_FAILURE); } - cache = open_and_lock(cachefile, "w"); - if (rename(tmpfile, cachefile) == -1) { perror("bee-dep: rename"); free(cachefile); From de403ee5f9f86cee62341389c1a53a977901ccf9 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 15:39:00 +0100 Subject: [PATCH 07/15] bee-dep: cleanup rebuild: move tmpfile logic to save_cache() init_cache() now save_cache()s the cachefile under a temporary name and renames it. --- src/bee-dep.c | 75 +++++++++------------------------------------------ src/graph.c | 36 ++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 64 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 0cbf967..47a6ac1 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -70,6 +70,8 @@ int init_cache(struct hash *graph, char *bee_metadir, char *filename) char path[PATH_MAX + 1]; struct stat st; + /* TODO: need to handle all kinds of race conditions here 8) */ + if ((pkg_cnt = scandir(bee_metadir, &package, 0, alphasort)) < 0) { perror("bee-dep: create_cache: scandir"); return 0; @@ -235,7 +237,6 @@ int main(int argc, char *argv[]) int c, help, rebuild, update, remove, print, options; int ret; char *cachefile = NULL; - char *tmpfile = NULL; char *depfile = NULL; char found; char *bee_metadir, *bee_cachedir, *pkgname; @@ -322,29 +323,15 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if(asprintf(&tmpfile, "%s/index.tmp", bee_cachedir) == -1) { - perror("bee-dep: asprintf"); - free(cachefile); - exit(EXIT_FAILURE); - } - if (rebuild) { - if (!init_cache(graph, bee_metadir, tmpfile)) { - free(cachefile); - free(tmpfile); - cleanup_and_exit(graph, NULL, EXIT_FAILURE); - } + int ret = EXIT_SUCCESS; - if (rename(tmpfile, cachefile) == -1) { - perror("bee-dep: rename"); - free(cachefile); - free(tmpfile); - cleanup_and_exit(graph, cache, EXIT_FAILURE); - } + if (!init_cache(graph, bee_metadir, cachefile)) + ret = EXIT_FAILURE; free(cachefile); - free(tmpfile); - cleanup_and_exit(graph, cache, EXIT_SUCCESS); + hash_free(graph); + return ret; } ret = regular_file_exists(cachefile); @@ -352,30 +339,19 @@ int main(int argc, char *argv[]) if (ret == -1 || (ret == 0 && errno != ENOENT)) { perror("bee-dep: regular_file_exists(cachefile)"); free(cachefile); - free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } else if (ret) { cache = open_and_lock(cachefile, "r"); if (load_cache(graph, cache) == EXIT_FAILURE) { free(cachefile); - free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } } else { - if (!init_cache(graph, bee_metadir, tmpfile)) { + if (!init_cache(graph, bee_metadir, cachefile)) { free(cachefile); - free(tmpfile); - cleanup_and_exit(graph, NULL, EXIT_FAILURE); - } - - cache = open_and_lock(cachefile, "w"); - - if (rename(tmpfile, cachefile) == -1) { - perror("bee-dep: rename"); - free(cachefile); - free(tmpfile); - cleanup_and_exit(graph, cache, EXIT_FAILURE); + hash_free(graph); + return EXIT_FAILURE; } } @@ -386,7 +362,6 @@ int main(int argc, char *argv[]) bee_metadir, pkgname) == -1) { perror("bee-dep: asprintf"); free(cachefile); - free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } @@ -395,14 +370,12 @@ int main(int argc, char *argv[]) fprintf(stderr, "bee-dep: package '%s' is " "already in the cache\n", pkgname); free(cachefile); - free(tmpfile); free(depfile); cleanup_and_exit(graph, cache, EXIT_SUCCESS); } if (graph_insert_nodes(graph, depfile) == EXIT_FAILURE) { free(cachefile); - free(tmpfile); free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } @@ -411,7 +384,6 @@ int main(int argc, char *argv[]) fprintf(stderr, "bee-dep: unknown package '%s'\n", pkgname); free(cachefile); - free(tmpfile); free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } @@ -419,34 +391,23 @@ int main(int argc, char *argv[]) if ((h = hash_search(graph, pkgname)) == NULL || !IS_PKG(h)) { fprintf(stderr, "bee-dep: unknown package '%s'\n", pkgname); free(cachefile); - free(tmpfile); free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } if (remove_package(graph, pkgname) == EXIT_FAILURE) free(cachefile); - free(tmpfile); free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } - if (!save_cache(graph, tmpfile)) { - free(cachefile); - free(tmpfile); - free(depfile); - cleanup_and_exit(graph, cache, EXIT_FAILURE); - } - if (rename(tmpfile, cachefile) == -1) { - perror("bee-dep: rename"); + if (!save_cache(graph, cachefile)) { free(cachefile); - free(tmpfile); free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } free(cachefile); - free(tmpfile); free(depfile); cleanup_and_exit(graph, cache, EXIT_SUCCESS); } @@ -454,14 +415,12 @@ int main(int argc, char *argv[]) if ((h = hash_search(graph, pkgname)) == NULL || !IS_PKG(h)) { fprintf(stderr, "bee-dep: unknown package '%s'\n", pkgname); free(cachefile); - free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } if (print) { if (print_removable(graph, pkgname) == EXIT_FAILURE) { free(cachefile); - free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } } @@ -469,26 +428,16 @@ int main(int argc, char *argv[]) if (remove) { if (remove_package(graph, pkgname) == EXIT_FAILURE) { free(cachefile); - free(tmpfile); - cleanup_and_exit(graph, cache, EXIT_FAILURE); - } - - if (!save_cache(graph, tmpfile)) { - free(cachefile); - free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } - if (rename(tmpfile, cachefile) == -1) { - perror("bee-dep: rename"); + if (!save_cache(graph, cachefile)) { free(cachefile); - free(tmpfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } } free(cachefile); - free(tmpfile); cleanup_and_exit(graph, cache, EXIT_SUCCESS); return EXIT_FAILURE; diff --git a/src/graph.c b/src/graph.c index 82e40f1..500c1d2 100644 --- a/src/graph.c +++ b/src/graph.c @@ -24,11 +24,14 @@ ** along with this program; if not, see <http://www.gnu.org/licenses/>. */ +#define _GNU_SOURCE + #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <string.h> #include <sys/stat.h> +#include <unistd.h> #include "graph.h" @@ -495,13 +498,15 @@ int print_removable(struct hash *hash, char *remove) return EXIT_SUCCESS; } -int save_cache(struct hash *hash, char *path) +static int save_cache_to_file(struct hash *hash, char *path) { int i; unsigned long index; struct tree_node *s, *t; FILE *file; + /* TODO: need to handle all kinds of race conditions here 8) */ + if ((file = fopen(path, "w")) == NULL) { perror("bee-dep: save_cache: fopen"); return 0; @@ -561,6 +566,35 @@ int save_cache(struct hash *hash, char *path) return 1; } +int save_cache(struct hash *hash, char *fname) +{ + char *tmpname; + int ret = 1; + + /* TODO: need to handle all kinds of race conditions here 8) */ + + if(asprintf(&tmpname, "%s.tmp", fname) == -1) { + perror("bee-dep: save_cache: asprintf"); + return 0; + } + + if(save_cache_to_file(hash, tmpname)) { + if(rename(tmpname, fname) == -1) { + perror("bee-dep: save_cache: rename"); + if(unlink(tmpname) == -1) { + perror("bee-dep: save_cache: unlink"); + } + ret = 0; + } + } else { + ret = 0; + } + + free(tmpname); + + return ret; +} + int load_cache(struct hash *hash, FILE *file) { char line[LINE_MAX], From f6368458db7787ae73e7fae5d14d816505cff5b8 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 15:52:02 +0100 Subject: [PATCH 08/15] bee-dep: load_cache() return 1 on success and 0 on failure --- src/bee-dep.c | 2 +- src/graph.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 47a6ac1..5b4932c 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -343,7 +343,7 @@ int main(int argc, char *argv[]) } else if (ret) { cache = open_and_lock(cachefile, "r"); - if (load_cache(graph, cache) == EXIT_FAILURE) { + if (!load_cache(graph, cache)) { free(cachefile); cleanup_and_exit(graph, cache, EXIT_FAILURE); } diff --git a/src/graph.c b/src/graph.c index 500c1d2..30b04ff 100644 --- a/src/graph.c +++ b/src/graph.c @@ -616,7 +616,7 @@ int load_cache(struct hash *hash, FILE *file) if (sscanf(line, "%s %s", a, b) == EOF) { fprintf(stderr, "beedep: load_cache: " "cache file is broken (line %d)\n", line_cnt); - return EXIT_FAILURE; + return 0; } hash_insert(hash, node_new(a, b)); @@ -628,7 +628,7 @@ int load_cache(struct hash *hash, FILE *file) if (sscanf(line, "%s %s %c", a, b, &c) == EOF) { fprintf(stderr, "beedep: load_cache: " "cache file is broken (line %d)\n", line_cnt); - return EXIT_FAILURE; + return 0; } k = hash_search(hash, a); @@ -637,7 +637,7 @@ int load_cache(struct hash *hash, FILE *file) if (!k || !l) { fprintf(stderr, "beedep: load_cache: " "cache file is broken (line %d)\n", line_cnt); - return EXIT_FAILURE; + return 0; } if (c == 'n') { @@ -649,11 +649,11 @@ int load_cache(struct hash *hash, FILE *file) } else { fprintf(stderr, "beedep: load_cache: " "cache file is broken (line %d)\n", line_cnt); - return EXIT_FAILURE; + return 0; } } - return EXIT_SUCCESS; + return 1; } unsigned long count_providedby(struct hash *hash, char *count) From 9f926c7b13deb5ca98ca49c6323485ddcd0ca667 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 16:00:45 +0100 Subject: [PATCH 09/15] bee-dep: new ENV handling --- src/bee-dep.c | 66 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 5b4932c..59e4a65 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -46,6 +46,39 @@ #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) +#define BEE_METADIR env_bee_metadir() +#define BEE_CACHEDIR env_bee_cachedir() + +static char *env_bee_metadir(void) +{ + static char *value = NULL; + + if(value) + return value; + + value = getenv("BEE_METADIR"); + + if(!value) + value = ""; + + return value; +} + +static char *env_bee_cachedir(void) +{ + static char *value = NULL; + + if(value) + return value; + + value = getenv("BEE_CACHEDIR"); + + if(!value) + value = ""; + + return value; +} + static void usage(void) { printf("bee-dep v%s 2011\n" @@ -63,7 +96,7 @@ static void usage(void) getenv("BEE_VERSION")); } -int init_cache(struct hash *graph, char *bee_metadir, char *filename) +int init_cache(struct hash *graph, char *filename) { struct dirent **package; int i, pkg_cnt; @@ -72,7 +105,7 @@ int init_cache(struct hash *graph, char *bee_metadir, char *filename) /* TODO: need to handle all kinds of race conditions here 8) */ - if ((pkg_cnt = scandir(bee_metadir, &package, 0, alphasort)) < 0) { + if ((pkg_cnt = scandir(BEE_METADIR, &package, 0, alphasort)) < 0) { perror("bee-dep: create_cache: scandir"); return 0; } @@ -82,7 +115,7 @@ int init_cache(struct hash *graph, char *bee_metadir, char *filename) free(package[1]); for (i = 2; i < pkg_cnt; i++) { - sprintf(path, "%s/%s", bee_metadir, package[i]->d_name); + sprintf(path, "%s/%s", BEE_METADIR, package[i]->d_name); if (stat(path, &st) == -1) { perror("bee-dep: create_cache: stat"); @@ -136,19 +169,6 @@ void cleanup_and_exit(struct hash *h, FILE *f, int r) exit(r); } -void get_bee_variables(char **bee_cachedir, char **bee_metadir) -{ - if (!(*bee_cachedir = getenv("BEE_CACHEDIR"))) { - fprintf(stderr, "BEE-ERROR: BEE_CACHEDIR not set\n"); - exit(EXIT_FAILURE); - } - - if (!(*bee_metadir = getenv("BEE_METADIR"))) { - fprintf(stderr, "BEE-ERROR: BEE_METADIR not set\n"); - exit(EXIT_FAILURE); - } -} - static FILE *open_and_lock(char *filename, char *mode) { FILE *f; @@ -239,7 +259,7 @@ int main(int argc, char *argv[]) char *cachefile = NULL; char *depfile = NULL; char found; - char *bee_metadir, *bee_cachedir, *pkgname; + char *pkgname; struct hash *graph; struct stat st; FILE *cache = NULL; @@ -259,8 +279,6 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - get_bee_variables(&bee_cachedir, &bee_metadir); - if (argc == 1) { usage(); exit(EXIT_FAILURE); @@ -308,7 +326,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if (mkdirp(bee_cachedir, 0755) == -1) { + if (mkdirp(BEE_CACHEDIR, 0755) == -1) { perror("bee-dep: mkdirp"); exit(EXIT_FAILURE); } @@ -318,7 +336,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if(asprintf(&cachefile, "%s/%s", bee_cachedir, CACHENAME) == -1) { + if(asprintf(&cachefile, "%s/%s", BEE_CACHEDIR, CACHENAME) == -1) { perror("bee-dep: asprintf"); exit(EXIT_FAILURE); } @@ -326,7 +344,7 @@ int main(int argc, char *argv[]) if (rebuild) { int ret = EXIT_SUCCESS; - if (!init_cache(graph, bee_metadir, cachefile)) + if (!init_cache(graph, cachefile)) ret = EXIT_FAILURE; free(cachefile); @@ -348,7 +366,7 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, cache, EXIT_FAILURE); } } else { - if (!init_cache(graph, bee_metadir, cachefile)) { + if (!init_cache(graph, cachefile)) { free(cachefile); hash_free(graph); return EXIT_FAILURE; @@ -359,7 +377,7 @@ int main(int argc, char *argv[]) found = !!hash_search(graph, pkgname); if (asprintf(&depfile, "%s/%s/DEPENDENCIES", - bee_metadir, pkgname) == -1) { + BEE_METADIR, pkgname) == -1) { perror("bee-dep: asprintf"); free(cachefile); cleanup_and_exit(graph, cache, EXIT_FAILURE); From 22bc2852edb527ba602320da0863e9f94e39d9d8 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 16:21:09 +0100 Subject: [PATCH 10/15] bee-dep: graph_insert_nodes() return 1 on success and 0 on failure --- src/bee-dep.c | 4 ++-- src/graph.c | 21 +++++++++------------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 59e4a65..34c5902 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -133,7 +133,7 @@ int init_cache(struct hash *graph, char *filename) return 0; } - if (graph_insert_nodes(graph, path) == EXIT_FAILURE) + if (!graph_insert_nodes(graph, path)) return 0; } @@ -392,7 +392,7 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, cache, EXIT_SUCCESS); } - if (graph_insert_nodes(graph, depfile) == EXIT_FAILURE) { + if (!graph_insert_nodes(graph, depfile)) { free(cachefile); free(depfile); cleanup_and_exit(graph, cache, EXIT_FAILURE); diff --git a/src/graph.c b/src/graph.c index 30b04ff..ca8472e 100644 --- a/src/graph.c +++ b/src/graph.c @@ -100,7 +100,7 @@ int graph_insert_nodes(struct hash *hash, char *filename) if ((file = fopen(filename, "r")) == NULL) { perror("bee-dep: graph_insert_nodes: fopen"); - return EXIT_FAILURE; + return 0; } line_cnt = type_flag = u = 0; @@ -137,7 +137,7 @@ int graph_insert_nodes(struct hash *hash, char *filename) fprintf(stderr, "bee-dep: %s: error at line %d: missing bracket\n", filename, line_cnt); - return EXIT_FAILURE; + return 0; } *p = '\0'; @@ -146,7 +146,7 @@ int graph_insert_nodes(struct hash *hash, char *filename) fprintf(stderr, "bee-dep: %s: error at line %d: empty node name\n", filename, line_cnt); - return EXIT_FAILURE; + return 0; } if (IS_FILE(s)) { @@ -155,7 +155,7 @@ int graph_insert_nodes(struct hash *hash, char *filename) "bee-dep: %s: error at line %d: " "dont know to which package" "\"%s\" belongs to\n", filename, line_cnt, s); - return EXIT_FAILURE; + return 0; } sprintf(nodename, "%s%s", pkgname, s); @@ -192,7 +192,7 @@ int graph_insert_nodes(struct hash *hash, char *filename) fprintf(stderr, "bee-dep: %s: error at line %d: missing value " "for property \"%s\"\n", filename, line_cnt, prop); - return EXIT_FAILURE; + return 0; } memset(value, '\0', LINE_MAX); @@ -204,7 +204,7 @@ int graph_insert_nodes(struct hash *hash, char *filename) "bee-dep: %s: error at line %d: " "ambiguous type \"%s\"\n", filename, line_cnt, value); - return EXIT_FAILURE; + return 0; } node_set_type(n, value); @@ -248,18 +248,15 @@ int graph_insert_nodes(struct hash *hash, char *filename) if (fclose(file) == EOF) { perror("bee-dep: graph_insert_nodes: fclose"); - return EXIT_FAILURE; + return 0; } if(line_cnt == 0) { fprintf(stderr, "bee-dep: error: file '%s' is empty\n", filename); - /* WTF: why can't we return 0 here for errors ??? */ - return EXIT_FAILURE; + return 0; } - /* we dont't want to exit on success ??? or do we? i don't get it! */ - /* but works for me now.. 8) */ - return EXIT_SUCCESS; + return 1; } void search_dependencies(struct hash *hash, struct node *n, struct tree *d) From ecffb716985e32d87cefec38ca52ca8c388d26a6 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 16:32:14 +0100 Subject: [PATCH 11/15] bee-dep: fix a minor memory leak --- src/bee-dep.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bee-dep.c b/src/bee-dep.c index 34c5902..2b126f6 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -338,6 +338,7 @@ int main(int argc, char *argv[]) if(asprintf(&cachefile, "%s/%s", BEE_CACHEDIR, CACHENAME) == -1) { perror("bee-dep: asprintf"); + hash_free(graph); exit(EXIT_FAILURE); } From feb20abf8a88a269bb9c0cb4a91b63764cc4f6ef Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 16:39:09 +0100 Subject: [PATCH 12/15] bee-dep: init_cache() cleanup --- src/bee-dep.c | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 2b126f6..d145eef 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -96,12 +96,26 @@ static void usage(void) getenv("BEE_VERSION")); } +int pkg_to_graph(struct hash *graph, char *pkgname) +{ + int ret = 1; + char *fname; + + if(asprintf(&fname, "%s/%s/DEPENDENCIES", BEE_METADIR, pkgname) == -1) { + perror("bee-dep: pkg_to_graph: asprintf"); + return -1; + } + + ret = graph_insert_nodes(graph, fname); + + free(fname); + return ret; +} + int init_cache(struct hash *graph, char *filename) { struct dirent **package; int i, pkg_cnt; - char path[PATH_MAX + 1]; - struct stat st; /* TODO: need to handle all kinds of race conditions here 8) */ @@ -115,28 +129,7 @@ int init_cache(struct hash *graph, char *filename) free(package[1]); for (i = 2; i < pkg_cnt; i++) { - sprintf(path, "%s/%s", BEE_METADIR, package[i]->d_name); - - if (stat(path, &st) == -1) { - perror("bee-dep: create_cache: stat"); - return 0; - } - - if (S_ISDIR(st.st_mode)) { - strcat(path, "/DEPENDENCIES"); - - if (stat(path, &st) == -1) { - fprintf(stderr, - "bee-dep: create_cache: missing " - "DEPENDENCIES file for package '%s'\n", - package[i]->d_name); - return 0; - } - - if (!graph_insert_nodes(graph, path)) - return 0; - } - + pkg_to_graph(graph, package[i]->d_name); free(package[i]); } From c92df330eac84ccff24617f39503679ab6872b8b Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 16:57:55 +0100 Subject: [PATCH 13/15] bee-dep: search pkg only once in cachedb --- src/bee-dep.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index d145eef..5ad0f28 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -256,7 +256,7 @@ int main(int argc, char *argv[]) struct hash *graph; struct stat st; FILE *cache = NULL; - struct node *h; + struct node *hnode; struct option long_options[] = { {"help", 0, &help, 1}, @@ -367,9 +367,10 @@ int main(int argc, char *argv[]) } } - if (update) { - found = !!hash_search(graph, pkgname); + hnode = hash_search(graph, pkgname); + found = hnode && IS_PKG(hnode); + if (update) { if (asprintf(&depfile, "%s/%s/DEPENDENCIES", BEE_METADIR, pkgname) == -1) { perror("bee-dep: asprintf"); @@ -378,7 +379,7 @@ int main(int argc, char *argv[]) } if (stat(depfile, &st) != -1) { - if (found) { + if (hnode) { fprintf(stderr, "bee-dep: package '%s' is " "already in the cache\n", pkgname); free(cachefile); @@ -400,7 +401,7 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, cache, EXIT_FAILURE); } - if ((h = hash_search(graph, pkgname)) == NULL || !IS_PKG(h)) { + if (!hnode || !IS_PKG(hnode)) { fprintf(stderr, "bee-dep: unknown package '%s'\n", pkgname); free(cachefile); free(depfile); @@ -424,7 +425,7 @@ int main(int argc, char *argv[]) cleanup_and_exit(graph, cache, EXIT_SUCCESS); } - if ((h = hash_search(graph, pkgname)) == NULL || !IS_PKG(h)) { + if (!hnode || !IS_PKG(hnode)) { fprintf(stderr, "bee-dep: unknown package '%s'\n", pkgname); free(cachefile); cleanup_and_exit(graph, cache, EXIT_FAILURE); From 7e6bc60170461e63c9a1590d614584d835d6f292 Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 17:03:37 +0100 Subject: [PATCH 14/15] bee-dep: get_cachefilename() added to create cache filename --- src/bee-dep.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 5ad0f28..7ffaf7b 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -245,6 +245,17 @@ int regular_file_exists(char *fname) return -1; } +char *get_cachefilename(void) +{ + char *cfname; + + if(asprintf(&cfname, "%s/%s", BEE_CACHEDIR, CACHENAME) == -1) { + perror("bee-dep: get_cachefilename"); + return NULL; + } + return cfname; +} + int main(int argc, char *argv[]) { int c, help, rebuild, update, remove, print, options; @@ -329,8 +340,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if(asprintf(&cachefile, "%s/%s", BEE_CACHEDIR, CACHENAME) == -1) { - perror("bee-dep: asprintf"); + if(!(cachefile = get_cachefilename())) { hash_free(graph); exit(EXIT_FAILURE); } From 8a20f41cee1872831e67129d0e9add0083184d2a Mon Sep 17 00:00:00 2001 From: Marius Tolzmann <tolzmann@molgen.mpg.de> Date: Mon, 19 Dec 2011 17:14:38 +0100 Subject: [PATCH 15/15] bee-dep: rebuild logic now 100% in do_rebuild_cachedb() --- src/bee-dep.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/bee-dep.c b/src/bee-dep.c index 7ffaf7b..54d77cf 100644 --- a/src/bee-dep.c +++ b/src/bee-dep.c @@ -256,6 +256,32 @@ char *get_cachefilename(void) return cfname; } +int do_rebuild_cachedb(void) +{ + char *cfname; + struct hash *graph; + int ret; + + cfname = get_cachefilename(); + + if (!cfname) + return 0; + + graph = hash_new(); + + if (!graph) { + free(cfname); + return 0; + } + + ret = init_cache(graph, cfname); + + free(cfname); + hash_free(graph); + + return ret; +} + int main(int argc, char *argv[]) { int c, help, rebuild, update, remove, print, options; @@ -335,6 +361,12 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + if (rebuild) { + if(!do_rebuild_cachedb()) + return EXIT_FAILURE; + return EXIT_SUCCESS; + } + if(!(graph = hash_new())) { perror("bee-dep: hash_new"); exit(EXIT_FAILURE); @@ -345,16 +377,6 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if (rebuild) { - int ret = EXIT_SUCCESS; - - if (!init_cache(graph, cachefile)) - ret = EXIT_FAILURE; - - free(cachefile); - hash_free(graph); - return ret; - } ret = regular_file_exists(cachefile);