2019-01-30 13:48:58 +01:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <fcntl.h>
|
2019-01-19 17:26:41 +01:00
|
|
|
|
2019-01-30 13:48:58 +01:00
|
|
|
#include "pkgreader.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "pkgio.h"
|
|
|
|
#include "util.h"
|
2019-01-19 17:26:41 +01:00
|
|
|
|
|
|
|
static const struct option long_opts[] = {
|
|
|
|
{ "root", required_argument, NULL, 'r' },
|
2019-02-03 12:21:16 +01:00
|
|
|
{ "no-chown", no_argument, NULL, 'o' },
|
|
|
|
{ "no-chmod", no_argument, NULL, 'm' },
|
2019-01-19 17:26:41 +01:00
|
|
|
{ NULL, 0, NULL, 0 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *short_opts = "r:om";
|
|
|
|
|
|
|
|
static int cmd_unpack(int argc, char **argv)
|
|
|
|
{
|
|
|
|
const char *root = NULL, *filename;
|
2019-01-30 12:59:20 +01:00
|
|
|
int i, rootfd, flags = 0;
|
2019-01-19 17:26:41 +01:00
|
|
|
pkg_reader_t *rd;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
i = getopt_long(argc, argv, short_opts, long_opts, NULL);
|
|
|
|
if (i == -1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (i) {
|
|
|
|
case 'r':
|
|
|
|
root = optarg;
|
|
|
|
break;
|
|
|
|
case 'o':
|
2019-01-30 13:08:14 +01:00
|
|
|
flags |= UNPACK_NO_CHOWN;
|
2019-01-19 17:26:41 +01:00
|
|
|
break;
|
|
|
|
case 'm':
|
2019-01-30 13:08:14 +01:00
|
|
|
flags |= UNPACK_NO_CHMOD;
|
2019-01-19 17:26:41 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
tell_read_help(argv[0]);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (optind >= argc) {
|
|
|
|
fputs("missing argument: package file\n", stderr);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
filename = argv[optind++];
|
|
|
|
|
|
|
|
if (optind < argc)
|
|
|
|
fputs("warning: ignoring extra arguments\n", stderr);
|
|
|
|
|
2019-01-30 11:27:32 +01:00
|
|
|
if (root == NULL) {
|
|
|
|
rootfd = AT_FDCWD;
|
|
|
|
} else {
|
|
|
|
if (mkdir_p(root))
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
rootfd = open(root, O_RDONLY | O_DIRECTORY);
|
|
|
|
if (rootfd < 0) {
|
|
|
|
perror(root);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-19 17:26:41 +01:00
|
|
|
rd = pkg_reader_open(filename);
|
|
|
|
if (rd == NULL)
|
2019-01-30 11:27:32 +01:00
|
|
|
goto fail_rootfd;
|
2019-01-19 17:26:41 +01:00
|
|
|
|
2019-01-30 12:59:20 +01:00
|
|
|
if (pkg_unpack(rootfd, flags, rd))
|
2019-01-19 17:26:41 +01:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
pkg_reader_close(rd);
|
2019-01-30 11:27:32 +01:00
|
|
|
if (rootfd != AT_FDCWD)
|
|
|
|
close(rootfd);
|
2019-01-19 17:26:41 +01:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
fail:
|
|
|
|
pkg_reader_close(rd);
|
2019-01-30 11:27:32 +01:00
|
|
|
fail_rootfd:
|
|
|
|
if (rootfd != AT_FDCWD)
|
|
|
|
close(rootfd);
|
2019-01-19 17:26:41 +01:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static command_t unpack = {
|
|
|
|
.cmd = "unpack",
|
|
|
|
.usage = "[OPTIONS...] <pkgfile>",
|
|
|
|
.s_desc = "unpack the contents of a package file",
|
|
|
|
.l_desc =
|
|
|
|
"The unpack command extracts the file hierarchy stored in a package into\n"
|
|
|
|
"a destination directory (default: current working directory).\n"
|
|
|
|
"\n"
|
|
|
|
"Possible options:\n"
|
2019-02-02 20:28:37 +01:00
|
|
|
" --root, -r <directory> A root directory to unpack the package. Defaults\n"
|
2019-01-19 17:26:41 +01:00
|
|
|
" to the current working directory if not set.\n"
|
|
|
|
" --no-chown, -o Do not change ownership of the extracted data.\n"
|
|
|
|
" Keep the uid/gid of the user who runs the program.\n"
|
|
|
|
" --no-chmod, -m Do not change permission flags of the extarcted\n"
|
|
|
|
" data. Use 0644 for all files and 0755 for all\n"
|
|
|
|
" directories.\n",
|
|
|
|
.run_cmd = cmd_unpack,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGISTER_COMMAND(unpack)
|