aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2011-03-02 07:03:31 +0000
committerMike Frysinger <vapier@gentoo.org>2011-03-02 07:03:31 +0000
commit4c2427c67a7cad2d696e506278e54561c918df4c (patch)
tree2104745a9cf66ef58857ed1b6d761a4f70744f45
parentfix up extended line reading to avoid buffer overflows (diff)
downloadportage-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.c1
-rw-r--r--libq/profile.c77
-rw-r--r--libq/virtuals.c71
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);
}