diff options
Diffstat (limited to 'src/logic/tpax_archive_write.c')
-rw-r--r-- | src/logic/tpax_archive_write.c | 162 |
1 files changed, 145 insertions, 17 deletions
diff --git a/src/logic/tpax_archive_write.c b/src/logic/tpax_archive_write.c index 96af625..492d3b1 100644 --- a/src/logic/tpax_archive_write.c +++ b/src/logic/tpax_archive_write.c @@ -13,13 +13,23 @@ #define ssizeof(x) (ssize_t)(sizeof(x)) #endif +static const char tpax_cpio_trailer[11] = TPAX_CPIO_TRAILER; + +static void tpax_cpio_octal_write(char * ch, ssize_t len, uint64_t val) +{ + for (; len; ) { + ch[--len] = val % 8 + '0'; + val /= 8; + } +} + static int tpax_archive_append_memory_data( int fdout, - void * buf, + const void * buf, ssize_t nbytes) { - ssize_t ret; - char * ch; + ssize_t ret; + const char * ch; for (ch=buf; nbytes; ch+=ret) { ret = write(fdout,ch,nbytes); @@ -46,6 +56,9 @@ static int tpax_archive_append_pad( ssize_t nbytes; char buf[512]; + if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_CPIO) + return 0; + nbytes = st->st_size; nbytes += 0x1ff; nbytes |= 0x1ff; @@ -110,7 +123,9 @@ static int tpax_archive_write_impl( int fdcwd, int fdout) { + int ret; struct tpax_unit_ctx * uctx; + struct tpax_cpio_header chdr; struct tpax_ustar_header uhdr; const struct stat * st; struct stat stbuf; @@ -143,7 +158,7 @@ static int tpax_archive_write_impl( TPAX_ERR_FLOW_ERROR); /* regex matching and patter substitution */ - if ((slen = tpax_apply_string_replacement(dctx,path,replbuf,buflen)) < 0) + if ((slen = tpax_apply_string_replacement(dctx,path,replbuf,PATH_MAX)) < 0) return TPAX_CUSTOM_ERROR( dctx, TPAX_ERR_FLOW_ERROR); @@ -205,14 +220,26 @@ static int tpax_archive_write_impl( tpax_driver_set_ectx( dctx,0,path); - /* header and data offsets: todo pax and cpio */ + /* header offset */ hpos = tpax_get_driver_cpos(dctx); - dpos = hpos + sizeof(uhdr); /* header */ - if (tpax_meta_init_ustar_header( - dctx,apath,st, - slnk,&uhdr) < 0) + if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_RUSTAR) { + ret = tpax_meta_init_rustar_header(apath,st,slnk,&uhdr); + + } else if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_USTAR) { + ret = tpax_meta_init_ustar_header(apath,st,slnk,&uhdr); + + } else if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_CPIO) { + ret = tpax_meta_init_cpio_header( + apath,st,slnk, + cdent->cpdev, + cdent->cpino, + cdent->nlink, + &chdr); + } + + if (ret < 0) return tpax_archive_write_ret( TPAX_NESTED_ERROR(dctx), dctx,uctx); @@ -254,8 +281,28 @@ static int tpax_archive_write_impl( } } - /* append header */ - if (tpax_archive_append_memory_data(fdout,&uhdr,ssizeof(uhdr)) < 0) { + /* append header (and cpio symbolic link data) */ + if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_CPIO) { + ret = tpax_archive_append_memory_data( + fdout,&chdr, + offsetof(struct tpax_cpio_header,c_namedata)); + + if (ret == 0) + ret = tpax_archive_append_memory_data( + fdout,apath, + strlen(apath) + 1); + + if ((ret == 0) && slnk) + ret = tpax_archive_append_memory_data( + fdout,slnk, + strlen(slnk)); + } else { + ret = tpax_archive_append_memory_data( + fdout,&uhdr, + ssizeof(uhdr)); + } + + if (ret < 0) { if (fdtmp >= 0) close(fdtmp); @@ -264,6 +311,16 @@ static int tpax_archive_write_impl( dctx,uctx); } + /* data offset */ + if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_CPIO) { + dpos = hpos; + dpos += offsetof(struct tpax_cpio_header,c_namedata); + dpos += strlen(apath) + 1; + dpos += slnk ? strlen(slnk) : 0; + } else { + dpos = hpos + ssizeof(uhdr); + } + tpax_set_driver_cpos(dctx,dpos); /* all done? */ @@ -346,8 +403,79 @@ int tpax_archive_write(const struct tpax_driver_ctx * dctx) static int tpax_archive_seal_cpio(const struct tpax_driver_ctx * dctx) { - (void)dctx; - return -1; + int fdout; + off_t cpos; + ssize_t nbytes; + ssize_t blksize; + ssize_t nwritten; + char buf[1024]; + struct tpax_cpio_header chdr; + + /* trailer initialization */ + memset(buf,0,sizeof(buf)); + memset(&chdr,0,sizeof(chdr)); + + tpax_cpio_octal_write(chdr.c_magic,sizeof(chdr.c_magic),0070707); + tpax_cpio_octal_write(chdr.c_dev,sizeof(chdr.c_dev),0); + tpax_cpio_octal_write(chdr.c_ino,sizeof(chdr.c_ino),0); + tpax_cpio_octal_write(chdr.c_mode,sizeof(chdr.c_mode),0); + tpax_cpio_octal_write(chdr.c_uid,sizeof(chdr.c_uid),0); + tpax_cpio_octal_write(chdr.c_gid,sizeof(chdr.c_gid),0); + tpax_cpio_octal_write(chdr.c_nlink,sizeof(chdr.c_nlink),1); + tpax_cpio_octal_write(chdr.c_rdev,sizeof(chdr.c_rdev),0); + tpax_cpio_octal_write(chdr.c_mtime,sizeof(chdr.c_mtime),0); + + tpax_cpio_octal_write(chdr.c_filesize,sizeof(chdr.c_filesize),0); + tpax_cpio_octal_write(chdr.c_namesize,sizeof(chdr.c_namesize),sizeof(tpax_cpio_trailer)); + + /* fdout, archive block size, current position */ + fdout = tpax_driver_fdout(dctx); + blksize = dctx->cctx->blksize; + cpos = tpax_get_driver_cpos(dctx); + + /* trailer header */ + nbytes = offsetof(struct tpax_cpio_header,c_namedata); + + if (tpax_archive_append_memory_data(fdout,&chdr,nbytes) < 0) + return TPAX_SYSTEM_ERROR(dctx); + + cpos += nbytes; + + /* trailer c_namedata[] */ + nbytes = sizeof(tpax_cpio_trailer); + + if (tpax_archive_append_memory_data(fdout,tpax_cpio_trailer,nbytes) < 0) + return TPAX_SYSTEM_ERROR(dctx); + + cpos += nbytes; + + /* pad the current block to a 512 byte boundary */ + nbytes = (cpos % 512) ? 512 - (cpos % 512) : 0; + + if (tpax_archive_append_memory_data(fdout,buf,nbytes) < 0) + return TPAX_SYSTEM_ERROR(dctx); + + cpos += nbytes; + + /* 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); + + /* all done */ + tpax_set_driver_cpos(dctx,nwritten); + + return 0; } int tpax_archive_seal(const struct tpax_driver_ctx * dctx) @@ -359,6 +487,10 @@ int tpax_archive_seal(const struct tpax_driver_ctx * dctx) ssize_t blksize; char buf[1024]; + /* cpio trailer? */ + if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_CPIO) + return tpax_archive_seal_cpio(dctx); + /* archive block size, current position */ blksize = dctx->cctx->blksize; cpos = tpax_get_driver_cpos(dctx); @@ -367,10 +499,6 @@ int tpax_archive_seal(const struct tpax_driver_ctx * dctx) 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)); |