diff --git a/src/bee-dep.c b/src/bee-dep.c
index 65f53a0..54d77cf 100644
--- a/src/bee-dep.c
+++ b/src/bee-dep.c
@@ -24,6 +24,8 @@
** along with this program; if not, see .
*/
+#define _GNU_SOURCE
+
#include
#include
#include
@@ -41,6 +43,42 @@
#define CACHENAME "index.db"
+#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"
@@ -58,16 +96,32 @@ static void usage(void)
getenv("BEE_VERSION"));
}
-int init_cache(struct hash *graph, char *bee_metadir, char *filename)
+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;
- if ((pkg_cnt = scandir(bee_metadir, &package, 0, alphasort)) < 0) {
+ /* 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 EXIT_FAILURE;
+ return 0;
}
/* skip . and .. */
@@ -75,28 +129,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);
-
- if (stat(path, &st) == -1) {
- perror("bee-dep: create_cache: stat");
- return EXIT_FAILURE;
- }
-
- 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 EXIT_FAILURE;
- }
-
- if (graph_insert_nodes(graph, path) == EXIT_FAILURE)
- return EXIT_FAILURE;
- }
-
+ pkg_to_graph(graph, package[i]->d_name);
free(package[i]);
}
@@ -129,19 +162,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;
@@ -192,16 +212,88 @@ 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;
+}
+
+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 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;
+ int ret;
+ char *cachefile = 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;
+ char *pkgname;
struct hash *graph;
struct stat st;
- FILE *cache;
- struct node *h;
+ FILE *cache = NULL;
+ struct node *hnode;
struct option long_options[] = {
{"help", 0, &help, 1},
@@ -217,8 +309,6 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- get_bee_variables(&bee_cachedir, &bee_metadir);
-
if (argc == 1) {
usage();
exit(EXIT_FAILURE);
@@ -266,120 +356,133 @@ 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) {
+ if (mkdirp(BEE_CACHEDIR, 0755) == -1) {
perror("bee-dep: mkdirp");
exit(EXIT_FAILURE);
}
- found = (stat(cachefile, &st) != -1 && S_ISREG(st.st_mode));
-
- graph = hash_new();
-
if (rebuild) {
- if (init_cache(graph, bee_metadir, tmp) == EXIT_FAILURE)
- cleanup_and_exit(graph, NULL, EXIT_FAILURE);
-
- cache = open_and_lock(cachefile, "w");
+ if(!do_rebuild_cachedb())
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ }
- if (rename(tmp, cachefile) == -1) {
- perror("bee-dep: rename");
- cleanup_and_exit(graph, cache, EXIT_FAILURE);
- }
+ if(!(graph = hash_new())) {
+ perror("bee-dep: hash_new");
+ exit(EXIT_FAILURE);
+ }
- cleanup_and_exit(graph, cache, EXIT_SUCCESS);
+ if(!(cachefile = get_cachefilename())) {
+ hash_free(graph);
+ exit(EXIT_FAILURE);
}
- if (found) {
- cache = open_and_lock(cachefile, "r");
- if (load_cache(graph, cache) == EXIT_FAILURE)
- cleanup_and_exit(graph, cache, EXIT_FAILURE);
- } else {
- if (init_cache(graph, bee_metadir, tmp) == EXIT_FAILURE)
- cleanup_and_exit(graph, NULL, EXIT_FAILURE);
+ ret = regular_file_exists(cachefile);
- cache = open_and_lock(cachefile, "w");
+ if (ret == -1 || (ret == 0 && errno != ENOENT)) {
+ perror("bee-dep: regular_file_exists(cachefile)");
+ free(cachefile);
+ cleanup_and_exit(graph, cache, EXIT_FAILURE);
+ } else if (ret) {
+ cache = open_and_lock(cachefile, "r");
- if (rename(tmp, cachefile) == -1) {
- perror("bee-dep: rename");
+ if (!load_cache(graph, cache)) {
+ free(cachefile);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
}
+ } else {
+ if (!init_cache(graph, cachefile)) {
+ free(cachefile);
+ hash_free(graph);
+ return EXIT_FAILURE;
+ }
}
- if (update) {
- found = !!hash_search(graph, pkgname);
+ hnode = hash_search(graph, pkgname);
+ found = hnode && IS_PKG(hnode);
- if (sprintf(path, "%s/%s/DEPENDENCIES",
- bee_metadir, pkgname) < 0) {
- perror("bee-dep: sprintf");
+ if (update) {
+ if (asprintf(&depfile, "%s/%s/DEPENDENCIES",
+ BEE_METADIR, pkgname) == -1) {
+ perror("bee-dep: asprintf");
+ free(cachefile);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
}
- if (stat(path, &st) != -1) {
- if (found) {
+ if (stat(depfile, &st) != -1) {
+ if (hnode) {
fprintf(stderr, "bee-dep: package '%s' is "
"already in the cache\n", pkgname);
+ free(cachefile);
+ free(depfile);
cleanup_and_exit(graph, cache, EXIT_SUCCESS);
}
- if (graph_insert_nodes(graph, path) == EXIT_FAILURE)
+ if (!graph_insert_nodes(graph, depfile)) {
+ free(cachefile);
+ free(depfile);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
+ }
} else {
if (!found) {
fprintf(stderr,
"bee-dep: unknown package '%s'\n", pkgname);
+ free(cachefile);
+ free(depfile);
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);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
}
if (remove_package(graph, pkgname) == EXIT_FAILURE)
+ free(cachefile);
+ free(depfile);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
}
- if (save_cache(graph, tmp) == EXIT_FAILURE)
- cleanup_and_exit(graph, cache, EXIT_FAILURE);
-
- if (rename(tmp, cachefile) == -1) {
- perror("bee-dep: rename");
+ if (!save_cache(graph, cachefile)) {
+ free(cachefile);
+ free(depfile);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
}
+ free(cachefile);
+ free(depfile);
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);
}
if (print) {
- if (print_removable(graph, pkgname) == EXIT_FAILURE)
+ if (print_removable(graph, pkgname) == EXIT_FAILURE) {
+ free(cachefile);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
+ }
}
if (remove) {
- if (remove_package(graph, pkgname) == EXIT_FAILURE)
- cleanup_and_exit(graph, cache, EXIT_FAILURE);
-
- if (save_cache(graph, tmp) == EXIT_FAILURE)
+ if (remove_package(graph, pkgname) == EXIT_FAILURE) {
+ free(cachefile);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
+ }
- if (rename(tmp, cachefile) == -1) {
- perror("bee-dep: rename");
+ if (!save_cache(graph, cachefile)) {
+ free(cachefile);
cleanup_and_exit(graph, cache, EXIT_FAILURE);
}
}
+ free(cachefile);
cleanup_and_exit(graph, cache, EXIT_SUCCESS);
return EXIT_FAILURE;
diff --git a/src/graph.c b/src/graph.c
index 0643d26..ca8472e 100644
--- a/src/graph.c
+++ b/src/graph.c
@@ -24,11 +24,14 @@
** along with this program; if not, see .
*/
+#define _GNU_SOURCE
+
#include
#include
#include
#include
#include
+#include
#include "graph.h"
@@ -97,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;
@@ -134,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';
@@ -143,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)) {
@@ -152,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);
@@ -189,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);
@@ -201,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);
@@ -245,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)
@@ -495,22 +495,24 @@ 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 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 +557,39 @@ 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 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)
@@ -582,7 +613,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));
@@ -594,7 +625,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);
@@ -603,7 +634,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') {
@@ -615,11 +646,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)
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();