summaryrefslogtreecommitdiffhomepage
path: root/src/logic/tpax_archive_write.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/logic/tpax_archive_write.c')
-rw-r--r--src/logic/tpax_archive_write.c142
1 files changed, 132 insertions, 10 deletions
diff --git a/src/logic/tpax_archive_write.c b/src/logic/tpax_archive_write.c
index fbf46a7..492d3b1 100644
--- a/src/logic/tpax_archive_write.c
+++ b/src/logic/tpax_archive_write.c
@@ -13,6 +13,16 @@
#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,
const void * buf,
@@ -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;
@@ -112,6 +125,7 @@ static int tpax_archive_write_impl(
{
int ret;
struct tpax_unit_ctx * uctx;
+ struct tpax_cpio_header chdr;
struct tpax_ustar_header uhdr;
const struct stat * st;
struct stat stbuf;
@@ -206,9 +220,8 @@ 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 (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_RUSTAR) {
@@ -216,6 +229,14 @@ static int tpax_archive_write_impl(
} 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)
@@ -260,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);
@@ -270,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? */
@@ -352,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)
@@ -365,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);
@@ -373,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));