From 156e23cd69630cba8dee55eaafae5d33e40c30bc Mon Sep 17 00:00:00 2001 From: midipix Date: Wed, 29 May 2024 03:10:40 +0000 Subject: driver: implemented the -f (archive path) command-line argument. --- include/tpax/tpax.h | 1 + src/driver/tpax_driver_ctx.c | 109 ++++++++++++++++++++++++++++++++++++---- src/internal/tpax_driver_impl.h | 2 + src/skin/tpax_skin_default.c | 6 +++ 4 files changed, 109 insertions(+), 9 deletions(-) diff --git a/include/tpax/tpax.h b/include/tpax/tpax.h index 8822ee1..172c7ae 100644 --- a/include/tpax/tpax.h +++ b/include/tpax/tpax.h @@ -117,6 +117,7 @@ struct tpax_driver_ctx { const char ** units; const char * program; const char * module; + const char * const * file; const struct tpax_common_ctx * cctx; struct tpax_error_info ** errv; const off_t * cpos; 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; diff --git a/src/internal/tpax_driver_impl.h b/src/internal/tpax_driver_impl.h index cd734b0..1333f25 100644 --- a/src/internal/tpax_driver_impl.h +++ b/src/internal/tpax_driver_impl.h @@ -38,6 +38,7 @@ enum app_tags { TAG_READ, TAG_WRITE, TAG_COPY, + TAG_FILE, TAG_FORMAT, TAG_BLKSIZE, TAG_RECURSE, @@ -65,6 +66,7 @@ struct tpax_dirent_buffer { }; struct tpax_driver_ctx_impl { + const char * file; struct tpax_common_ctx cctx; struct tpax_driver_ctx ctx; struct tpax_fd_ctx fdctx; diff --git a/src/skin/tpax_skin_default.c b/src/skin/tpax_skin_default.c index 1db63c8..a385aac 100644 --- a/src/skin/tpax_skin_default.c +++ b/src/skin/tpax_skin_default.c @@ -28,6 +28,12 @@ const tpax_hidden struct argv_option tpax_default_options[] = { "copy mode (copy specified files " "to a specified destination directory)"}, + {"Wfile", 'f',TAG_FILE,ARGV_OPTARG_REQUIRED, + ARGV_OPTION_HYBRID_ONLY|ARGV_OPTION_HYBRID_EQUAL, + 0,"", + "read from (in read or list modes), " + "or write to (in write mode) the specified %s " + "after (in write mode) creating it as necessary"}, {"Wformat", 'x',TAG_FORMAT,ARGV_OPTARG_REQUIRED, ARGV_OPTION_HYBRID_ONLY|ARGV_OPTION_HYBRID_EQUAL, -- cgit v1.2.3