/**************************************************************/ /* tpax: a topological pax implementation */ /* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ #include #include "tpax_driver_impl.h" #include "tpax_errinfo_impl.h" #include "tpax_visibility_impl.h" static int tpax_archive_append_memory_data( int fdout, void * buf, ssize_t nbytes) { ssize_t ret; char * ch; for (ch=buf; nbytes; ch+=ret) { ret = write(fdout,ch,nbytes); while ((ret < 0) && (errno == EINTR)) ret = write(fdout,ch,nbytes); if (ret < 0) return ret; nbytes -= ret; } return 0; } static int tpax_archive_append_pad( const struct tpax_driver_ctx * dctx, int fdout, const struct stat * st) { int ret; off_t cpos; ssize_t nbytes; char buf[512]; nbytes = st->st_size; nbytes += 0x1ff; nbytes |= 0x1ff; nbytes ^= 0x1ff; nbytes -= st->st_size; memset(buf,0,nbytes); cpos = tpax_get_driver_cpos(dctx); cpos += st->st_size + nbytes; if (!(ret = tpax_archive_append_memory_data(fdout,buf,nbytes))) tpax_set_driver_cpos(dctx,cpos); return ret; } int tpax_archive_seal(const struct tpax_driver_ctx * dctx) { int fdout; off_t cpos; ssize_t nbytes; ssize_t nwritten; ssize_t blksize; char buf[512]; blksize = tpax_get_archive_block_size(dctx); cpos = tpax_get_driver_cpos(dctx); if (cpos % 512) return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); fdout = tpax_driver_fdout(dctx); memset(buf,0,sizeof(buf)); switch (cpos % blksize) { case 0: nbytes = cpos + blksize; break; default: nbytes = cpos / blksize; nbytes *= blksize; nbytes += blksize; if (nbytes-cpos == 512) nbytes += blksize; } for (nwritten=cpos; nwritten