summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/tpax/tpax.h6
-rw-r--r--src/driver/tpax_driver_ctx.c219
-rw-r--r--src/internal/tpax_driver_impl.h4
-rw-r--r--src/skin/tpax_skin_default.c13
4 files changed, 232 insertions, 10 deletions
diff --git a/include/tpax/tpax.h b/include/tpax/tpax.h
index e89076d..c649058 100644
--- a/include/tpax/tpax.h
+++ b/include/tpax/tpax.h
@@ -22,6 +22,7 @@ extern "C" {
#define TPAX_OK 0x00
#define TPAX_USAGE 0x01
#define TPAX_ERROR 0x02
+#define TPAX_FATAL 0x03
/* driver flags */
#define TPAX_DRIVER_VERBOSITY_NONE 0x0000
@@ -33,6 +34,11 @@ extern "C" {
#define TPAX_DRIVER_VERSION 0x0010
#define TPAX_DRIVER_DRY_RUN 0x0020
+#define TPAX_DRIVER_EXEC_MODE_LIST 0x0100
+#define TPAX_DRIVER_EXEC_MODE_READ 0x0200
+#define TPAX_DRIVER_EXEC_MODE_WRITE 0x0400
+#define TPAX_DRIVER_EXEC_MODE_COPY 0x0800
+
#define TPAX_DRIVER_ANNOTATE_ALWAYS 0x1000
#define TPAX_DRIVER_ANNOTATE_NEVER 0x2000
#define TPAX_DRIVER_ANNOTATE_FULL 0x4000
diff --git a/src/driver/tpax_driver_ctx.c b/src/driver/tpax_driver_ctx.c
index 96fe8ff..b43d129 100644
--- a/src/driver/tpax_driver_ctx.c
+++ b/src/driver/tpax_driver_ctx.c
@@ -5,8 +5,10 @@
/******************************************************/
#include <stdint.h>
+#include <string.h>
#include <unistd.h>
#include <fcntl.h>
+#include <errno.h>
#define ARGV_DRIVER
@@ -15,6 +17,12 @@
#include "tpax_driver_impl.h"
#include "argv/argv.h"
+#define TPAX_DRIVER_EXEC_MODE_MASK \
+ (TPAX_DRIVER_EXEC_MODE_LIST \
+ | TPAX_DRIVER_EXEC_MODE_READ \
+ | TPAX_DRIVER_EXEC_MODE_WRITE \
+ | TPAX_DRIVER_EXEC_MODE_COPY)
+
/* package info */
static const struct tpax_source_version tpax_src_version = {
TPAX_TAG_VER_MAJOR,
@@ -66,8 +74,14 @@ static int tpax_driver_usage(
char header[512];
snprintf(header,sizeof(header),
- "Usage: %s [options] <file>...\n" "Options:\n",
- program);
+ "%s — topological pax implementation\n\n"
+ "Synopsis:\n"
+ " %s\n"
+ " %s -r\n"
+ " %s -w\n"
+ " %s -r -w\n\n"
+ "Options:\n",
+ program,program,program,program,program);
argv_usage(fdout,header,optv,arg);
argv_free(meta);
@@ -75,6 +89,100 @@ static int tpax_driver_usage(
return TPAX_USAGE;
}
+static int tpax_driver_usage_exec_mode(
+ int fdout,
+ const char * program,
+ const char * arg,
+ const struct argv_option ** optv,
+ struct argv_meta * meta)
+{
+ tpax_driver_usage(
+ fdout,program,
+ arg,optv,meta);
+
+ tpax_dprintf(
+ fdout,
+ "\nWhen using explicit (long) mode options, "
+ "only one of --list, --read, --write, --copy "
+ "may be used.\n");
+
+ return TPAX_USAGE;
+}
+
+static int tpax_driver_usage_copy_mode(
+ int fdout,
+ const char * program,
+ const char * arg,
+ const struct argv_option ** optv,
+ struct argv_meta * meta,
+ struct argv_entry * operand)
+{
+ const char * errdesc;
+
+ if (!operand) {
+ tpax_driver_usage(
+ fdout,program,
+ arg,optv,meta);
+
+ tpax_dprintf(
+ fdout,
+ "\nThe copy mode requires a destination "
+ "directory argument.\n\n");
+
+ return TPAX_USAGE;
+ }
+
+ switch (errno) {
+ case ENOENT:
+ tpax_dprintf(
+ fdout,
+ "%s: error: "
+ "the destination directory '%s' "
+ "does not exist.\n\n",
+ program,operand->arg);
+ break;
+
+ case ENOTDIR:
+ tpax_dprintf(
+ fdout,
+ "%s: error: "
+ "'%s' is not a directory.\n\n",
+ program,operand->arg);
+ break;
+
+ default:
+ if (!(errdesc = strerror(errno)))
+ errdesc = "<no error description>";
+
+ tpax_dprintf(
+ fdout,
+ "%s: error: while opening the "
+ "destination directory '%s': %s.\n\n",
+ program,operand->arg,errdesc);
+ break;
+ }
+
+ argv_free(meta);
+
+ return TPAX_USAGE;
+}
+
+static int tpax_driver_error_not_implemented(
+ int fdout,
+ const char * program,
+ const char * feature,
+ struct argv_meta * meta)
+
+{
+ tpax_dprintf(
+ fdout,"%s: error: %s is not yet implemented!\n\n",
+ program,feature);
+
+ argv_free(meta);
+
+ return TPAX_FATAL;
+}
+
static struct tpax_driver_ctx_impl * tpax_driver_ctx_alloc(
struct argv_meta * meta,
const struct tpax_fd_ctx * fdctx,
@@ -130,8 +238,10 @@ int tpax_get_driver_ctx(
const struct argv_option * optv[TPAX_OPTV_ELEMENTS];
struct argv_meta * meta;
struct argv_entry * entry;
+ struct argv_entry * operand;
size_t nunits;
const char * program;
+ int fddst;
(void)envp;
@@ -147,15 +257,12 @@ int tpax_get_driver_ctx(
return -1;
nunits = 0;
+ operand = 0;
program = argv_program_name(argv[0]);
memset(&cctx,0,sizeof(cctx));
- cctx.drvflags = flags;
- if (!argv[1] && (flags & TPAX_DRIVER_VERBOSITY_USAGE))
- return tpax_driver_usage(
- fdctx->fderr,
- program,
- 0,optv,meta);
+ cctx.drvflags = flags;
+ fddst = fdctx->fddst;
/* get options, count units */
for (entry=meta->entries; entry->fopt || entry->arg; entry++) {
@@ -172,13 +279,105 @@ int tpax_get_driver_ctx(
case TAG_VERSION:
cctx.drvflags |= TPAX_DRIVER_VERSION;
break;
+
+ case TAG_LIST:
+ cctx.drvflags |= TPAX_DRIVER_EXEC_MODE_LIST;
+ break;
+
+ case TAG_READ:
+ cctx.drvflags |= TPAX_DRIVER_EXEC_MODE_READ;
+ break;
+
+ case TAG_WRITE:
+ cctx.drvflags |= TPAX_DRIVER_EXEC_MODE_WRITE;
+ break;
+
+ case TAG_COPY:
+ cctx.drvflags |= TPAX_DRIVER_EXEC_MODE_COPY;
+ break;
}
- } else
+ } else {
+ operand = entry;
nunits++;
+ }
+ }
+
+ /* incompatible arguments? */
+ switch (cctx.drvflags & TPAX_DRIVER_EXEC_MODE_MASK) {
+ case 0:
+ if (!(cctx.drvflags & TPAX_DRIVER_VERSION))
+ cctx.drvflags |= TPAX_DRIVER_EXEC_MODE_LIST;
+ break;
+
+ case TPAX_DRIVER_EXEC_MODE_READ|TPAX_DRIVER_EXEC_MODE_WRITE:
+ cctx.drvflags &= ~(uint64_t)(TPAX_DRIVER_EXEC_MODE_READ);
+ cctx.drvflags &= ~(uint64_t)(TPAX_DRIVER_EXEC_MODE_WRITE);
+ cctx.drvflags |= TPAX_DRIVER_EXEC_MODE_COPY;
+ break;
+
+ case TPAX_DRIVER_EXEC_MODE_LIST:
+ case TPAX_DRIVER_EXEC_MODE_READ:
+ case TPAX_DRIVER_EXEC_MODE_WRITE:
+ case TPAX_DRIVER_EXEC_MODE_COPY:
+ break;
+
+ default:
+ return tpax_driver_usage_exec_mode(
+ fdctx->fderr,
+ program,entry->arg,
+ optv,meta);
}
- if (!(ctx = tpax_driver_ctx_alloc(meta,fdctx,&cctx,nunits)))
+ /* copy mode: destination directory */
+ if (cctx.drvflags & TPAX_DRIVER_EXEC_MODE_COPY) {
+ if (!operand)
+ return tpax_driver_usage_copy_mode(
+ fdctx->fderr,
+ program,entry->arg,
+ optv,meta,operand);
+
+ fddst = openat(
+ fdctx->fdcwd,
+ operand->arg,
+ O_RDONLY|O_DIRECTORY|O_CLOEXEC,0);
+
+ if (fddst < 0)
+ return tpax_driver_usage_copy_mode(
+ fdctx->fderr,
+ program,entry->arg,
+ optv,meta,operand);
+ }
+
+ /* not implemented mode(s) */
+ switch (cctx.drvflags & TPAX_DRIVER_EXEC_MODE_MASK) {
+ case TPAX_DRIVER_EXEC_MODE_LIST:
+ return tpax_driver_error_not_implemented(
+ fdctx->fderr,program,"list mode",meta);
+
+ case TPAX_DRIVER_EXEC_MODE_READ:
+ return tpax_driver_error_not_implemented(
+ fdctx->fderr,program,"read mode",meta);
+
+ case TPAX_DRIVER_EXEC_MODE_WRITE:
+ return tpax_driver_error_not_implemented(
+ fdctx->fderr,program,"write mode",meta);
+
+ case TPAX_DRIVER_EXEC_MODE_COPY:
+ close(fddst);
+
+ return tpax_driver_error_not_implemented(
+ fdctx->fderr,program,"copy mode",meta);
+
+ default:
+ break;
+ }
+
+ if (!(ctx = tpax_driver_ctx_alloc(meta,fdctx,&cctx,nunits))) {
+ if (cctx.drvflags & TPAX_DRIVER_EXEC_MODE_COPY)
+ close(fddst);
+
return tpax_get_driver_ctx_fail(meta);
+ }
ctx->ctx.program = program;
ctx->ctx.cctx = &ctx->cctx;
diff --git a/src/internal/tpax_driver_impl.h b/src/internal/tpax_driver_impl.h
index 49dea15..6d749b5 100644
--- a/src/internal/tpax_driver_impl.h
+++ b/src/internal/tpax_driver_impl.h
@@ -22,6 +22,10 @@ extern const struct argv_option tpax_default_options[];
enum app_tags {
TAG_HELP,
TAG_VERSION,
+ TAG_LIST,
+ TAG_READ,
+ TAG_WRITE,
+ TAG_COPY,
};
struct tpax_driver_ctx_impl {
diff --git a/src/skin/tpax_skin_default.c b/src/skin/tpax_skin_default.c
index c969ff3..eb7e363 100644
--- a/src/skin/tpax_skin_default.c
+++ b/src/skin/tpax_skin_default.c
@@ -8,5 +8,18 @@ const struct argv_option tpax_default_options[] = {
{"help", 0,TAG_HELP,ARGV_OPTARG_OPTIONAL,0,"short|long",0,
"show usage information [listing %s options only]"},
+ {"list", 0,TAG_LIST,ARGV_OPTARG_NONE,0,0,0,
+ "list mode (output names of archive members"},
+
+ {"read", 'r',TAG_READ,ARGV_OPTARG_NONE,0,0,0,
+ "read mode (extract matching archive members"},
+
+ {"write", 'w',TAG_WRITE,ARGV_OPTARG_NONE,0,0,0,
+ "write mode (add specified files to archive"},
+
+ {"copy", 0,TAG_COPY,ARGV_OPTARG_NONE,0,0,0,
+ "copy mode (copy specified files "
+ "to a specified destination directory)"},
+
{0,0,0,0,0,0,0,0}
};