diff --git a/src/driver/tpax_driver_ctx.c b/src/driver/tpax_driver_ctx.c index 0a92537..c621bb6 100644 --- a/src/driver/tpax_driver_ctx.c +++ b/src/driver/tpax_driver_ctx.c @@ -276,6 +276,12 @@ static struct tpax_driver_ctx_impl * tpax_driver_ctx_alloc( ictx->ctx.errinfp = &ictx->ctx.erriptr[0]; ictx->ctx.erricap = &ictx->ctx.erriptr[--elements]; + elements = sizeof(ictx->ctx.prefptr) / sizeof(*ictx->ctx.prefptr); + + ictx->ctx.prefixv = &ictx->ctx.prefptr[0]; + ictx->ctx.prefixp = &ictx->ctx.prefptr[0]; + ictx->ctx.prefcap = &ictx->ctx.prefptr[--elements]; + ictx->meta = meta; for (entry=meta->entries,units=ictx->units; entry->fopt || entry->arg; entry++) @@ -561,6 +567,7 @@ static void tpax_free_driver_ctx_impl(struct tpax_driver_ctx_alloc * ictx) { void * next; size_t size; + char ** ppref; for (; ictx->ctx.dirents; ) { next = ictx->ctx.dirents->next; @@ -576,6 +583,12 @@ static void tpax_free_driver_ctx_impl(struct tpax_driver_ctx_alloc * ictx) if (ictx->ctx.dirbuff) munmap(ictx->ctx.dirbuff,TPAX_DIRENT_BUFLEN); + for (ppref=ictx->ctx.prefixv; *ppref; ppref++) + free(*ppref); + + if (ictx->ctx.prefixv != ictx->ctx.prefptr) + free(ictx->ctx.prefixv); + argv_free(ictx->meta); free(ictx); } diff --git a/src/internal/tpax_driver_impl.h b/src/internal/tpax_driver_impl.h index 5fabb0a..ea02185 100644 --- a/src/internal/tpax_driver_impl.h +++ b/src/internal/tpax_driver_impl.h @@ -26,6 +26,9 @@ (TPAX_DRIVER_EXEC_MODE_WRITE | \ TPAX_DRIVER_EXEC_MODE_COPY) +#define TPAX_ITEM_EXPLICIT 0X1 +#define TPAX_ITEM_IMPLICIT 0X2 + extern const struct argv_option tpax_default_options[]; enum app_tags { @@ -46,7 +49,9 @@ enum app_tags { struct tpax_dirent { int fdat; int depth; + int flags; size_t nsize; + const char * prefix; const struct tpax_dirent * parent; struct dirent dirent; }; @@ -69,6 +74,10 @@ struct tpax_driver_ctx_impl { struct tpax_error_info ** erricap; struct tpax_error_info * erriptr[64]; struct tpax_error_info erribuf[64]; + char ** prefixv; + char ** prefixp; + char ** prefcap; + char * prefptr[64]; struct tpax_dirent_buffer * dirents; void * dirbuff; void * bufaddr; diff --git a/src/logic/tpax_archive_append.c b/src/logic/tpax_archive_append.c index 4bc3d2f..d8ac12f 100644 --- a/src/logic/tpax_archive_append.c +++ b/src/logic/tpax_archive_append.c @@ -49,6 +49,49 @@ static int tpax_archive_append_memory_data( return 0; } +static char * tpax_append_prefix_item( + const struct tpax_driver_ctx * dctx, + const char * prefix) +{ + struct tpax_driver_ctx_impl * ictx; + char ** prefv; + char ** psrc; + char ** pdst; + off_t elements; + char * pitem; + + ictx = tpax_get_driver_ictx(dctx); + + for (psrc=ictx->prefixv; *psrc; psrc++) + if (!strcmp(*psrc,prefix)) + return *psrc; + + if (ictx->prefixp == ictx->prefcap) { + elements = ictx->prefcap - ictx->prefixv; + elements += 256; + + if (!(prefv = calloc(elements,sizeof(char *)))) + return 0; + + for (psrc=ictx->prefixv,pdst=prefv; *psrc; psrc++,pdst++) + *pdst = *psrc; + + if (ictx->prefixv != ictx->prefptr) + free(ictx->prefixv); + + ictx->prefixv = prefv; + ictx->prefixp = pdst; + ictx->prefcap = &prefv[--elements]; + } + + if (!(pitem = strdup(prefix))) + return 0; + + *ictx->prefixp++ = pitem; + + return pitem; +} + static int tpax_archive_append_pad( const struct tpax_driver_ctx * dctx, int fdout, @@ -144,11 +187,12 @@ static int tpax_archive_append_queue_item( const struct tpax_driver_ctx * dctx, const struct dirent * dirent, const struct tpax_dirent * parent, + const char * prefix, struct tpax_unit_ctx * unit, int depth, + int flags, int fd, bool * fkeep) - { struct tpax_dirent_buffer * dentbuf; struct tpax_dirent * cdent; @@ -183,8 +227,10 @@ static int tpax_archive_append_queue_item( cdent->fdat = fd; cdent->depth = depth; + cdent->flags = flags; cdent->nsize = needed; cdent->parent = parent; + cdent->prefix = prefix; memset(&cdent->dirent,0,offsetof(struct dirent,d_name)); @@ -510,7 +556,8 @@ static int tpax_archive_append_dir( if (dirent->d_type == DT_DIR) { if (tpax_archive_append_queue_item( dctx,dirent, - parent,unit,depth, + parent,0,unit,depth, + TPAX_ITEM_IMPLICIT, fd,&fkeep) < 0) return tpax_archive_append_ret( TPAX_NESTED_ERROR(dctx), @@ -598,6 +645,10 @@ int tpax_archive_append( for (++prefix; *prefix=='/'; prefix++) (void)0; + if (prefix) + if (!(prefix = tpax_append_prefix_item(dctx,prefix))) + return TPAX_BUFFER_ERROR(dctx); + /* append explicit item */ tpax_archive_append_impl(dctx,uctx,0,prefix,0);