Gentoo Archives: gentoo-commits

From: Fabian Groffen <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage-utils:master commit in: /, libq/
Date: Fri, 15 Nov 2019 13:52:21
Message-Id: 1573825810.5ec1f4368412c8d6f02148d3d9cb109050c8c626.grobian@gentoo
1 commit: 5ec1f4368412c8d6f02148d3d9cb109050c8c626
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Fri Nov 15 13:50:10 2019 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Fri Nov 15 13:50:10 2019 +0000
6 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=5ec1f436
7
8 libq/xpak: rework to reuse more code
9
10 - introduce xpak_process{,_fd} to replace the very similar list and extract
11 - add _fd variant to be able to pass already open filedescriptor
12 - rework interface to carry a context pointer for the callback func for
13 more flexibility
14 - adapt qxpak for the interface changes
15
16 Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
17
18 libq/xpak.c | 132 ++++++++++++++++++++++++++----------------------------------
19 libq/xpak.h | 26 +++---------
20 qxpak.c | 98 ++++++++++++++++++++++++++------------------
21 3 files changed, 120 insertions(+), 136 deletions(-)
22
23 diff --git a/libq/xpak.c b/libq/xpak.c
24 index c2e93f9..9692eab 100644
25 --- a/libq/xpak.c
26 +++ b/libq/xpak.c
27 @@ -39,23 +39,22 @@
28 #define XPAK_END_MSG_LEN 8
29
30 typedef struct {
31 - int dir_fd;
32 + void *ctx;
33 FILE *fp;
34 - int index_len;
35 - int data_len;
36 + unsigned int index_len;
37 + unsigned int data_len;
38 char *index, *data;
39 } _xpak_archive;
40
41 -typedef void (*xpak_callback_t)(int,char*,int,int,int,char*);
42 -
43 static void _xpak_walk_index(
44 _xpak_archive *x,
45 - int argc,
46 - char **argv,
47 xpak_callback_t func)
48 {
49 - int i, pathname_len, data_offset, data_len;
50 - char *p, pathname[100];
51 + unsigned int pathname_len;
52 + unsigned int data_offset;
53 + unsigned int data_len;
54 + char *p;
55 + char pathname[100];
56
57 p = x->index;
58 while ((p - x->index) < x->index_len) {
59 @@ -73,43 +72,26 @@ static void _xpak_walk_index(
60 p += 4;
61 data_len = READ_BE_INT32((unsigned char*)p);
62 p += 4;
63 - if (argc) {
64 - for (i = 0; i < argc; ++i) {
65 - if (argv[i] && !strcmp(pathname, argv[i])) {
66 - argv[i] = NULL;
67 - break;
68 - }
69 - }
70 - if (i == argc)
71 - continue;
72 - }
73 - (*func)(x->dir_fd, pathname, pathname_len,
74 + (*func)(x->ctx, pathname, pathname_len,
75 data_offset, data_len, x->data);
76 }
77 -
78 - if (argc)
79 - for (i = 0; i < argc; ++i)
80 - if (argv[i])
81 - warn("Could not locate '%s' in archive", argv[i]);
82 }
83
84 -static _xpak_archive *_xpak_open(const char *file)
85 +static _xpak_archive *_xpak_open(const int fd)
86 {
87 static _xpak_archive ret;
88 char buf[XPAK_START_LEN];
89
90 /* init the file */
91 memset(&ret, 0x00, sizeof(ret));
92 - if (file[0] == '-' && file[1] == '\0')
93 - ret.fp = stdin;
94 - else if ((ret.fp = fopen(file, "r")) == NULL)
95 + if ((ret.fp = fdopen(fd, "r")) == NULL)
96 return NULL;
97
98 /* verify this xpak doesnt suck */
99 if (fread(buf, 1, XPAK_START_LEN, ret.fp) != XPAK_START_LEN)
100 goto close_and_ret;
101 if (memcmp(buf, XPAK_START_MSG, XPAK_START_MSG_LEN)) {
102 - warn("%s: Invalid xpak", file);
103 + warn("Not an xpak file");
104 goto close_and_ret;
105 }
106
107 @@ -117,7 +99,7 @@ static _xpak_archive *_xpak_open(const char *file)
108 ret.index_len = READ_BE_INT32((unsigned char*)buf+XPAK_START_MSG_LEN);
109 ret.data_len = READ_BE_INT32((unsigned char*)buf+XPAK_START_MSG_LEN+4);
110 if (!ret.index_len || !ret.data_len) {
111 - warn("Skipping empty archive '%s'", file);
112 + warn("Skipping empty archive");
113 goto close_and_ret;
114 }
115
116 @@ -135,52 +117,21 @@ static void _xpak_close(_xpak_archive *x)
117 }
118
119 int
120 -xpak_list(
121 - int dir_fd,
122 - const char *file,
123 - int argc,
124 - char **argv,
125 - xpak_callback_t func)
126 -{
127 - _xpak_archive *x;
128 - char buf[BUFSIZE];
129 - size_t ret;
130 -
131 - x = _xpak_open(file);
132 - if (!x)
133 - return 1;
134 -
135 - x->dir_fd = dir_fd;
136 - x->index = buf;
137 - if (x->index_len >= sizeof(buf))
138 - err("index length %d exceeds limit %zd", x->index_len, sizeof(buf));
139 - ret = fread(x->index, 1, x->index_len, x->fp);
140 - if (ret != (size_t)x->index_len)
141 - err("insufficient data read, got %zd, requested %d", ret, x->index_len);
142 - _xpak_walk_index(x, argc, argv, func);
143 -
144 - _xpak_close(x);
145 -
146 - return 0;
147 -}
148 -
149 -int
150 -xpak_extract(
151 - int dir_fd,
152 - const char *file,
153 - int argc,
154 - char **argv,
155 +xpak_process_fd(
156 + int fd,
157 + bool get_data,
158 + void *ctx,
159 xpak_callback_t func)
160 {
161 _xpak_archive *x;
162 char buf[BUFSIZE], ext[BUFSIZE*32];
163 size_t in;
164
165 - x = _xpak_open(file);
166 + x = _xpak_open(fd);
167 if (!x)
168 return 1;
169
170 - x->dir_fd = dir_fd;
171 + x->ctx = ctx;
172 x->index = buf;
173
174 if (x->index_len >= sizeof(buf))
175 @@ -189,22 +140,51 @@ xpak_extract(
176 if (in != (size_t)x->index_len)
177 err("insufficient data read, got %zd, requested %d", in, x->index_len);
178
179 - /* the xpak may be large (like when it has CONTENTS) #300744 */
180 - x->data = (size_t)x->data_len < sizeof(ext) ? ext : xmalloc(x->data_len);
181 - in = fread(x->data, 1, x->data_len, x->fp);
182 - if (in != (size_t)x->data_len)
183 - err("insufficient data read, got %zd, requested %d", in, x->data_len);
184 + if (get_data) {
185 + /* the xpak may be large (like when it has CONTENTS) #300744 */
186 + x->data = (size_t)x->data_len < sizeof(ext) ?
187 + ext : xmalloc(x->data_len);
188 + in = fread(x->data, 1, x->data_len, x->fp);
189 + if (in != (size_t)x->data_len)
190 + err("insufficient data read, got %zd, requested %d",
191 + in, x->data_len);
192 + } else {
193 + x->data = NULL;
194 + x->data_len = 0;
195 + }
196
197 - _xpak_walk_index(x, argc, argv, func);
198 + _xpak_walk_index(x, func);
199
200 _xpak_close(x);
201
202 - if (x->data != ext)
203 + if (get_data && x->data != ext)
204 free(x->data);
205
206 return 0;
207 }
208
209 +int
210 +xpak_process(
211 + const char *file,
212 + bool get_data,
213 + void *ctx,
214 + xpak_callback_t func)
215 +{
216 + int fd = -1;
217 + int ret;
218 +
219 + if (file[0] == '-' && file[1] == '\0')
220 + fd = 0;
221 + else if ((fd = open(file, O_RDONLY | O_CLOEXEC)) == -1)
222 + return -1;
223 +
224 + ret = xpak_process_fd(fd, get_data, ctx, func);
225 + if (ret != 0)
226 + warn("Unable to open file '%s'", file);
227 +
228 + return ret;
229 +}
230 +
231 static void
232 _xpak_add_file(
233 int dir_fd,
234 @@ -279,7 +259,7 @@ xpak_create(
235 const char *file,
236 int argc,
237 char **argv,
238 - char append,
239 + bool append,
240 int verbose)
241 {
242 FILE *findex, *fdata, *fout;
243
244 diff --git a/libq/xpak.h b/libq/xpak.h
245 index 0b318b2..aeafdae 100644
246 --- a/libq/xpak.h
247 +++ b/libq/xpak.h
248 @@ -6,26 +6,12 @@
249 #ifndef _XPAK_H
250 #define _XPAK_H 1
251
252 -typedef void (*xpak_callback_t)(int,char*,int,int,int,char*);
253 +typedef void (*xpak_callback_t)(void *, char *, int, int, int, char *);
254
255 -int xpak_list(
256 - int dir_fd,
257 - const char *file,
258 - int argc,
259 - char **argv,
260 - xpak_callback_t func);
261 -int xpak_extract(
262 - int dir_fd,
263 - const char *file,
264 - int argc,
265 - char **argv,
266 - xpak_callback_t func);
267 -int xpak_create(
268 - int dir_fd,
269 - const char *file,
270 - int argc,
271 - char **argv,
272 - char append,
273 - int v);
274 +int xpak_process_fd(int, bool, void *, xpak_callback_t);
275 +int xpak_process(const char *, bool, void *, xpak_callback_t);
276 +#define xpak_list(A,B,C) xpak_process(A,false,B,C)
277 +#define xpak_extract(A,B,C) xpak_process(A,true,B,C)
278 +int xpak_create(int, const char *, int, char **, bool, int);
279
280 #endif
281
282 diff --git a/qxpak.c b/qxpak.c
283 index eb19cae..fd0ec5d 100644
284 --- a/qxpak.c
285 +++ b/qxpak.c
286 @@ -42,31 +42,16 @@ static const char * const qxpak_opts_help[] = {
287
288 static char xpak_stdout;
289
290 -static void
291 -_xpak_list_callback(
292 - int dir_fd,
293 - char *pathname,
294 - int pathname_len,
295 - int data_offset,
296 - int data_len,
297 - char *data)
298 -{
299 - (void)dir_fd;
300 - (void)pathname_len;
301 - (void)data;
302 -
303 - if (!verbose)
304 - puts(pathname);
305 - else if (verbose == 1)
306 - printf("%s: %i byte%c\n", pathname, data_len, (data_len>1?'s':' '));
307 - else
308 - printf("%s: %i byte%c @ offset byte %i\n",
309 - pathname, data_len, (data_len>1?'s':' '), data_offset);
310 -}
311 +struct qxpak_cb {
312 + int dir_fd;
313 + int argc;
314 + char **argv;
315 + bool extract;
316 +};
317
318 static void
319 -_xpak_extract_callback(
320 - int dir_fd,
321 +_xpak_callback(
322 + void *ctx,
323 char *pathname,
324 int pathname_len,
325 int data_offset,
326 @@ -74,16 +59,38 @@ _xpak_extract_callback(
327 char *data)
328 {
329 FILE *out;
330 - (void)pathname_len;
331 + struct qxpak_cb *xctx = (struct qxpak_cb *)ctx;
332 +
333 + /* see if there is a match when there is a selection */
334 + if (xctx->argc > 0) {
335 + int i;
336 + for (i = 0; i < xctx->argc; i++) {
337 + if (xctx->argv[i] && !strcmp(pathname, xctx->argv[i])) {
338 + xctx->argv[i] = NULL;
339 + break;
340 + }
341 + }
342 + if (i == xctx->argc)
343 + return;
344 + }
345
346 - if (verbose == 1)
347 - puts(pathname);
348 - else if (verbose > 1)
349 - printf("%s: %i byte%c\n", pathname, data_len, (data_len>1?'s':' '));
350 + if (verbose == 0 + (xctx->extract ? 1 : 0))
351 + printf("%.*s", pathname_len, pathname);
352 + else if (verbose == 1 + (xctx->extract ? 1 : 0))
353 + printf("%.*s: %d byte%s\n",
354 + pathname_len, pathname,
355 + data_len, (data_len > 1 ? "s" : ""));
356 + else
357 + printf("%.*s: %d byte%s @ offset byte %d\n",
358 + pathname_len, pathname,
359 + data_len, (data_len > 1 ? "s" : ""), data_offset);
360 +
361 + if (!xctx->extract)
362 + return;
363
364 if (!xpak_stdout) {
365 - int fd = openat(dir_fd, pathname,
366 - O_WRONLY|O_CLOEXEC|O_CREAT|O_TRUNC, 0644);
367 + int fd = openat(xctx->dir_fd, pathname,
368 + O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, 0644);
369 if (fd < 0)
370 return;
371 out = fdopen(fd, "w");
372 @@ -101,12 +108,14 @@ _xpak_extract_callback(
373 int qxpak_main(int argc, char **argv)
374 {
375 enum { XPAK_ACT_NONE, XPAK_ACT_LIST, XPAK_ACT_EXTRACT, XPAK_ACT_CREATE };
376 - int i, ret, dir_fd;
377 + int i, ret;
378 char *xpak;
379 char action = XPAK_ACT_NONE;
380 + struct qxpak_cb cbctx;
381
382 - dir_fd = AT_FDCWD;
383 xpak_stdout = 0;
384 + cbctx.dir_fd = AT_FDCWD;
385 + cbctx.extract = false;
386
387 while ((i = GETOPT_LONG(QXPAK, qxpak, "")) != -1) {
388 switch (i) {
389 @@ -116,10 +125,10 @@ int qxpak_main(int argc, char **argv)
390 case 'c': action = XPAK_ACT_CREATE; break;
391 case 'O': xpak_stdout = 1; break;
392 case 'd':
393 - if (dir_fd != AT_FDCWD)
394 + if (cbctx.dir_fd != AT_FDCWD)
395 err("Only use -d once");
396 - dir_fd = open(optarg, O_RDONLY|O_CLOEXEC|O_PATH);
397 - if (dir_fd < 0)
398 + cbctx.dir_fd = open(optarg, O_RDONLY|O_CLOEXEC|O_PATH);
399 + if (cbctx.dir_fd < 0)
400 errp("Could not open directory %s", optarg);
401 break;
402 }
403 @@ -130,23 +139,32 @@ int qxpak_main(int argc, char **argv)
404 xpak = argv[optind++];
405 argc -= optind;
406 argv += optind;
407 + cbctx.argc = argc;
408 + cbctx.argv = argv;
409
410 switch (action) {
411 case XPAK_ACT_LIST:
412 - ret = xpak_list(dir_fd, xpak, argc, argv, &_xpak_list_callback);
413 + ret = xpak_list(xpak, &cbctx, &_xpak_callback);
414 break;
415 case XPAK_ACT_EXTRACT:
416 - ret = xpak_extract(dir_fd, xpak, argc, argv, &_xpak_extract_callback);
417 + cbctx.extract = true;
418 + ret = xpak_extract(xpak, &cbctx, &_xpak_callback);
419 break;
420 case XPAK_ACT_CREATE:
421 - ret = xpak_create(dir_fd, xpak, argc, argv, 0, verbose);
422 + ret = xpak_create(cbctx.dir_fd, xpak, argc, argv, 0, verbose);
423 break;
424 default:
425 ret = EXIT_FAILURE;
426 }
427
428 - if (dir_fd != AT_FDCWD)
429 - close(dir_fd);
430 + if (cbctx.dir_fd != AT_FDCWD)
431 + close(cbctx.dir_fd);
432 +
433 + /* warn about non-matched args */
434 + if (argc > 0 && (action == XPAK_ACT_LIST || action == XPAK_ACT_EXTRACT))
435 + for (i = 0; i < argc; ++i)
436 + if (argv[i])
437 + warn("Could not locate '%s' in archive", argv[i]);
438
439 return ret;
440 }