diff --git a/include/tpax/tpax.h b/include/tpax/tpax.h index 059dbac..5281ea1 100644 --- a/include/tpax/tpax.h +++ b/include/tpax/tpax.h @@ -147,6 +147,7 @@ tpax_api int tpax_set_driver_fdctx (struct tpax_driver_ctx *, const struct /* core api */ /* helper api */ +tpax_api int tpax_path_copy (char *, const char *, size_t, uint32_t, size_t *); /* utility api */ tpax_api int tpax_main (char **, char **, diff --git a/project/common.mk b/project/common.mk index 54f7d11..ca6bc81 100644 --- a/project/common.mk +++ b/project/common.mk @@ -2,6 +2,7 @@ API_SRCS = \ src/driver/tpax_amain.c \ src/driver/tpax_driver_ctx.c \ src/driver/tpax_unit_ctx.c \ + src/helper/tpax_path_copy.c \ src/logic/tpax_init_ustar_header.c \ src/output/tpax_output_error.c \ src/skin/tpax_skin_default.c \ diff --git a/project/tree.mk b/project/tree.mk index ab26f1e..548db6f 100644 --- a/project/tree.mk +++ b/project/tree.mk @@ -1,5 +1,6 @@ TREE_DIRS = bin lib src \ src/driver \ + src/helper \ src/internal \ src/logic \ src/output \ diff --git a/src/helper/tpax_path_copy.c b/src/helper/tpax_path_copy.c new file mode 100644 index 0000000..0df6c17 --- /dev/null +++ b/src/helper/tpax_path_copy.c @@ -0,0 +1,86 @@ +/******************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/******************************************************/ + +#include +#include +#include +#include +#include + +#include +#include "tpax_driver_impl.h" + +int tpax_path_copy( + char * dstpath, + const char * srcpath, + size_t bufsize, + uint32_t flags, + size_t * nwritten) +{ + const char * src; + char * dst; + char * cap; + + if (!bufsize) { + errno = ENOBUFS; + return -1; + } + + src = srcpath; + dst = dstpath; + cap = &dst[bufsize]; + + if ((src[0] == '/') && (src[1] == '/') && (src[2] != '/')) { + *dst++ = *src++; + *dst++ = *src++; + } + + if (flags & TPAX_DRIVER_PURE_PATH_OUTPUT) + if ((src[0] == '.') && (src[1] == '/')) + for (++src; *src=='/'; src++) + (void)0; + + for (; *src; ) { + if ((src[0] == '.') && (src[1] == '.')) { + if ((src[2] == '/') || (src[2] == '\0')) { + if (flags & TPAX_DRIVER_STRICT_PATH_INPUT) { + errno = EINVAL; + return -1; + } + } + } + + if (flags & TPAX_DRIVER_PURE_PATH_OUTPUT) { + if ((src[0] == '.') && (src[1] == '/') && (src[-1] == '/')) { + for (++src; *src=='/'; src++) + (void)0; + + } else if ((src[0] == '/')) { + for (src++; *src=='/'; src++) + (void)0; + + *dst++ = '/'; + + } else { + *dst++ = *src++; + } + } else { + *dst++ = *src++; + } + + if (dst == cap) { + errno = ENOBUFS; + return -1; + } + } + + if (nwritten) + *nwritten = dst - dstpath; + + *dst = '\0'; + + return 0; +}