summaryrefslogtreecommitdiffhomepage
path: root/src/logic
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2024-06-06 21:52:55 +0000
committermidipix <writeonce@midipix.org>2024-06-07 00:58:32 +0000
commite50240012b56272abfd1ce2c873dc99e7a89631b (patch)
treeaac34605a155ae24142049ec020d460e6f152ddf /src/logic
parent8034d053d2a29f7721066ff1190aa6814a300d40 (diff)
downloadtpax-e50240012b56272abfd1ce2c873dc99e7a89631b.tar.bz2
tpax-e50240012b56272abfd1ce2c873dc99e7a89631b.tar.xz
driver: implemented and integrated the -L (follow symlink items) cmdline option.
Diffstat (limited to 'src/logic')
-rw-r--r--src/logic/tpax_archive_enqueue.c49
1 files changed, 49 insertions, 0 deletions
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;