From ee80f814e924d7e84e02b290f5f8796d6c4b05be Mon Sep 17 00:00:00 2001 From: midipix Date: May 30 2024 22:45:00 +0000 Subject: driver: implemented and integrated the -t (preserve atime) command-line option. --- diff --git a/include/tpax/tpax.h b/include/tpax/tpax.h index eb106d6..2938d92 100644 --- a/include/tpax/tpax.h +++ b/include/tpax/tpax.h @@ -54,6 +54,9 @@ extern "C" { #define TPAX_DRIVER_STRICT_PATH_INPUT 0x200000 #define TPAX_DRIVER_PURE_PATH_OUTPUT 0x400000 +#define TPAX_DRIVER_PRESERVE_ATIME 0x1000000 +#define TPAX_DRIVER_PRESERVE_MTIME 0x2000000 + /* error flags */ #define TPAX_ERROR_TOP_LEVEL 0x0001 #define TPAX_ERROR_NESTED 0x0002 diff --git a/project/common.mk b/project/common.mk index c934519..26e171c 100644 --- a/project/common.mk +++ b/project/common.mk @@ -17,6 +17,7 @@ API_SRCS = \ INTERNAL_SRCS = \ src/internal/$(PACKAGE)_dprintf_impl.c \ src/internal/$(PACKAGE)_errinfo_impl.c \ + src/internal/$(PACKAGE)_ftime_impl.c \ src/internal/$(PACKAGE)_tmpfile_impl.c \ APP_SRCS = \ diff --git a/project/headers.mk b/project/headers.mk index e495f1b..a5ee670 100644 --- a/project/headers.mk +++ b/project/headers.mk @@ -8,6 +8,7 @@ INTERNAL_HEADERS = \ $(SOURCE_DIR)/src/internal/tpax_dprintf_impl.h \ $(SOURCE_DIR)/src/internal/tpax_driver_impl.h \ $(SOURCE_DIR)/src/internal/tpax_errinfo_impl.h \ + $(SOURCE_DIR)/src/internal/tpax_ftime_impl.h \ $(SOURCE_DIR)/src/internal/tpax_getdents_impl.h \ $(SOURCE_DIR)/src/internal/tpax_readlink_impl.h \ $(SOURCE_DIR)/src/internal/tpax_tmpfile_impl.h \ diff --git a/src/driver/tpax_driver_ctx.c b/src/driver/tpax_driver_ctx.c index 0807379..e8ecb9e 100644 --- a/src/driver/tpax_driver_ctx.c +++ b/src/driver/tpax_driver_ctx.c @@ -526,6 +526,10 @@ int tpax_lib_get_driver_ctx( cctx.drvflags &= ~(uintptr_t)TPAX_DRIVER_DIR_MEMBER_RECURSE; break; + case TAG_PRESERVE_ATIME: + cctx.drvflags |= TPAX_DRIVER_PRESERVE_ATIME; + 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 1345c32..1e898e9 100644 --- a/src/internal/tpax_driver_impl.h +++ b/src/internal/tpax_driver_impl.h @@ -45,6 +45,7 @@ enum app_tags { TAG_NORECURSE, TAG_STRICT_PATH, TAG_PURE_PATH, + TAG_PRESERVE_ATIME, }; struct tpax_dirent { diff --git a/src/internal/tpax_ftime_impl.c b/src/internal/tpax_ftime_impl.c new file mode 100644 index 0000000..19c6d7b --- /dev/null +++ b/src/internal/tpax_ftime_impl.c @@ -0,0 +1,48 @@ +/**************************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/**************************************************************/ + +#include +#include +#include + +#include "tpax_ftime_impl.h" +#include "tpax_driver_impl.h" +#include "tpax_visibility_impl.h" + +tpax_hidden void tpax_ftime_restore( + const struct tpax_driver_ctx * dctx, + int fd, + const struct stat * refst) +{ + struct timespec ts[2]; + + if (dctx->cctx->drvflags & TPAX_DRIVER_PRESERVE_ATIME) { + ts[0].tv_sec = refst->st_atim.tv_sec; + ts[0].tv_nsec = refst->st_atim.tv_nsec; + } else { + ts[0].tv_nsec = UTIME_OMIT; + } + + if (dctx->cctx->drvflags & TPAX_DRIVER_PRESERVE_MTIME) { + ts[1].tv_sec = refst->st_mtim.tv_sec; + ts[1].tv_nsec = refst->st_mtim.tv_nsec; + } else { + ts[1].tv_nsec = UTIME_OMIT; + } + + if ((ts[0].tv_nsec != UTIME_OMIT) || (ts[1].tv_nsec != UTIME_OMIT)) { + futimens(fd,ts); + } +} + +tpax_hidden void tpax_ftime_restore_and_close( + const struct tpax_driver_ctx * dctx, + int fd, + const struct stat * refst) +{ + tpax_ftime_restore(dctx,fd,refst); + close(fd); +} diff --git a/src/internal/tpax_ftime_impl.h b/src/internal/tpax_ftime_impl.h new file mode 100644 index 0000000..2d0e981 --- /dev/null +++ b/src/internal/tpax_ftime_impl.h @@ -0,0 +1,24 @@ +/**************************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/**************************************************************/ + +#ifndef TPAX_FTIME_IMPL_H +#define TPAX_FTIME_IMPL_H + +#include +#include +#include + +#include "tpax_driver_impl.h" + +void tpax_ftime_restore( + const struct tpax_driver_ctx *, + int fd, const struct stat *); + +void tpax_ftime_restore_and_close( + const struct tpax_driver_ctx *, + int fd, const struct stat *); + +#endif diff --git a/src/io/tpax_create_memory_snapshot.c b/src/io/tpax_create_memory_snapshot.c index 7c3dd7e..6be087f 100644 --- a/src/io/tpax_create_memory_snapshot.c +++ b/src/io/tpax_create_memory_snapshot.c @@ -18,6 +18,7 @@ #include #include "tpax_driver_impl.h" #include "tpax_errinfo_impl.h" +#include "tpax_ftime_impl.h" #ifndef ssizeof #define ssizeof(x) (ssize_t)(sizeof(x)) @@ -69,11 +70,11 @@ int tpax_io_create_memory_snapshot( nread = read(fd,ch,cap-ch); if (nread < 0) { - close(fd); + tpax_ftime_restore_and_close(dctx,fd,&dstst); return TPAX_SYSTEM_ERROR(dctx); } else if (nread == 0) { - close(fd); + tpax_ftime_restore_and_close(dctx,fd,&dstst); return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); } else { @@ -81,6 +82,9 @@ int tpax_io_create_memory_snapshot( } } + /* preserve last data access time as needed */ + tpax_ftime_restore(dctx,fd,&dstst); + /* stat compare */ if ((fstat(fd,&dstst)) < 0) { close(fd); diff --git a/src/io/tpax_create_tmpfs_snapshot.c b/src/io/tpax_create_tmpfs_snapshot.c index 9891e98..99a1665 100644 --- a/src/io/tpax_create_tmpfs_snapshot.c +++ b/src/io/tpax_create_tmpfs_snapshot.c @@ -19,6 +19,7 @@ #include "tpax_driver_impl.h" #include "tpax_tmpfile_impl.h" #include "tpax_errinfo_impl.h" +#include "tpax_ftime_impl.h" #ifndef ssizeof #define ssizeof(x) (ssize_t)(sizeof(x)) @@ -78,12 +79,12 @@ int tpax_io_create_tmpfs_snapshot( nbytes = read(fdsrc,buf,buflen); if (nbytes < 0) { - close(fdsrc); + tpax_ftime_restore_and_close(dctx,fdsrc,&dstst); close(fdtmp); return TPAX_SYSTEM_ERROR(dctx); } else if (nbytes == 0) { - close(fdsrc); + tpax_ftime_restore_and_close(dctx,fdsrc,&dstst); close(fdtmp); return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); @@ -98,7 +99,7 @@ int tpax_io_create_tmpfs_snapshot( ret = write(fdtmp,ch,nbytes); if (ret < 0) { - close(fdsrc); + tpax_ftime_restore_and_close(dctx,fdsrc,&dstst); close(fdtmp); return TPAX_SYSTEM_ERROR(dctx); @@ -108,6 +109,9 @@ int tpax_io_create_tmpfs_snapshot( } } + /* preserve last data access time as needed */ + tpax_ftime_restore(dctx,fdsrc,&dstst); + /* stat compare */ if ((fstat(fdsrc,&dstst)) < 0) { close(fdsrc); diff --git a/src/skin/tpax_skin_default.c b/src/skin/tpax_skin_default.c index a385aac..1684553 100644 --- a/src/skin/tpax_skin_default.c +++ b/src/skin/tpax_skin_default.c @@ -58,6 +58,14 @@ const tpax_hidden struct argv_option tpax_default_options[] = { ARGV_OPTION_HYBRID_ONLY,0,0, "do not recurse into directory archive members"}, + {"Wpreserve-atime", + 't',TAG_PRESERVE_ATIME,ARGV_OPTARG_NONE, + ARGV_OPTION_HYBRID_ONLY,0,0, + "when user has the necessary permissions, " + "set the access time of each file to the access " + "time that was reported by fstatat(3) prior to the " + "first read operation performed by pax"}, + {"Wstrict-path-input", 0,TAG_STRICT_PATH,ARGV_OPTARG_NONE, ARGV_OPTION_HYBRID_ONLY,0,0,