summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2024-05-30 22:45:00 +0000
committermidipix <writeonce@midipix.org>2024-05-30 22:45:00 +0000
commitee80f814e924d7e84e02b290f5f8796d6c4b05be (patch)
tree8c78b3821a7daa042fd572083c1aa8f5cc9654af
parent55da8fe4b7c34589e14af92421077f906f65a592 (diff)
downloadtpax-ee80f814e924d7e84e02b290f5f8796d6c4b05be.tar.bz2
tpax-ee80f814e924d7e84e02b290f5f8796d6c4b05be.tar.xz
driver: implemented and integrated the -t (preserve atime) command-line option.
-rw-r--r--include/tpax/tpax.h3
-rw-r--r--project/common.mk1
-rw-r--r--project/headers.mk1
-rw-r--r--src/driver/tpax_driver_ctx.c4
-rw-r--r--src/internal/tpax_driver_impl.h1
-rw-r--r--src/internal/tpax_ftime_impl.c48
-rw-r--r--src/internal/tpax_ftime_impl.h24
-rw-r--r--src/io/tpax_create_memory_snapshot.c8
-rw-r--r--src/io/tpax_create_tmpfs_snapshot.c10
-rw-r--r--src/skin/tpax_skin_default.c8
10 files changed, 103 insertions, 5 deletions
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 <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#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 <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#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 <tpax/tpax_specs.h>
#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,