diff --git a/include/tpax/tpax.h b/include/tpax/tpax.h index 3514858..ac7745a 100644 --- a/include/tpax/tpax.h +++ b/include/tpax/tpax.h @@ -172,12 +172,12 @@ tpax_api int tpax_output_error_record (const struct tpax_driver_ctx *, con tpax_api int tpax_meta_init_ustar_header (const struct tpax_driver_ctx *, const char *, const struct stat *, const char *, struct tpax_ustar_header *); -/* low-level api */ -tpax_api int tpax_file_create_memory_snapshot (const struct tpax_driver_ctx *, int, const char *, - const struct stat *, void *); +/* low-level interfaces */ +tpax_api int tpax_io_create_memory_snapshot(const struct tpax_driver_ctx *, int, const char *, + const struct stat *, void *); -tpax_api int tpax_file_create_tmpfs_snapshot (const struct tpax_driver_ctx *, int, const char *, - const struct stat *); +tpax_api int tpax_io_create_tmpfs_snapshot (const struct tpax_driver_ctx *, int, const char *, + const struct stat *); /* package info */ tpax_api const struct tpax_source_version * tpax_source_version(void); diff --git a/project/common.mk b/project/common.mk index 43297fb..a23c2ef 100644 --- a/project/common.mk +++ b/project/common.mk @@ -2,10 +2,10 @@ API_SRCS = \ src/driver/tpax_amain.c \ src/driver/tpax_driver_ctx.c \ src/driver/tpax_unit_ctx.c \ + src/io/tpax_create_memory_snapshot.c \ + src/io/tpax_create_tmpfs_snapshot.c \ src/logic/tpax_archive_append.c \ src/logic/tpax_archive_write.c \ - src/logic/tpax_file_create_memory_snapshot.c \ - src/logic/tpax_file_create_tmpfs_snapshot.c \ src/logic/tpax_queue_vector.c \ src/meta/tpax_init_ustar_header.c \ src/output/tpax_output_error.c \ diff --git a/project/tree.mk b/project/tree.mk index 90a5470..affd4ba 100644 --- a/project/tree.mk +++ b/project/tree.mk @@ -1,6 +1,7 @@ TREE_DIRS = bin lib src \ src/driver \ src/internal \ + src/io \ src/logic \ src/meta \ src/output \ diff --git a/src/io/tpax_create_memory_snapshot.c b/src/io/tpax_create_memory_snapshot.c new file mode 100644 index 0000000..7c3dd7e --- /dev/null +++ b/src/io/tpax_create_memory_snapshot.c @@ -0,0 +1,98 @@ +/**************************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/**************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "tpax_driver_impl.h" +#include "tpax_errinfo_impl.h" + +#ifndef ssizeof +#define ssizeof(x) (ssize_t)(sizeof(x)) +#endif + +int tpax_io_create_memory_snapshot( + const struct tpax_driver_ctx * dctx, + int fdat, + const char * path, + const struct stat * srcst, + void * addr) +{ + int fd; + char * ch; + char * cap; + ssize_t nread; + struct stat dstst; + + /* record errors */ + tpax_driver_set_ectx( + dctx,0,path); + + /* memory snapshot internal limit */ + if (srcst->st_size >= 0x80000000) + return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_REGION_SIZE); + + /* open */ + if ((fd = openat(fdat,path,O_CLOEXEC|O_NOCTTY|O_NOFOLLOW,0)) < 0) + return TPAX_SYSTEM_ERROR(dctx); + + /* stat compare */ + if ((fstat(fd,&dstst)) < 0) { + close(fd); + return TPAX_SYSTEM_ERROR(dctx); + + } else if (tpax_util_stat_compare(srcst,&dstst)) { + close(fd); + return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); + } + + /* read loop */ + ch = addr; + cap = &ch[srcst->st_size]; + + while (ch < cap) { + nread = read(fd,ch,cap-ch); + + while ((nread < 0) && (errno == EINTR)) + nread = read(fd,ch,cap-ch); + + if (nread < 0) { + close(fd); + return TPAX_SYSTEM_ERROR(dctx); + + } else if (nread == 0) { + close(fd); + return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); + + } else { + ch += nread; + } + } + + /* stat compare */ + if ((fstat(fd,&dstst)) < 0) { + close(fd); + return TPAX_SYSTEM_ERROR(dctx); + + } else if (tpax_util_stat_compare(srcst,&dstst)) { + close(fd); + return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); + } + + /* yay */ + close(fd); + + return 0; +} diff --git a/src/io/tpax_create_tmpfs_snapshot.c b/src/io/tpax_create_tmpfs_snapshot.c new file mode 100644 index 0000000..9891e98 --- /dev/null +++ b/src/io/tpax_create_tmpfs_snapshot.c @@ -0,0 +1,127 @@ +/**************************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/**************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "tpax_driver_impl.h" +#include "tpax_tmpfile_impl.h" +#include "tpax_errinfo_impl.h" + +#ifndef ssizeof +#define ssizeof(x) (ssize_t)(sizeof(x)) +#endif + +int tpax_io_create_tmpfs_snapshot( + const struct tpax_driver_ctx * dctx, + int fdat, + const char * path, + const struct stat * srcst) +{ + int fdsrc; + int fdtmp; + char * ch; + ssize_t nread; + ssize_t nbytes; + ssize_t ret; + void * buf; + size_t buflen; + struct stat dstst; + + /* record errors */ + tpax_driver_set_ectx( + dctx,0,path); + + /* tmpfile */ + if ((fdtmp = tpax_tmpfile()) < 0) + return TPAX_SYSTEM_ERROR(dctx); + + /* buffer */ + buf = tpax_get_driver_anon_map_addr( + dctx,&buflen); + + /* open */ + if ((fdsrc = openat(fdat,path,O_CLOEXEC|O_NOCTTY|O_NOFOLLOW,0)) < 0) { + close(fdtmp); + return TPAX_SYSTEM_ERROR(dctx); + } + + /* stat compare */ + if ((fstat(fdsrc,&dstst)) < 0) { + close(fdsrc); + close(fdtmp); + return TPAX_SYSTEM_ERROR(dctx); + + } else if (tpax_util_stat_compare(srcst,&dstst)) { + close(fdsrc); + close(fdtmp); + return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); + } + + /* read/write loop */ + for (nread=0; nreadst_size; ) { + nbytes = read(fdsrc,buf,buflen); + + while ((nbytes < 0) && (errno == EINTR)) + nbytes = read(fdsrc,buf,buflen); + + if (nbytes < 0) { + close(fdsrc); + close(fdtmp); + return TPAX_SYSTEM_ERROR(dctx); + + } else if (nbytes == 0) { + close(fdsrc); + close(fdtmp); + return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); + + } else { + nread += nbytes; + } + + for (ch=buf; nbytes; ch+=ret) { + ret = write(fdtmp,ch,nbytes); + + while ((ret < 0) && (errno == EINTR)) + ret = write(fdtmp,ch,nbytes); + + if (ret < 0) { + close(fdsrc); + close(fdtmp); + return TPAX_SYSTEM_ERROR(dctx); + + } else { + nbytes -= ret; + } + } + } + + /* stat compare */ + if ((fstat(fdsrc,&dstst)) < 0) { + close(fdsrc); + close(fdtmp); + return TPAX_SYSTEM_ERROR(dctx); + + } else if (tpax_util_stat_compare(srcst,&dstst)) { + close(fdsrc); + close(fdtmp); + return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); + } + + /* yay */ + close(fdsrc); + + return fdtmp; +} diff --git a/src/logic/tpax_archive_write.c b/src/logic/tpax_archive_write.c index c5109d3..5214787 100644 --- a/src/logic/tpax_archive_write.c +++ b/src/logic/tpax_archive_write.c @@ -130,14 +130,14 @@ static int tpax_archive_write_impl( /* snapshot */ if (membuf) { - if (tpax_file_create_memory_snapshot( + if (tpax_io_create_memory_snapshot( dctx,fdcwd,path, uctx->st,membuf) < 0) return tpax_archive_write_ret( TPAX_NESTED_ERROR(dctx), uctx); } else { - if ((fdtmp = tpax_file_create_tmpfs_snapshot( + if ((fdtmp = tpax_io_create_tmpfs_snapshot( dctx,fdcwd,path, uctx->st)) < 0) return tpax_archive_write_ret( diff --git a/src/logic/tpax_file_create_memory_snapshot.c b/src/logic/tpax_file_create_memory_snapshot.c deleted file mode 100644 index 504a4a1..0000000 --- a/src/logic/tpax_file_create_memory_snapshot.c +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************/ -/* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ -/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ -/**************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "tpax_driver_impl.h" -#include "tpax_errinfo_impl.h" - -#ifndef ssizeof -#define ssizeof(x) (ssize_t)(sizeof(x)) -#endif - -int tpax_file_create_memory_snapshot( - const struct tpax_driver_ctx * dctx, - int fdat, - const char * path, - const struct stat * srcst, - void * addr) -{ - int fd; - char * ch; - char * cap; - ssize_t nread; - struct stat dstst; - - /* record errors */ - tpax_driver_set_ectx( - dctx,0,path); - - /* memory snapshot internal limit */ - if (srcst->st_size >= 0x80000000) - return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_REGION_SIZE); - - /* open */ - if ((fd = openat(fdat,path,O_CLOEXEC|O_NOCTTY|O_NOFOLLOW,0)) < 0) - return TPAX_SYSTEM_ERROR(dctx); - - /* stat compare */ - if ((fstat(fd,&dstst)) < 0) { - close(fd); - return TPAX_SYSTEM_ERROR(dctx); - - } else if (tpax_util_stat_compare(srcst,&dstst)) { - close(fd); - return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); - } - - /* read loop */ - ch = addr; - cap = &ch[srcst->st_size]; - - while (ch < cap) { - nread = read(fd,ch,cap-ch); - - while ((nread < 0) && (errno == EINTR)) - nread = read(fd,ch,cap-ch); - - if (nread < 0) { - close(fd); - return TPAX_SYSTEM_ERROR(dctx); - - } else if (nread == 0) { - close(fd); - return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); - - } else { - ch += nread; - } - } - - /* stat compare */ - if ((fstat(fd,&dstst)) < 0) { - close(fd); - return TPAX_SYSTEM_ERROR(dctx); - - } else if (tpax_util_stat_compare(srcst,&dstst)) { - close(fd); - return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); - } - - /* yay */ - close(fd); - - return 0; -} diff --git a/src/logic/tpax_file_create_tmpfs_snapshot.c b/src/logic/tpax_file_create_tmpfs_snapshot.c deleted file mode 100644 index 2e92211..0000000 --- a/src/logic/tpax_file_create_tmpfs_snapshot.c +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************/ -/* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ -/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ -/**************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "tpax_driver_impl.h" -#include "tpax_tmpfile_impl.h" -#include "tpax_errinfo_impl.h" - -#ifndef ssizeof -#define ssizeof(x) (ssize_t)(sizeof(x)) -#endif - -int tpax_file_create_tmpfs_snapshot( - const struct tpax_driver_ctx * dctx, - int fdat, - const char * path, - const struct stat * srcst) -{ - int fdsrc; - int fdtmp; - char * ch; - ssize_t nread; - ssize_t nbytes; - ssize_t ret; - void * buf; - size_t buflen; - struct stat dstst; - - /* record errors */ - tpax_driver_set_ectx( - dctx,0,path); - - /* tmpfile */ - if ((fdtmp = tpax_tmpfile()) < 0) - return TPAX_SYSTEM_ERROR(dctx); - - /* buffer */ - buf = tpax_get_driver_anon_map_addr( - dctx,&buflen); - - /* open */ - if ((fdsrc = openat(fdat,path,O_CLOEXEC|O_NOCTTY|O_NOFOLLOW,0)) < 0) { - close(fdtmp); - return TPAX_SYSTEM_ERROR(dctx); - } - - /* stat compare */ - if ((fstat(fdsrc,&dstst)) < 0) { - close(fdsrc); - close(fdtmp); - return TPAX_SYSTEM_ERROR(dctx); - - } else if (tpax_util_stat_compare(srcst,&dstst)) { - close(fdsrc); - close(fdtmp); - return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); - } - - /* read/write loop */ - for (nread=0; nreadst_size; ) { - nbytes = read(fdsrc,buf,buflen); - - while ((nbytes < 0) && (errno == EINTR)) - nbytes = read(fdsrc,buf,buflen); - - if (nbytes < 0) { - close(fdsrc); - close(fdtmp); - return TPAX_SYSTEM_ERROR(dctx); - - } else if (nbytes == 0) { - close(fdsrc); - close(fdtmp); - return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); - - } else { - nread += nbytes; - } - - for (ch=buf; nbytes; ch+=ret) { - ret = write(fdtmp,ch,nbytes); - - while ((ret < 0) && (errno == EINTR)) - ret = write(fdtmp,ch,nbytes); - - if (ret < 0) { - close(fdsrc); - close(fdtmp); - return TPAX_SYSTEM_ERROR(dctx); - - } else { - nbytes -= ret; - } - } - } - - /* stat compare */ - if ((fstat(fdsrc,&dstst)) < 0) { - close(fdsrc); - close(fdtmp); - return TPAX_SYSTEM_ERROR(dctx); - - } else if (tpax_util_stat_compare(srcst,&dstst)) { - close(fdsrc); - close(fdtmp); - return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FILE_CHANGED); - } - - /* yay */ - close(fdsrc); - - return fdtmp; -}