From e50240012b56272abfd1ce2c873dc99e7a89631b Mon Sep 17 00:00:00 2001 From: midipix Date: Thu, 6 Jun 2024 21:52:55 +0000 Subject: driver: implemented and integrated the -L (follow symlink items) cmdline option. --- include/tpax/tpax.h | 1 + src/driver/tpax_driver_ctx.c | 5 ++++ src/internal/tpax_driver_impl.h | 1 + src/logic/tpax_archive_enqueue.c | 49 ++++++++++++++++++++++++++++++++++++++++ src/skin/tpax_skin_default.c | 9 ++++++++ 5 files changed, 65 insertions(+) diff --git a/include/tpax/tpax.h b/include/tpax/tpax.h index ec44b41..d5de59a 100644 --- a/include/tpax/tpax.h +++ b/include/tpax/tpax.h @@ -57,6 +57,7 @@ extern "C" { #define TPAX_DRIVER_PRESERVE_ATIME 0x1000000 #define TPAX_DRIVER_PRESERVE_MTIME 0x2000000 #define TPAX_DRIVER_PAX_SYMLINK_ARGS 0x4000000 +#define TPAX_DRIVER_PAX_SYMLINK_ITEMS 0x8000000 /* error flags */ #define TPAX_ERROR_TOP_LEVEL 0x0001 diff --git a/src/driver/tpax_driver_ctx.c b/src/driver/tpax_driver_ctx.c index 71b4656..97eb776 100644 --- a/src/driver/tpax_driver_ctx.c +++ b/src/driver/tpax_driver_ctx.c @@ -534,6 +534,11 @@ int tpax_lib_get_driver_ctx( cctx.drvflags |= TPAX_DRIVER_PAX_SYMLINK_ARGS; break; + case TAG_PAX_SYMLINK_ITEMS: + cctx.drvflags |= TPAX_DRIVER_PAX_SYMLINK_ARGS; + cctx.drvflags |= TPAX_DRIVER_PAX_SYMLINK_ITEMS; + break; + case TAG_STRICT_PATH: cctx.drvflags |= TPAX_DRIVER_STRICT_PATH_INPUT; break; diff --git a/src/internal/tpax_driver_impl.h b/src/internal/tpax_driver_impl.h index a074535..aa65eed 100644 --- a/src/internal/tpax_driver_impl.h +++ b/src/internal/tpax_driver_impl.h @@ -49,6 +49,7 @@ enum app_tags { TAG_PURE_PATH, TAG_PRESERVE_ATIME, TAG_PAX_SYMLINK_ARGS, + TAG_PAX_SYMLINK_ITEMS, }; struct tpax_dirent { diff --git a/src/logic/tpax_archive_enqueue.c b/src/logic/tpax_archive_enqueue.c index ab07ab5..1b45a2f 100644 --- a/src/logic/tpax_archive_enqueue.c +++ b/src/logic/tpax_archive_enqueue.c @@ -19,6 +19,7 @@ #include #include "tpax_driver_impl.h" #include "tpax_getdents_impl.h" +#include "tpax_readlink_impl.h" #include "tpax_tmpfile_impl.h" #include "tpax_errinfo_impl.h" @@ -267,14 +268,21 @@ static int tpax_archive_enqueue_dir_entries( { int fd; int fdat; + int fdlnk; int depth; bool fkeep; + bool flinks; long nbytes; + struct dirent * lnkent; struct dirent * dirent; struct dirent * dirents; + struct tpax_dirent * cdent; struct tpax_unit_ctx * uctx; struct stat st; + struct stat lnkst; uintptr_t addr; + char lnktgt[PATH_MAX]; + char lnkbuf[PATH_MAX + sizeof(struct dirent)]; /* init */ fdat = dent->fdat; @@ -306,6 +314,8 @@ static int tpax_archive_enqueue_dir_entries( TPAX_SYSTEM_ERROR(dctx), uctx); + lnkent = (struct dirent *)lnkbuf; + flinks = (dctx->cctx->drvflags & TPAX_DRIVER_PAX_SYMLINK_ITEMS); nbytes = tpax_getdents(fd,dirents,TPAX_DIRENT_BUFLEN); while ((nbytes == -EINTR) || ((nbytes < 0) && (errno == EINTR))) @@ -344,6 +354,45 @@ static int tpax_archive_enqueue_dir_entries( return tpax_archive_enqueue_ret( TPAX_NESTED_ERROR(dctx), uctx); + + /* follow encountered symlink arguments as needed */ + fdlnk = (flinks && (dirent->d_type == DT_LNK)) + ? openat(fd,dirent->d_name,O_RDONLY|O_CLOEXEC) + : (-1); + + if (fdlnk >= 0) { + if (fstat(fdlnk,&lnkst) <0) { + close(fdlnk); + return tpax_archive_enqueue_ret( + TPAX_SYSTEM_ERROR(dctx), + uctx); + } + + if (tpax_readlinkat(fd,dirent->d_name,lnktgt,PATH_MAX) < 0) + return tpax_archive_enqueue_ret( + TPAX_SYSTEM_ERROR(dctx), + uctx); + + close(fdlnk); + + if (tpax_dirent_init_from_uctx(&lnkst,lnktgt,lnkent) < 0) + return tpax_archive_enqueue_ret( + TPAX_CUSTOM_ERROR( + dctx, + TPAX_ERR_FLOW_ERROR), + 0); + + cdent = tpax_get_driver_dirmark(dctx); + cdent->flags |= TPAX_ITEM_NAMEREF; + + if (tpax_archive_add_queue_item( + dctx,lnkent,cdent,0,depth+1, + TPAX_ITEM_IMPLICIT|TPAX_ITEM_SYMLINK, + fd,&fkeep) < 0) + return tpax_archive_enqueue_ret( + TPAX_NESTED_ERROR(dctx), + 0); + } } addr = (uintptr_t)dirent; diff --git a/src/skin/tpax_skin_default.c b/src/skin/tpax_skin_default.c index 5bddb70..bfb4551 100644 --- a/src/skin/tpax_skin_default.c +++ b/src/skin/tpax_skin_default.c @@ -74,6 +74,15 @@ const tpax_hidden struct argv_option tpax_default_options[] = { "or directory to the archive using the name of the " "symbolic link."}, + {"Wpax-symlink-items", + 'L',TAG_PAX_SYMLINK_ITEMS,ARGV_OPTARG_NONE, + ARGV_OPTION_HYBRID_ONLY,0,0, + "when a command-line argument is a symbolic link, or when " + "an item added by way of recursion is a symbolic link, " + "add the underlying (referenced) file-system object " + "or directory to the archive using the name of the " + "symbolic link."}, + {"Wstrict-path-input", 0,TAG_STRICT_PATH,ARGV_OPTARG_NONE, ARGV_OPTION_HYBRID_ONLY,0,0, -- cgit v1.2.3