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.c169
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;
}