summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/driver/tpax_driver_ctx.c5
-rw-r--r--src/internal/tpax_driver_impl.h1
-rw-r--r--src/logic/tpax_archive_enqueue.c49
-rw-r--r--src/skin/tpax_skin_default.c9
4 files changed, 64 insertions, 0 deletions
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 <tpax/tpax_specs.h>
#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,