diff options
author | Mike Frysinger <vapier@gentoo.org> | 2011-03-02 07:03:31 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-03-02 07:03:31 +0000 |
commit | 4c2427c67a7cad2d696e506278e54561c918df4c (patch) | |
tree | 2104745a9cf66ef58857ed1b6d761a4f70744f45 | |
parent | fix up extended line reading to avoid buffer overflows (diff) | |
download | portage-utils-4c2427c67a7cad2d696e506278e54561c918df4c.tar.gz portage-utils-4c2427c67a7cad2d696e506278e54561c918df4c.tar.bz2 portage-utils-4c2427c67a7cad2d696e506278e54561c918df4c.zip |
add a helper to walk the profile tree and read files
-rw-r--r-- | libq/libq.c | 1 | ||||
-rw-r--r-- | libq/profile.c | 77 | ||||
-rw-r--r-- | libq/virtuals.c | 71 |
3 files changed, 100 insertions, 49 deletions
diff --git a/libq/libq.c b/libq/libq.c index e79b67b0..1e5e839f 100644 --- a/libq/libq.c +++ b/libq/libq.c @@ -34,6 +34,7 @@ #include "basename.c" #ifndef _LIB_Q +# include "profile.c" # include "vdb_get_next_dir.c" # include "virtuals.c" #endif diff --git a/libq/profile.c b/libq/profile.c new file mode 100644 index 00000000..79e9577d --- /dev/null +++ b/libq/profile.c @@ -0,0 +1,77 @@ +typedef void *(q_profile_callback_t)(void *, char *, FILE *); + +_q_static void * +q_profile_walk_at(int dir_fd, const char *dir, const char *file, + q_profile_callback_t callback, void *data) +{ + FILE *fp; + int subdir_fd, fd; + size_t buflen; + char *buf; + + /* Pop open this profile dir */ + subdir_fd = openat(dir_fd, dir, O_RDONLY|O_CLOEXEC); + if (subdir_fd < 0) + return data; + + /* Then open the file */ + fd = openat(subdir_fd, file, O_RDONLY|O_CLOEXEC); + if (fd < 0) + goto walk_parent; + + fp = fdopen(fd, "r"); + if (!fp) { + close(fd); + goto walk_parent; + } + + /* hand feed the file to the callback */ + buf = NULL; + while (getline(&buf, &buflen, fp) != -1) + data = callback(data, buf, fp); + free(buf); + + /* does close(fd) for us */ + fclose(fp); + + /* Now walk the parents */ + walk_parent: + fd = openat(subdir_fd, "parent", O_RDONLY|O_CLOEXEC); + if (fd < 0) + goto done; + fp = fdopen(fd, "r"); + if (!fp) { + close(fd); + goto done; + } + + buf = NULL; + while (getline(&buf, &buflen, fp) != -1) { + char *s; + + s = strchr(buf, '#'); + if (s) + *s = '\0'; + rmspace(buf); + + data = q_profile_walk_at(subdir_fd, buf, file, callback, data); + } + free(buf); + + /* does close(fd) for us */ + fclose(fp); + + done: + if (subdir_fd != AT_FDCWD) + close(subdir_fd); + + return data; +} + +_q_static void * +q_profile_walk(const char *file, q_profile_callback_t callback, void *data) +{ + /* Walk the profiles and read the file in question */ + data = q_profile_walk_at(AT_FDCWD, EPREFIX "/etc/make.profile", file, callback, data); + return q_profile_walk_at(AT_FDCWD, EPREFIX "/etc/portage/make.profile", file, callback, data); +} diff --git a/libq/virtuals.c b/libq/virtuals.c index 2f9fb87d..52ed8254 100644 --- a/libq/virtuals.c +++ b/libq/virtuals.c @@ -1,12 +1,12 @@ /* * Copyright 2005-2010 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 - * $Header: /var/cvsroot/gentoo-projects/portage-utils/libq/virtuals.c,v 1.25 2011/02/24 01:29:27 vapier Exp $ + * $Header: /var/cvsroot/gentoo-projects/portage-utils/libq/virtuals.c,v 1.26 2011/03/02 07:03:31 vapier Exp $ * * Copyright 2005-2010 Ned Ludd - <solar@gentoo.org> * Copyright 2005-2010 Mike Frysinger - <vapier@gentoo.org> * - * $Header: /var/cvsroot/gentoo-projects/portage-utils/libq/virtuals.c,v 1.25 2011/02/24 01:29:27 vapier Exp $ + * $Header: /var/cvsroot/gentoo-projects/portage-utils/libq/virtuals.c,v 1.26 2011/03/02 07:03:31 vapier Exp $ */ #include <stdio.h> @@ -81,10 +81,12 @@ queue *add_set(const char *vv, const char *ss, queue *q) strcpy(s, ptr); } while (v[0]); + free(s); free(ptr); free(v); free(vptr); + return q; } @@ -248,57 +250,28 @@ static queue *resolve_local_profile_virtuals(void) return virtuals; } -static queue *resolve_virtuals(void) +_q_static void * +resolve_virtuals_line(void *data, char *buf, FILE *fp) { - static char buf[_Q_PATH_MAX]; - static char savecwd[_Q_PATH_MAX]; - static char *p; - FILE *fp; + char *p; + + if (*buf != 'v') + return data; - xgetcwd(savecwd, sizeof(savecwd)); + rmspace(buf); + if ((p = strchr(buf, ' ')) != NULL) { + *p = 0; + if (virtual(buf, virtuals) == NULL) + virtuals = add_set(buf, rmspace(++p), virtuals); + } + + return data; +} +_q_static queue *resolve_virtuals(void) +{ free_sets(virtuals); virtuals = resolve_local_profile_virtuals(); virtuals = resolve_vdb_virtuals(portvdb); - - if (chdir("/etc/") == -1) - return virtuals; - - if (readlink("make.profile", buf, sizeof(buf)) != -1) { - xchdir(buf); - xgetcwd(buf, sizeof(buf)); - if (access(buf, R_OK) != 0) - return virtuals; - vstart: - if ((fp = fopen("virtuals", "r")) != NULL) { - while ((fgets(buf, sizeof(buf), fp)) != NULL) { - if (*buf != 'v') continue; - rmspace(buf); - if ((p = strchr(buf, ' ')) != NULL) { - *p = 0; - if (virtual(buf, virtuals) == NULL) - virtuals = add_set(buf, rmspace(++p), virtuals); - } - } - fclose(fp); - } - if ((fp = fopen("parent", "r")) != NULL) { - while ((fgets(buf, sizeof(buf), fp)) != NULL) { - rmspace(buf); - if (!*buf) continue; - if (*buf == '#') continue; - if (isspace(*buf)) continue; - fclose(fp); - if (chdir(buf) == -1) { - fclose(fp); - goto done; - } - goto vstart; - } - fclose(fp); - } - } - done: - xchdir(savecwd); - return virtuals; + return q_profile_walk("virtuals", resolve_virtuals_line, virtuals); } |