diff options
Diffstat (limited to 'src/driver')
-rw-r--r-- | src/driver/tpax_driver_ctx.c | 109 |
1 files changed, 100 insertions, 9 deletions
diff --git a/src/driver/tpax_driver_ctx.c b/src/driver/tpax_driver_ctx.c index 6497126..7cae777 100644 --- a/src/driver/tpax_driver_ctx.c +++ b/src/driver/tpax_driver_ctx.c @@ -125,19 +125,27 @@ static int tpax_driver_usage_copy_mode( const char * arg, const struct argv_option ** optv, struct argv_meta * meta, - struct argv_entry * operand) + struct argv_entry * operand, + struct argv_entry * archive) { const char * errdesc; - if (!operand) { + if (archive || !operand) { tpax_driver_usage( fdout,program, arg,optv,meta); - tpax_dprintf( - fdout, - "\nThe copy mode requires a destination " - "directory argument.\n\n"); + if (archive) { + tpax_dprintf( + fdout, + "\n%s: the __copy__ mode does not permit specifying " + "an archive path.\n\n",program); + } else { + tpax_dprintf( + fdout, + "\n%s: the __copy__ mode requires a destination " + "directory argument.\n\n",program); + } return TPAX_USAGE; } @@ -234,6 +242,42 @@ static int tpax_driver_usage_block_size_range( return TPAX_USAGE; } +static int tpax_driver_error_archive_path( + int fdout, + const char * program, + const char * arg, + struct argv_meta * meta, + bool fwrite) +{ + int lerrno; + const char * errstr; + + lerrno = errno; + errno = 0; + + errstr = strerror(lerrno); + errstr = errno ? "" : errstr; + errno = lerrno; + + if (fwrite) { + tpax_dprintf( + fdout, + "%s: archive file <%s> could not be created " + "or opened for writing (%s).\n", + program,arg,errstr); + } else { + tpax_dprintf( + fdout, + "%s: archive file <%s> could not be opened " + "for reading (%s).\n", + program,arg,errstr); + } + + argv_free(meta); + + return TPAX_FATAL; +} + static int tpax_driver_error_not_implemented( int fdout, const char * program, @@ -337,7 +381,9 @@ int tpax_lib_get_driver_ctx( const struct argv_option * optv[TPAX_OPTV_ELEMENTS]; struct argv_meta * meta; struct argv_entry * entry; + struct argv_entry * archive; struct argv_entry * operand; + struct tpax_fd_ctx lfdctx; size_t nunits; const char * program; int fddst; @@ -357,6 +403,7 @@ int tpax_lib_get_driver_ctx( return -1; nunits = 0; + archive = 0; operand = 0; program = argv_program_name(argv[0]); memset(&cctx,0,sizeof(cctx)); @@ -396,6 +443,10 @@ int tpax_lib_get_driver_ctx( cctx.drvflags |= TPAX_DRIVER_EXEC_MODE_COPY; break; + case TAG_FILE: + archive = entry; + break; + case TAG_FORMAT: cctx.drvflags &= ~(uint64_t)(TPAX_DRIVER_WRITE_FORMAT_MASK); @@ -481,11 +532,11 @@ int tpax_lib_get_driver_ctx( /* copy mode: destination directory */ if (cctx.drvflags & TPAX_DRIVER_EXEC_MODE_COPY) { - if (!operand) + if (archive || !operand) return tpax_driver_usage_copy_mode( fdctx->fderr, program,entry->arg, - optv,meta,operand); + optv,meta,operand,archive); fddst = openat( fdctx->fdcwd, @@ -496,7 +547,42 @@ int tpax_lib_get_driver_ctx( return tpax_driver_usage_copy_mode( fdctx->fderr, program,entry->arg, - optv,meta,operand); + optv,meta,operand,archive); + } + + /* archive path */ + if (archive && (cctx.drvflags & TPAX_DRIVER_EXEC_MODE_WRITE)) { + memcpy(&lfdctx,fdctx,sizeof(*fdctx)); + + lfdctx.fdout = openat( + fdctx->fdcwd, + archive->arg, + O_WRONLY|O_CREAT|O_TRUNC, + 0644); + + if (lfdctx.fdout < 0) + return tpax_driver_error_archive_path( + fdctx->fderr, + program,archive->arg, + meta,true); + + fdctx = &lfdctx; + + } else if (archive) { + memcpy(&lfdctx,fdctx,sizeof(*fdctx)); + + lfdctx.fdin = openat( + fdctx->fdcwd, + archive->arg, + O_RDONLY,0); + + if (lfdctx.fdin < 0) + return tpax_driver_error_archive_path( + fdctx->fderr, + program,archive->arg, + meta,false); + + fdctx = &lfdctx; } /* not implemented mode(s) */ @@ -555,6 +641,11 @@ int tpax_lib_get_driver_ctx( return tpax_get_driver_ctx_fail(meta); } + if (archive) { + ctx->file = archive->arg; + ctx->ctx.file = &ctx->file; + } + ctx->ctx.program = program; ctx->ctx.cctx = &ctx->cctx; |