diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/driver/tpax_driver_ctx.c | 219 | ||||
-rw-r--r-- | src/internal/tpax_driver_impl.h | 4 | ||||
-rw-r--r-- | src/skin/tpax_skin_default.c | 13 |
3 files changed, 226 insertions, 10 deletions
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} }; |