diff options
Diffstat (limited to 'src/logic')
-rw-r--r-- | src/logic/tpax_archive_enqueue.c | 49 |
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; |