diff options
Diffstat (limited to 'src/logic/tpax_archive_write.c')
-rw-r--r-- | src/logic/tpax_archive_write.c | 169 |
1 files changed, 126 insertions, 43 deletions
diff --git a/src/logic/tpax_archive_write.c b/src/logic/tpax_archive_write.c index 5214787..7ce6cca 100644 --- a/src/logic/tpax_archive_write.c +++ b/src/logic/tpax_archive_write.c @@ -64,9 +64,13 @@ static int tpax_archive_append_pad( } static int tpax_archive_write_ret( - int ret, - struct tpax_unit_ctx * uctx) + int ret, + const struct tpax_driver_ctx * dctx, + struct tpax_unit_ctx * uctx) { + if (dctx->cctx->drvflags & TPAX_DRIVER_VERBOSE) + tpax_dprintf(tpax_driver_fderr(dctx),"\n",0); + tpax_lib_free_unit_ctx(uctx); return ret; } @@ -79,7 +83,11 @@ static int tpax_archive_write_impl( { struct tpax_unit_ctx * uctx; struct tpax_ustar_header uhdr; + const struct stat * st; + struct stat stbuf; const char * path; + const char * slnk; + const char * mlnk; off_t hpos; off_t dpos; int fdtmp; @@ -89,6 +97,12 @@ static int tpax_archive_write_impl( size_t buflen; size_t cmplen; void * membuf; + char * ch; + char pathbuf[PATH_MAX]; + + /* followed symlink? */ + if (cdent->flags & TPAX_ITEM_NAMEREF) + return 0; /* full path */ if (!(path = tpax_queue_item_full_path(dctx,cdent))) @@ -96,9 +110,56 @@ static int tpax_archive_write_impl( dctx, TPAX_ERR_FLOW_ERROR); + /* verbose mode */ + if (dctx->cctx->drvflags & TPAX_DRIVER_VERBOSE) + tpax_dprintf(tpax_driver_fderr(dctx),"%s",path); + /* uctx */ if (tpax_lib_get_unit_ctx(dctx,fdcwd,path,&uctx) < 0) - return TPAX_NESTED_ERROR(dctx); + tpax_archive_write_ret( + TPAX_NESTED_ERROR(dctx), + dctx,0); + + st = uctx->st; + slnk = uctx->link[0]; + mlnk = 0; + + if (cdent->flags & TPAX_ITEM_SYMLINK) { + st = &stbuf; + mlnk = slnk; + slnk = 0; + ch = 0; + + if (mlnk[0] != '/') { + if (strlen(path) >= PATH_MAX) + return tpax_archive_write_ret( + TPAX_CUSTOM_ERROR( + dctx, + TPAX_ERR_FLOW_ERROR), + dctx,uctx); + + strcpy(pathbuf,path); + + ch = strrchr(pathbuf,'/'); + } + + if (ch && (++ch - pathbuf >= PATH_MAX)) + return tpax_archive_write_ret( + TPAX_CUSTOM_ERROR( + dctx, + TPAX_ERR_FLOW_ERROR), + dctx,uctx); + + if (ch) { + strcpy(ch,mlnk); + mlnk = pathbuf; + } + + if (fstatat(fdcwd,mlnk,&stbuf,0) < 0) + return tpax_archive_write_ret( + TPAX_SYSTEM_ERROR(dctx), + dctx,uctx); + } /* record errors */ tpax_driver_set_ectx( @@ -110,44 +171,46 @@ static int tpax_archive_write_impl( /* header */ if (tpax_meta_init_ustar_header( - dctx,path,uctx->st, - *uctx->link,&uhdr) < 0) + dctx,path,st, + slnk,&uhdr) < 0) return tpax_archive_write_ret( TPAX_NESTED_ERROR(dctx), - uctx); + dctx,uctx); /* buffer */ membuf = 0; fdtmp = -1; /* associated data? */ - if S_ISREG(uctx->st->st_mode) { + if S_ISREG(st->st_mode) { buf = tpax_get_driver_anon_map_addr( dctx,&buflen); - if (buflen >= (cmplen = uctx->st->st_size)) + if (buflen >= (cmplen = st->st_size)) membuf = buf; /* snapshot */ if (membuf) { if (tpax_io_create_memory_snapshot( - dctx,fdcwd,path, - uctx->st,membuf) < 0) + dctx,fdcwd, + mlnk ? mlnk : path, + st,membuf) < 0) return tpax_archive_write_ret( TPAX_NESTED_ERROR(dctx), - uctx); + dctx,uctx); } else { if ((fdtmp = tpax_io_create_tmpfs_snapshot( - dctx,fdcwd,path, - uctx->st)) < 0) + dctx,fdcwd, + mlnk ? mlnk : path, + st)) < 0) return tpax_archive_write_ret( TPAX_NESTED_ERROR(dctx), - uctx); + dctx,uctx); if (lseek(fdtmp,0,SEEK_SET) < 0) return tpax_archive_write_ret( TPAX_SYSTEM_ERROR(dctx), - uctx); + dctx,uctx); } } @@ -158,23 +221,22 @@ static int tpax_archive_write_impl( return tpax_archive_write_ret( TPAX_SYSTEM_ERROR(dctx), - uctx); + dctx,uctx); } tpax_set_driver_cpos(dctx,dpos); /* all done? */ - if (!(S_ISREG(uctx->st->st_mode))) { - tpax_lib_free_unit_ctx(uctx); - return 0; - } + if (!(S_ISREG(st->st_mode))) + return tpax_archive_write_ret( + 0,dctx,uctx); /* append data from snapshot */ if (fdtmp >= 0) { buf = tpax_get_driver_anon_map_addr( dctx,&buflen); - for (nread=0; nread<uctx->st->st_size; ) { + for (nread=0; nread<st->st_size; ) { nbytes = read(fdtmp,buf,buflen); while ((nbytes < 0) && (errno == EINTR)) @@ -184,13 +246,13 @@ static int tpax_archive_write_impl( close(fdtmp); return tpax_archive_write_ret( TPAX_SYSTEM_ERROR(dctx), - uctx); + dctx,uctx); } else if (nbytes == 0) { close(fdtmp); return tpax_archive_write_ret( TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR), - uctx); + dctx,uctx); } else { nread += nbytes; @@ -200,7 +262,7 @@ static int tpax_archive_write_impl( close(fdtmp); return tpax_archive_write_ret( TPAX_SYSTEM_ERROR(dctx), - uctx); + dctx,uctx); } } @@ -208,15 +270,15 @@ static int tpax_archive_write_impl( } else { if (tpax_archive_append_memory_data( fdout,membuf, - uctx->st->st_size) < 0) + st->st_size) < 0) return tpax_archive_write_ret( TPAX_SYSTEM_ERROR(dctx), - uctx); + dctx,uctx); } return tpax_archive_write_ret( - tpax_archive_append_pad(dctx,fdout,uctx->st), - uctx); + tpax_archive_append_pad(dctx,fdout,st), + dctx,uctx); } int tpax_archive_write(const struct tpax_driver_ctx * dctx) @@ -242,6 +304,12 @@ int tpax_archive_write(const struct tpax_driver_ctx * dctx) return 0; } +static int tpax_archive_seal_cpio(const struct tpax_driver_ctx * dctx) +{ + (void)dctx; + return -1; +} + int tpax_archive_seal(const struct tpax_driver_ctx * dctx) { int fdout; @@ -249,37 +317,52 @@ int tpax_archive_seal(const struct tpax_driver_ctx * dctx) ssize_t nbytes; ssize_t nwritten; ssize_t blksize; - char buf[512]; + char buf[1024]; - blksize = tpax_get_archive_block_size(dctx); + /* archive block size, current position */ + blksize = dctx->cctx->blksize; cpos = tpax_get_driver_cpos(dctx); + /* internal error? */ if (cpos % 512) return TPAX_CUSTOM_ERROR(dctx,TPAX_ERR_FLOW_ERROR); + /* cpio trailer? */ + if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_CPIO) + return tpax_archive_seal_cpio(dctx); + + /* ustar, pax */ fdout = tpax_driver_fdout(dctx); memset(buf,0,sizeof(buf)); - switch (cpos % blksize) { - case 0: - nbytes = cpos + blksize; - break; + if (tpax_archive_append_memory_data(fdout,buf,2*512) < 0) + return TPAX_SYSTEM_ERROR(dctx); - default: - nbytes = cpos / blksize; - nbytes *= blksize; - nbytes += blksize; + cpos += 2*512; - if (nbytes-cpos == 512) - nbytes += blksize; + /* pax? */ + if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_PAX) { + tpax_set_driver_cpos(dctx,cpos); + return 0; } - for (nwritten=cpos; nwritten<nbytes; nwritten+=512) { + /* already at block boundary? */ + if ((cpos % blksize) == 0) { + tpax_set_driver_cpos(dctx,cpos); + return 0; + } + + /* zero-fill the remainder of the block */ + nbytes = cpos / blksize; + nbytes *= blksize; + nbytes += blksize; + + for (nwritten=cpos; nwritten<nbytes; nwritten+=512) if (tpax_archive_append_memory_data(fdout,buf,512) < 0) return TPAX_SYSTEM_ERROR(dctx); - tpax_set_driver_cpos(dctx,nwritten); - } + /* all done */ + tpax_set_driver_cpos(dctx,nwritten); return 0; } |