diff options
Diffstat (limited to 'src/driver/tpax_driver_ctx.c')
-rw-r--r-- | src/driver/tpax_driver_ctx.c | 151 |
1 files changed, 149 insertions, 2 deletions
diff --git a/src/driver/tpax_driver_ctx.c b/src/driver/tpax_driver_ctx.c index dff6ef6..5593ec6 100644 --- a/src/driver/tpax_driver_ctx.c +++ b/src/driver/tpax_driver_ctx.c @@ -6,6 +6,7 @@ #define _DEFAULT_SOURCE 1 +#include <regex.h> #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -322,6 +323,109 @@ static void tpax_set_archive_block_size(struct tpax_common_ctx * cctx) cctx->blksize = TPAX_USTAR_BLOCK_SIZE; } +static int tpax_add_replstr( + struct argv_entry * entry, + struct tpax_replstr * replstr, + char ** mark) +{ + const char * src; + char * dst; + char sep; + int nsep; + + /* non-null separator character */ + if (!(sep = entry->arg[0])) + return -1; + + /* exactly three separator characters */ + for (nsep=1,src=&entry->arg[1]; *src; src++) { + if ((src[0] == '\\') && (src[1] == sep)) { + src++; + + } else if (src[0] == sep) { + nsep++; + } + } + + if (nsep != 3) + return -1; + + /* regexp */ + for (src=&entry->arg[1],dst=*mark; (*src != sep); src++) { + if ((src[0] == '\\') && (src[1] == sep)) + src++; + + *dst++ = *src; + } + + replstr->replarg = entry->arg; + replstr->replstr = ++dst; + replstr->regexp = *mark; + + /* replstr */ + for (++src; (*src != sep); src++) { + if ((src[0] == '\\') && (src[1] == sep)) + src++; + + *dst++ = *src; + } + + src++; + dst++; + + *mark = dst; + + /* flags */ + if (src[0] && src[1] && src[2]) + return -1; + + if (src[0] && (src[0] == src[1])) + return -1; + + if (src[0] && (src[0] != 'g') && (src[0] != 'p')) + return -1; + + if (src[0] && src[1] && (src[1] != 'g') && (src[1] != 'p')) + return -1; + + if (src[0] && ((src[0] == 'g') || (src[1] == 'g'))) + replstr->flags |= TPAX_REPL_GLOBAL; + + if (src[0] && ((src[0] == 'p') || (src[1] == 'p'))) + replstr->flags |= TPAX_REPL_PRINT; + + /* regex */ + if (regcomp(&replstr->regex,replstr->regexp,0)) { + replstr->regexp = 0; + return -1; + } + + return 0; +} + +static int tpax_init_replstr_vector( + struct tpax_driver_ctx_impl * ctx, + struct argv_meta * meta) +{ + struct argv_entry * entry; + struct tpax_replstr * replstr; + char * mark; + + if (!(replstr = ctx->replstrv)) + return 0; + + for (entry=meta->entries,mark=ctx->replstrs; entry->fopt || entry->arg; entry++) { + if (entry->tag == TAG_REPLSTR) { + if (tpax_add_replstr(entry,replstr,&mark) < 0) + return -1; + + replstr++; + } + } + + return 0; +} + static int tpax_driver_is_valid_keyval(struct argv_keyval * keyval) { (void)keyval; @@ -332,7 +436,9 @@ static struct tpax_driver_ctx_impl * tpax_driver_ctx_alloc( struct argv_meta * meta, const struct tpax_fd_ctx * fdctx, const struct tpax_common_ctx * cctx, - size_t nunits) + size_t nunits, + size_t nreplstr, + size_t sreplstr) { struct tpax_driver_ctx_alloc * ictx; size_t size; @@ -379,6 +485,19 @@ static struct tpax_driver_ctx_impl * tpax_driver_ctx_alloc( return 0; } + if (nreplstr && !(ictx->ctx.replstrv = calloc(++nreplstr,sizeof(*ictx->ctx.replstrv)))) { + free(ictx->ctx.keyvalv); + free(ictx); + return 0; + } + + if (sreplstr && !(ictx->ctx.replstrs = calloc(sreplstr,1))) { + free(ictx->ctx.replstrv); + free(ictx->ctx.keyvalv); + free(ictx); + return 0; + } + if ((pkeyval = ictx->ctx.keyvalv)) for (entry=meta->entries; entry->fopt || entry->arg; entry++) if (entry->keyv) @@ -474,6 +593,8 @@ int tpax_lib_get_driver_ctx( struct argv_keyval ** pkeyval; struct tpax_fd_ctx lfdctx; size_t nunits; + size_t nreplstr; + size_t sreplstr; const char * program; int fddst; const char * ch; @@ -497,6 +618,9 @@ int tpax_lib_get_driver_ctx( program = argv_program_name(argv[0]); memset(&cctx,0,sizeof(cctx)); + nreplstr = 0; + sreplstr = 0; + cctx.drvflags = flags; fddst = fdctx->fddst; @@ -581,6 +705,12 @@ int tpax_lib_get_driver_ctx( meta); break; + case TAG_REPLSTR: + sreplstr += strlen(entry->arg); + sreplstr++; + nreplstr++; + break; + case TAG_RECURSE: cctx.drvflags |= TPAX_DRIVER_DIR_MEMBER_RECURSE; break; @@ -751,13 +881,19 @@ int tpax_lib_get_driver_ctx( } /* driver ctx */ - if (!(ctx = tpax_driver_ctx_alloc(meta,fdctx,&cctx,nunits))) { + if (!(ctx = tpax_driver_ctx_alloc(meta,fdctx,&cctx,nunits,nreplstr,sreplstr))) { if (cctx.drvflags & TPAX_DRIVER_EXEC_MODE_COPY) close(fddst); return tpax_get_driver_ctx_fail(meta); } + /* replstr validation and vector initialization */ + if (tpax_init_replstr_vector(ctx,meta) < 0) { + tpax_lib_free_driver_ctx(&ctx->ctx); + return TPAX_ERROR; + } + /* keyval validation */ for (pkeyval=ctx->keyvalv; pkeyval && *pkeyval; pkeyval++) if (!tpax_driver_is_valid_keyval(*pkeyval)) @@ -781,6 +917,8 @@ static void tpax_free_driver_ctx_impl(struct tpax_driver_ctx_alloc * ictx) size_t size; char ** ppref; + struct tpax_replstr * replstrv; + for (; ictx->ctx.dirents; ) { next = ictx->ctx.dirents->next; size = ictx->ctx.dirents->size; @@ -789,6 +927,15 @@ static void tpax_free_driver_ctx_impl(struct tpax_driver_ctx_alloc * ictx) ictx->ctx.dirents = (struct tpax_dirent_buffer *)next; } + for (replstrv=ictx->ctx.replstrv; replstrv && replstrv->regexp; replstrv++) + regfree(&replstrv->regex); + + if (ictx->ctx.replstrv) + free(ictx->ctx.replstrv); + + if (ictx->ctx.replstrs) + free(ictx->ctx.replstrs); + if (ictx->ctx.keyvalv) free(ictx->ctx.keyvalv); |