aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2019-03-27 11:53:58 +0100
committerFabian Groffen <grobian@gentoo.org>2019-03-27 11:53:58 +0100
commitd0a8d231167adddb80a73849d3bc70edbfda3507 (patch)
tree387e1ffea50f8da37063ce5be638fe35f7397712 /qxpak.c
parentlibq: split out cache-related funcs from main/qsearch (diff)
downloadportage-utils-d0a8d231167adddb80a73849d3bc70edbfda3507.tar.gz
portage-utils-d0a8d231167adddb80a73849d3bc70edbfda3507.tar.bz2
portage-utils-d0a8d231167adddb80a73849d3bc70edbfda3507.zip
build: compile applets as separate objects
Instead of including everything from a single file, compile each applet separately. This standardises things somewhat, and allows for parallel compilation. Signed-off-by: Fabian Groffen <grobian@gentoo.org>
Diffstat (limited to 'qxpak.c')
-rw-r--r--qxpak.c374
1 files changed, 46 insertions, 328 deletions
diff --git a/qxpak.c b/qxpak.c
index bdd5294..eb19cae 100644
--- a/qxpak.c
+++ b/qxpak.c
@@ -1,32 +1,25 @@
/*
- * Copyright 2005-2018 Gentoo Foundation
+ * Copyright 2005-2019 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
*
* Copyright 2005-2010 Ned Ludd - <solar@gentoo.org>
* Copyright 2005-2014 Mike Frysinger - <vapier@gentoo.org>
*/
-#ifdef APPLET_qxpak
+#include "main.h"
+#include "applets.h"
-/*
-# The format for a tbz2/xpak:
-#
-# tbz2: tar.bz2 + xpak + (xpak_offset) + "STOP"
-# xpak: "XPAKPACK" + (index_len) + (data_len) + index + data + "XPAKSTOP"
-# index: (pathname_len) + pathname + (data_offset) + (data_len)
-# index entries are concatenated end-to-end.
-# data: concatenated data chunks, end-to-end.
-#
-# [tarball]XPAKPACKIIIIDDDD[index][data]XPAKSTOPOOOOSTOP
-#
-# (integer) == encodeint(integer) ===> 4 characters (big-endian copy)
-# '+' means concatenate the fields ===> All chunks are strings
-*/
-#define XPAK_START_MSG "XPAKPACK"
-#define XPAK_START_MSG_LEN 8
-#define XPAK_START_LEN (8 + 4 + 4)
-#define XPAK_END_MSG "XPAKSTOP"
-#define XPAK_END_MSG_LEN 8
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "basename.h"
+#include "copy_file.h"
+#include "safe_io.h"
+#include "scandirat.h"
+#include "xpak.h"
#define QXPAK_FLAGS "lxcd:O" COMMON_FLAGS
static struct option const qxpak_long_opts[] = {
@@ -47,100 +40,21 @@ static const char * const qxpak_opts_help[] = {
};
#define qxpak_usage(ret) usage(ret, QXPAK_FLAGS, qxpak_long_opts, qxpak_opts_help, NULL, lookup_applet_idx("qxpak"))
-typedef struct {
- int dir_fd;
- FILE *fp;
- int index_len;
- int data_len;
- char *index, *data;
-} _xpak_archive;
-
static char xpak_stdout;
-typedef void (*xpak_callback_t)(int,char*,int,int,int,char*);
-
-static void _xpak_walk_index(_xpak_archive *x, int argc, char **argv, xpak_callback_t func)
-{
- int i, pathname_len, data_offset, data_len;
- char *p, pathname[100];
-
- p = x->index;
- while ((p - x->index) < x->index_len) {
- pathname_len = tbz2_decode_int((unsigned char*)p);
- assert((size_t)pathname_len < sizeof(pathname));
- p += 4;
- memcpy(pathname, p, pathname_len);
- pathname[pathname_len] = '\0';
- if (strchr(pathname, '/') != NULL || strchr(pathname, '\\') != NULL)
- err("Index contains a file with a path: '%s'", pathname);
- p += pathname_len;
- data_offset = tbz2_decode_int((unsigned char*)p);
- p += 4;
- data_len = tbz2_decode_int((unsigned char*)p);
- p += 4;
- if (argc) {
- for (i = 0; i < argc; ++i)
- if (argv[i] && !strcmp(pathname, argv[i])) {
- argv[i] = NULL;
- break;
- }
- if (i == argc)
- continue;
- }
- (*func)(x->dir_fd, pathname, pathname_len, data_offset, data_len, x->data);
- }
-
- if (argc)
- for (i = 0; i < argc; ++i)
- if (argv[i])
- warn("Could not locate '%s' in archive", argv[i]);
-}
-
-static _xpak_archive *_xpak_open(const char *file)
-{
- static _xpak_archive ret;
- char buf[XPAK_START_LEN];
-
- /* init the file */
- memset(&ret, 0x00, sizeof(ret));
- if (file[0] == '-' && file[1] == '\0')
- ret.fp = stdin;
- else if ((ret.fp = fopen(file, "r")) == NULL)
- return NULL;
-
- /* verify this xpak doesnt suck */
- if (fread(buf, 1, XPAK_START_LEN, ret.fp) != XPAK_START_LEN)
- goto close_and_ret;
- if (memcmp(buf, XPAK_START_MSG, XPAK_START_MSG_LEN)) {
- warn("%s: Invalid xpak", file);
- goto close_and_ret;
- }
-
- /* calc index and data sizes */
- ret.index_len = tbz2_decode_int((unsigned char*)buf+XPAK_START_MSG_LEN);
- ret.data_len = tbz2_decode_int((unsigned char*)buf+XPAK_START_MSG_LEN+4);
- if (!ret.index_len || !ret.data_len) {
- warn("Skipping empty archive '%s'", file);
- goto close_and_ret;
- }
-
- return &ret;
-
-close_and_ret:
- if (ret.fp != stdin)
- fclose(ret.fp);
- return NULL;
-}
-
-static void _xpak_close(_xpak_archive *x)
-{
- fclose(x->fp);
-}
-
static void
-_xpak_list_callback(_q_unused_ int dir_fd, char *pathname, _q_unused_ int pathname_len,
- int data_offset, int data_len, _q_unused_ char *data)
+_xpak_list_callback(
+ int dir_fd,
+ char *pathname,
+ int pathname_len,
+ int data_offset,
+ int data_len,
+ char *data)
{
+ (void)dir_fd;
+ (void)pathname_len;
+ (void)data;
+
if (!verbose)
puts(pathname);
else if (verbose == 1)
@@ -149,34 +63,18 @@ _xpak_list_callback(_q_unused_ int dir_fd, char *pathname, _q_unused_ int pathna
printf("%s: %i byte%c @ offset byte %i\n",
pathname, data_len, (data_len>1?'s':' '), data_offset);
}
-static int
-xpak_list(int dir_fd, const char *file, int argc, char **argv)
-{
- _xpak_archive *x;
- char buf[BUFSIZE];
- size_t ret;
-
- x = _xpak_open(file);
- if (!x)
- return 1;
-
- x->dir_fd = dir_fd;
- x->index = buf;
- assert((size_t)x->index_len < sizeof(buf));
- ret = fread(x->index, 1, x->index_len, x->fp);
- assert(ret == (size_t)x->index_len);
- _xpak_walk_index(x, argc, argv, &_xpak_list_callback);
-
- _xpak_close(x);
-
- return 0;
-}
static void
-_xpak_extract_callback(int dir_fd, char *pathname, _q_unused_ int pathname_len,
- int data_offset, int data_len, char *data)
+_xpak_extract_callback(
+ int dir_fd,
+ char *pathname,
+ int pathname_len,
+ int data_offset,
+ int data_len,
+ char *data)
{
FILE *out;
+ (void)pathname_len;
if (verbose == 1)
puts(pathname);
@@ -184,7 +82,8 @@ _xpak_extract_callback(int dir_fd, char *pathname, _q_unused_ int pathname_len,
printf("%s: %i byte%c\n", pathname, data_len, (data_len>1?'s':' '));
if (!xpak_stdout) {
- int fd = openat(dir_fd, pathname, O_WRONLY|O_CLOEXEC|O_CREAT|O_TRUNC, 0644);
+ int fd = openat(dir_fd, pathname,
+ O_WRONLY|O_CLOEXEC|O_CREAT|O_TRUNC, 0644);
if (fd < 0)
return;
out = fdopen(fd, "w");
@@ -198,190 +97,6 @@ _xpak_extract_callback(int dir_fd, char *pathname, _q_unused_ int pathname_len,
if (!xpak_stdout)
fclose(out);
}
-static int
-xpak_extract(int dir_fd, const char *file, int argc, char **argv)
-{
- _xpak_archive *x;
- char buf[BUFSIZE], ext[BUFSIZE*32];
- size_t in;
-
- x = _xpak_open(file);
- if (!x)
- return 1;
-
- x->dir_fd = dir_fd;
- x->index = buf;
-
- assert((size_t)x->index_len < sizeof(buf));
- in = fread(x->index, 1, x->index_len, x->fp);
- if ((int)in != x->index_len)
- err("index chunk: read %i bytes, wanted %i bytes", (int)in, x->index_len);
-
- /* the xpak may be large (like when it has CONTENTS) #300744 */
- x->data = (size_t)x->data_len < sizeof(ext) ? ext : xmalloc(x->data_len);
- in = fread(x->data, 1, x->data_len, x->fp);
- if ((int)in != x->data_len)
- err("data chunk: read %i bytes, wanted %i bytes", (int)in, x->data_len);
-
- _xpak_walk_index(x, argc, argv, &_xpak_extract_callback);
-
- _xpak_close(x);
-
- if (x->data != ext)
- free(x->data);
-
- return 0;
-}
-
-static void
-_xpak_add_file(int dir_fd, const char *filename, struct stat *st, FILE *findex,
- int *index_len, FILE *fdata, int *data_len)
-{
- FILE *fin;
- unsigned char *p;
- const char *basefile;
- int fd, in_len;
-
- if ((basefile = strrchr(filename, '/')) == NULL) {
- basefile = filename;
- } else {
- ++basefile;
- assert(*basefile);
- }
-
- if (verbose == 1)
- printf("%s\n", basefile);
- else if (verbose)
- printf("%s @ offset byte %i\n", basefile, *data_len);
-
- /* write out the (pathname_len) */
- in_len = strlen(basefile);
- p = tbz2_encode_int(in_len);
- fwrite(p, 1, 4, findex);
- /* write out the pathname */
- fwrite(basefile, 1, in_len, findex);
- /* write out the (data_offset) */
- p = tbz2_encode_int(*data_len);
- fwrite(p, 1, 4, findex);
-
- *index_len += 4 + in_len + 4 + 4;
-
- /* now open the file, get (data_len), and append the file to the data file */
- fd = openat(dir_fd, filename, O_RDONLY|O_CLOEXEC);
- if (fd < 0) {
- open_fail:
- warnp("could not open for reading: %s", filename);
- fake_data_len:
- p = tbz2_encode_int(0);
- fwrite(p, 1, 4, findex);
- return;
- }
- fin = fdopen(fd, "r");
- if (!fin) {
- close(fd);
- goto open_fail;
- }
- in_len = st->st_size;
- /* the xpak format can only store files whose size is a 32bit int
- * so we have to make sure we don't store a big file */
- if (in_len != st->st_size) {
- warnf("File is too big: %"PRIu64, (uint64_t)st->st_size);
- fclose(fin);
- goto fake_data_len;
- }
- p = tbz2_encode_int(in_len);
- fwrite(p, 1, 4, findex);
- _tbz2_copy_file(fin, fdata);
- fclose(fin);
-
- *data_len += in_len;
-}
-static int
-xpak_create(int dir_fd, const char *file, int argc, char **argv)
-{
- FILE *findex, *fdata, *fout;
- struct dirent **dir;
- int i, fidx, numfiles;
- struct stat st;
- char path[_Q_PATH_MAX];
- unsigned char *p;
- int index_len, data_len;
-
- if (argc == 0)
- err("Create usage: <xpak output> <files/dirs to pack>");
-
- if (strlen(file) >= sizeof(path)-6)
- err("Pathname is too long: %s", file);
-
- if ((fout = fopen(file, "w")) == NULL) {
- warnp("could not open output: %s", file);
- return 1;
- }
- strcpy(path, file); strcat(path, ".index");
- if ((findex = fopen(path, "w+")) == NULL) {
- warnp("could not open output: %s", path);
- fclose(fout);
- return 1;
- }
- strcpy(path, file); strcat(path, ".dat");
- if ((fdata = fopen(path, "w+")) == NULL) {
- warnp("could not open output: %s", path);
- fclose(fout);
- fclose(findex);
- return 1;
- }
-
- index_len = data_len = 0;
- for (i = 0; i < argc; ++i) {
- if (fstatat(dir_fd, argv[i], &st, 0)) {
- warnp("fstatat(%s) failed", argv[i]);
- continue;
- }
- if (S_ISDIR(st.st_mode)) {
- if ((numfiles = scandir(argv[i], &dir, filter_hidden, alphasort)) < 0)
- warn("Directory '%s' is empty; skipping", argv[i]);
- for (fidx = 0; fidx < numfiles; ++fidx) {
- int ret = snprintf(path, sizeof(path), "%s/%s",
- argv[i], dir[fidx]->d_name);
- if (ret < 0 || (size_t)ret >= sizeof(path)) {
- warn("skipping path too long: %s/%s",
- argv[i], dir[fidx]->d_name);
- continue;
- }
- if (stat(path, &st) < 0) {
- warnp("could not read %s", path);
- continue;
- }
- _xpak_add_file(dir_fd, path, &st, findex, &index_len, fdata, &data_len);
- }
- scandir_free(dir, numfiles);
- } else if (S_ISREG(st.st_mode)) {
- _xpak_add_file(dir_fd, argv[i], &st, findex, &index_len, fdata, &data_len);
- } else
- warn("Skipping non file/directory '%s'", argv[i]);
- }
-
- rewind(findex);
- rewind(fdata);
-
- /* "XPAKPACK" + (index_len) + (data_len) + index + data + "XPAKSTOP" */
- fwrite(XPAK_START_MSG, 1, XPAK_START_MSG_LEN, fout); /* "XPAKPACK" */
- p = tbz2_encode_int(index_len);
- fwrite(p, 1, 4, fout); /* (index_len) */
- p = tbz2_encode_int(data_len);
- fwrite(p, 1, 4, fout); /* (data_len) */
- _tbz2_copy_file(findex, fout); /* index */
- _tbz2_copy_file(fdata, fout); /* data */
- fwrite(XPAK_END_MSG, 1, XPAK_END_MSG_LEN, fout); /* "XPAKSTOP" */
-
- strcpy(path, file); strcat(path, ".index"); unlink(path);
- strcpy(path, file); strcat(path, ".dat"); unlink(path);
- fclose(findex);
- fclose(fdata);
- fclose(fout);
-
- return 0;
-}
int qxpak_main(int argc, char **argv)
{
@@ -417,10 +132,17 @@ int qxpak_main(int argc, char **argv)
argv += optind;
switch (action) {
- case XPAK_ACT_LIST: ret = xpak_list(dir_fd, xpak, argc, argv); break;
- case XPAK_ACT_EXTRACT: ret = xpak_extract(dir_fd, xpak, argc, argv); break;
- case XPAK_ACT_CREATE: ret = xpak_create(dir_fd, xpak, argc, argv); break;
- default: ret = EXIT_FAILURE;
+ case XPAK_ACT_LIST:
+ ret = xpak_list(dir_fd, xpak, argc, argv, &_xpak_list_callback);
+ break;
+ case XPAK_ACT_EXTRACT:
+ ret = xpak_extract(dir_fd, xpak, argc, argv, &_xpak_extract_callback);
+ break;
+ case XPAK_ACT_CREATE:
+ ret = xpak_create(dir_fd, xpak, argc, argv, 0, verbose);
+ break;
+ default:
+ ret = EXIT_FAILURE;
}
if (dir_fd != AT_FDCWD)
@@ -428,7 +150,3 @@ int qxpak_main(int argc, char **argv)
return ret;
}
-
-#else
-DEFINE_APPLET_STUB(qxpak)
-#endif