diff options
author | midipix <writeonce@midipix.org> | 2024-05-26 03:22:34 +0000 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2024-05-26 03:42:16 +0000 |
commit | 5ce6ff10c2cced4bf75db11b16984d565cf1ebec (patch) | |
tree | afca7a6eda843acd738b1ca349366688fa5d9ec3 /src/logic | |
parent | de63a008bfb04739bd189ed183e1dbd656ec4183 (diff) | |
download | tpax-5ce6ff10c2cced4bf75db11b16984d565cf1ebec.tar.bz2 tpax-5ce6ff10c2cced4bf75db11b16984d565cf1ebec.tar.xz |
logic: tpax_archive_write(): initial implementation and integration.
Diffstat (limited to 'src/logic')
-rw-r--r-- | src/logic/tpax_archive_write.c | 185 |
1 files changed, 183 insertions, 2 deletions
diff --git a/src/logic/tpax_archive_write.c b/src/logic/tpax_archive_write.c index b4dcf2a..272f9b9 100644 --- a/src/logic/tpax_archive_write.c +++ b/src/logic/tpax_archive_write.c @@ -9,6 +9,10 @@ #include "tpax_errinfo_impl.h" #include "tpax_visibility_impl.h" +#ifndef ssizeof +#define ssizeof(x) (ssize_t)(sizeof(x)) +#endif + static int tpax_archive_append_memory_data( int fdout, void * buf, @@ -59,6 +63,185 @@ static int tpax_archive_append_pad( return ret; } +static int tpax_archive_write_ret( + int ret, + struct tpax_unit_ctx * uctx) +{ + tpax_free_unit_ctx(uctx); + return ret; +} + +static int tpax_archive_write_impl( + const struct tpax_driver_ctx * dctx, + const struct tpax_dirent * cdent, + int fdcwd, + int fdout) +{ + struct tpax_unit_ctx * uctx; + struct tpax_ustar_header uhdr; + const char * path; + off_t hpos; + off_t dpos; + int fdtmp; + ssize_t nread; + ssize_t nbytes; + void * buf; + size_t buflen; + size_t cmplen; + void * membuf; + + /* full path */ + if (!(path = tpax_queue_item_full_path(dctx,cdent))) + return TPAX_CUSTOM_ERROR( + dctx, + TPAX_ERR_FLOW_ERROR); + + /* uctx */ + if (tpax_get_unit_ctx(dctx,fdcwd,path,&uctx) < 0) + return TPAX_NESTED_ERROR(dctx); + + /* record errors */ + tpax_driver_set_ectx( + dctx,0,path); + + /* header and data offsets: todo pax and cpio */ + hpos = tpax_get_driver_cpos(dctx); + dpos = hpos + sizeof(uhdr); + + /* header */ + if (tpax_init_ustar_header( + dctx,path,uctx->st, + *uctx->link,&uhdr) < 0) + return tpax_archive_write_ret( + TPAX_NESTED_ERROR(dctx), + uctx); + + /* buffer */ + membuf = 0; + fdtmp = -1; + + /* associated data? */ + if S_ISREG(uctx->st->st_mode) { + buf = tpax_get_driver_anon_map_addr( + dctx,&buflen); + + if (buflen >= (cmplen = uctx->st->st_size)) + membuf = buf; + + /* snapshot */ + if (membuf) { + if (tpax_file_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( + dctx,fdcwd,path, + uctx->st)) < 0) + return tpax_archive_write_ret( + TPAX_NESTED_ERROR(dctx), + uctx); + + if (lseek(fdtmp,0,SEEK_SET) < 0) + return tpax_archive_write_ret( + TPAX_SYSTEM_ERROR(dctx), + uctx); + } + } + + /* append header */ + if (tpax_archive_append_memory_data(fdout,&uhdr,ssizeof(uhdr)) < 0) { + if (fdtmp >= 0) + close(fdtmp); + + return tpax_archive_write_ret( + TPAX_SYSTEM_ERROR(dctx), + uctx); + } + + tpax_set_driver_cpos(dctx,dpos); + + /* all done? */ + if (!(S_ISREG(uctx->st->st_mode))) { + tpax_free_unit_ctx(uctx); + return 0; + } + + /* append data from snapshot */ + if (fdtmp >= 0) { + buf = tpax_get_driver_anon_map_addr( + dctx,&buflen); + + for (nread=0; nread<uctx->st->st_size; ) { + nbytes = read(fdtmp,buf,buflen); + + while ((nbytes < 0) && (errno == EINTR)) + nbytes = read(fdtmp,buf,buflen); + + if (nbytes < 0) { + close(fdtmp); + return tpax_archive_write_ret( + TPAX_SYSTEM_ERROR(dctx), + uctx); + + } else if (nbytes == 0) { + close(fdtmp); + return tpax_archive_write_ret( + TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR), + uctx); + + } else { + nread += nbytes; + } + + if (tpax_archive_append_memory_data(fdout,buf,nbytes) < 0) { + close(fdtmp); + return tpax_archive_write_ret( + TPAX_SYSTEM_ERROR(dctx), + uctx); + } + } + + close(fdtmp); + } else { + if (tpax_archive_append_memory_data( + fdout,membuf, + uctx->st->st_size) < 0) + return tpax_archive_write_ret( + TPAX_SYSTEM_ERROR(dctx), + uctx); + } + + return tpax_archive_write_ret( + tpax_archive_append_pad(dctx,fdout,uctx->st), + uctx); +} + +int tpax_archive_write(const struct tpax_driver_ctx * dctx) +{ + struct tpax_driver_ctx_impl * ictx; + struct tpax_dirent ** direntv; + int fdcwd; + int fdout; + + /* driver */ + ictx = tpax_get_driver_ictx(dctx); + fdcwd = tpax_driver_fdcwd(dctx); + fdout = tpax_driver_fdout(dctx); + + /* quote to archive */ + if (tpax_update_queue_vector(dctx) < 0) + return TPAX_NESTED_ERROR(dctx); + + for (direntv=ictx->direntv; *direntv; direntv++) + if (tpax_archive_write_impl(dctx,*direntv,fdcwd,fdout) < 0) + return TPAX_NESTED_ERROR(dctx); + + return 0; +} + int tpax_archive_seal(const struct tpax_driver_ctx * dctx) { int fdout; @@ -98,7 +281,5 @@ int tpax_archive_seal(const struct tpax_driver_ctx * dctx) tpax_set_driver_cpos(dctx,nwritten); } - (void)tpax_archive_append_pad; - return 0; } |