1 |
commit: 0bbdb3f1328dcd0dd91c1ea502da3ba3e1fd364d |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun May 5 08:46:47 2019 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun May 5 08:46:47 2019 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=0bbdb3f1 |
7 |
|
8 |
libq/cache: add support for reading metadata.xml |
9 |
|
10 |
currently only one field is extracted: email |
11 |
|
12 |
Bug: https://bugs.gentoo.org/685052 |
13 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
14 |
|
15 |
libq/cache.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
16 |
libq/cache.h | 9 ++++++ |
17 |
2 files changed, 106 insertions(+), 2 deletions(-) |
18 |
|
19 |
diff --git a/libq/cache.c b/libq/cache.c |
20 |
index a8b4ede..c0ea85e 100644 |
21 |
--- a/libq/cache.c |
22 |
+++ b/libq/cache.c |
23 |
@@ -167,6 +167,9 @@ cache_next_pkg(cache_cat_ctx *cat_ctx) |
24 |
ctx->ebuilddir_pkg_ctx = NULL; |
25 |
return NULL; |
26 |
} |
27 |
+ |
28 |
+ /* "zap" the pkg such that it looks like CAT/P */ |
29 |
+ ctx->ebuilddir_cat_ctx->name = cat_ctx->name; |
30 |
} |
31 |
|
32 |
ret = q_vdb_next_pkg(ctx->ebuilddir_cat_ctx); |
33 |
@@ -178,8 +181,6 @@ cache_next_pkg(cache_cat_ctx *cat_ctx) |
34 |
cache_close_pkg(ret); |
35 |
ret = NULL; |
36 |
} else { |
37 |
- /* "zap" the pkg such that it looks like CAT/P */ |
38 |
- ret->cat_ctx->name = cat_ctx->name; |
39 |
*p = '\0'; |
40 |
} |
41 |
} |
42 |
@@ -529,6 +530,100 @@ cache_close_meta(cache_pkg_meta *cache) |
43 |
free(cache); |
44 |
} |
45 |
|
46 |
+cache_metadata_xml * |
47 |
+cache_read_metadata(cache_pkg_ctx *pkg_ctx) |
48 |
+{ |
49 |
+ cache_ctx *ctx = (cache_ctx *)(pkg_ctx->cat_ctx->ctx); |
50 |
+ int fd; |
51 |
+ FILE *f; |
52 |
+ struct stat s; |
53 |
+ char *xbuf; |
54 |
+ char *p; |
55 |
+ char *q; |
56 |
+ size_t len; |
57 |
+ cache_metadata_xml *ret = NULL; |
58 |
+ struct elist *emailw = NULL; |
59 |
+ char buf[_Q_PATH_MAX]; |
60 |
+ |
61 |
+ /* lame @$$ XML parsing, I don't want to pull in a real parser |
62 |
+ * library because we only retrieve one element for now: email |
63 |
+ * technically speaking, email may occur only once in a maintainer |
64 |
+ * tag, but practically speaking we don't care at all, so we can |
65 |
+ * just extract everything between <email> and </email> */ |
66 |
+ |
67 |
+ if (ctx->cachetype == CACHE_EBUILD) { |
68 |
+ fd = openat(pkg_ctx->cat_ctx->fd, "metadata", O_RDONLY | O_CLOEXEC); |
69 |
+ } else { |
70 |
+ depend_atom *atom; |
71 |
+ snprintf(buf, sizeof(buf), "%s/%s", |
72 |
+ pkg_ctx->cat_ctx->name, pkg_ctx->name); |
73 |
+ atom = atom_explode(buf); |
74 |
+ snprintf(buf, sizeof(buf), "../../%s/%s/metadata.xml", |
75 |
+ atom->CATEGORY, atom->PN); |
76 |
+ atom_implode(atom); |
77 |
+ fd = openat(ctx->vdb_fd, buf, O_RDONLY | O_CLOEXEC); |
78 |
+ } |
79 |
+ |
80 |
+ if (fd == -1) |
81 |
+ return NULL; |
82 |
+ |
83 |
+ if ((f = fdopen(fd, "r")) == NULL) { |
84 |
+ close(fd); |
85 |
+ return NULL; |
86 |
+ } |
87 |
+ |
88 |
+ if (fstat(fd, &s) != 0) { |
89 |
+ fclose(f); |
90 |
+ return NULL; |
91 |
+ } |
92 |
+ |
93 |
+ len = sizeof(*ret) + s.st_size + 1; |
94 |
+ p = xbuf = xzalloc(len); |
95 |
+ if ((off_t)fread(p, 1, s.st_size, f) != s.st_size) { |
96 |
+ free(p); |
97 |
+ fclose(f); |
98 |
+ pkg_ctx->fd = -1; |
99 |
+ return NULL; |
100 |
+ } |
101 |
+ |
102 |
+ ret = xmalloc(sizeof(*ret)); |
103 |
+ ret->email = NULL; |
104 |
+ |
105 |
+ while ((q = strstr(p, "<email>")) != NULL) { |
106 |
+ p = q + sizeof("<email>") - 1; |
107 |
+ if ((q = strstr(p, "</email>")) == NULL) |
108 |
+ break; |
109 |
+ *q = '\0'; |
110 |
+ rmspace(p); |
111 |
+ if (emailw == NULL) { |
112 |
+ emailw = ret->email = xmalloc(sizeof(*emailw)); |
113 |
+ } else { |
114 |
+ emailw = emailw->next = xmalloc(sizeof(*emailw)); |
115 |
+ } |
116 |
+ emailw->next = NULL; |
117 |
+ emailw->addr = xstrdup(p); |
118 |
+ p = q + 1; |
119 |
+ } |
120 |
+ |
121 |
+ free(xbuf); |
122 |
+ fclose(f); |
123 |
+ return ret; |
124 |
+} |
125 |
+ |
126 |
+void |
127 |
+cache_close_metadata(cache_metadata_xml *meta_ctx) |
128 |
+{ |
129 |
+ struct elist *e; |
130 |
+ while (meta_ctx->email != NULL) { |
131 |
+ e = meta_ctx->email; |
132 |
+ free(e->addr); |
133 |
+ e = e->next; |
134 |
+ free(meta_ctx->email); |
135 |
+ meta_ctx->email = e; |
136 |
+ } |
137 |
+ free(meta_ctx); |
138 |
+} |
139 |
+ |
140 |
void |
141 |
cache_close_pkg(cache_pkg_ctx *pkg_ctx) |
142 |
{ |
143 |
|
144 |
diff --git a/libq/cache.h b/libq/cache.h |
145 |
index 74f45b8..2ad2e78 100644 |
146 |
--- a/libq/cache.h |
147 |
+++ b/libq/cache.h |
148 |
@@ -43,6 +43,13 @@ typedef struct { |
149 |
char *_md5_; |
150 |
} cache_pkg_meta; |
151 |
|
152 |
+typedef struct { |
153 |
+ struct elist { |
154 |
+ char *addr; |
155 |
+ struct elist *next; |
156 |
+ } *email; |
157 |
+} cache_metadata_xml; |
158 |
+ |
159 |
typedef int (cache_pkg_cb)(cache_pkg_ctx *, void *priv); |
160 |
typedef int (cache_cat_filter)(cache_cat_ctx *, void *priv); |
161 |
|
162 |
@@ -55,6 +62,8 @@ cache_pkg_ctx *cache_open_pkg(cache_cat_ctx *cat_ctx, const char *name); |
163 |
cache_pkg_ctx *cache_next_pkg(cache_cat_ctx *cat_ctx); |
164 |
cache_pkg_meta *cache_pkg_read(cache_pkg_ctx *pkg_ctx); |
165 |
void cache_close_meta(cache_pkg_meta *cache); |
166 |
+cache_metadata_xml *cache_read_metadata(cache_pkg_ctx *pkg_ctx); |
167 |
+void cache_close_metadata(cache_metadata_xml *meta_ctx); |
168 |
void cache_close_pkg(cache_pkg_ctx *pkg_ctx); |
169 |
int cache_foreach_pkg(const char *sroot, const char *portdir, |
170 |
cache_pkg_cb callback, void *priv, cache_cat_filter filter); |