diff options
Diffstat (limited to 'src/internal')
-rw-r--r-- | src/internal/argv/argv.h | 281 | ||||
-rw-r--r-- | src/internal/tpax_dprintf_impl.c | 6 | ||||
-rw-r--r-- | src/internal/tpax_driver_impl.h | 73 | ||||
-rw-r--r-- | src/internal/tpax_errinfo_impl.c | 5 | ||||
-rw-r--r-- | src/internal/tpax_errinfo_impl.h | 2 | ||||
-rw-r--r-- | src/internal/tpax_ftime_impl.c | 48 | ||||
-rw-r--r-- | src/internal/tpax_ftime_impl.h | 24 | ||||
-rw-r--r-- | src/internal/tpax_getdents_impl.h | 2 | ||||
-rw-r--r-- | src/internal/tpax_readlink_impl.h | 2 | ||||
-rw-r--r-- | src/internal/tpax_tmpfile_impl.c | 6 | ||||
-rw-r--r-- | src/internal/tpax_visibility_impl.h | 26 |
11 files changed, 421 insertions, 54 deletions
diff --git a/src/internal/argv/argv.h b/src/internal/argv/argv.h index 87c60d2..8efedda 100644 --- a/src/internal/argv/argv.h +++ b/src/internal/argv/argv.h @@ -13,6 +13,7 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> +#include <ctype.h> #include <unistd.h> #define ARGV_VERBOSITY_NONE 0x00 @@ -57,16 +58,27 @@ #define ARGV_OPTION_HYBRID_EQUAL 0x04 #define ARGV_OPTION_HYBRID_COMMA 0x08 #define ARGV_OPTION_HYBRID_JOINED 0x10 + +#define ARGV_OPTION_KEYVAL_PAIR 0X20 +#define ARGV_OPTION_KEYVAL_ARRAY 0X40 +#define ARGV_OPTION_KEYVAL_MASK (ARGV_OPTION_KEYVAL_PAIR \ + | ARGV_OPTION_KEYVAL_ARRAY) + #define ARGV_OPTION_HYBRID_CIRCUS (ARGV_OPTION_HYBRID_SPACE \ | ARGV_OPTION_HYBRID_JOINED) + #define ARGV_OPTION_HYBRID_DUAL (ARGV_OPTION_HYBRID_SPACE \ | ARGV_OPTION_HYBRID_EQUAL) + #define ARGV_OPTION_HYBRID_SWITCH (ARGV_OPTION_HYBRID_ONLY \ | ARGV_OPTION_HYBRID_SPACE \ | ARGV_OPTION_HYBRID_EQUAL \ | ARGV_OPTION_HYBRID_COMMA \ | ARGV_OPTION_HYBRID_JOINED) +#define ARGV_KEYVAL_ASSIGN 0x01 +#define ARGV_KEYVAL_OVERRIDE 0x02 + enum argv_optarg { ARGV_OPTARG_NONE, ARGV_OPTARG_REQUIRED, @@ -92,6 +104,9 @@ enum argv_error { ARGV_ERROR_HYBRID_SPACE, ARGV_ERROR_HYBRID_EQUAL, ARGV_ERROR_HYBRID_COMMA, + ARGV_ERROR_KEYVAL_KEY, + ARGV_ERROR_KEYVAL_VALUE, + ARGV_ERROR_KEYVAL_ALLOC, }; struct argv_option { @@ -105,13 +120,20 @@ struct argv_option { const char * description; }; +struct argv_keyval { + const char * keyword; + const char * value; + int flags; +}; + struct argv_entry { - const char * arg; - int tag; - bool fopt; - bool fval; - bool fnoscan; - enum argv_error errcode; + const char * arg; + struct argv_keyval * keyv; + int tag; + bool fopt; + bool fval; + bool fnoscan; + enum argv_error errcode; }; struct argv_meta { @@ -129,6 +151,7 @@ struct argv_ctx { const char * errch; const struct argv_option * erropt; const char * program; + size_t keyvlen; }; #ifdef ARGV_DRIVER @@ -136,6 +159,8 @@ struct argv_ctx { struct argv_meta_impl { char ** argv; char * strbuf; + char * keyvbuf; + char * keyvmark; struct argv_meta meta; }; @@ -305,12 +330,131 @@ static inline const struct argv_option * option_from_tag( return 0; } +static inline int argv_scan_keyval_array(struct argv_meta_impl * meta, struct argv_entry * entry) +{ + const char * ch; + char * dst; + int ncomma; + int cint; + struct argv_keyval * keyv; + + /* count key[val] elements, assume no comma after last element */ + for (ch=entry->arg,ncomma=1; *ch; ch++) { + if ((ch[0]=='\\') && (ch[1]==',')) { + ch++; + + } else if ((ch[0]==',')) { + ncomma++; + } + } + + /* keyval string buffer */ + dst = meta->keyvmark; + + /* allocate keyval array */ + if (!(entry->keyv = calloc(ncomma+1,sizeof(*entry->keyv)))) + return ARGV_ERROR_KEYVAL_ALLOC; + + /* create keyval array */ + entry->keyv->keyword = dst; + + for (ch=entry->arg,keyv=entry->keyv; *ch; ch++) { + if ((ch[0]=='\\') && (ch[1]==',')) { + *dst++ = ','; + ch++; + + } else if ((ch[0]==':') && (ch[1]=='=')) { + if (!keyv->keyword[0]) + return ARGV_ERROR_KEYVAL_KEY; + + keyv->flags = ARGV_KEYVAL_OVERRIDE; + keyv->value = ++dst; + ch++; + + } else if ((ch[0]=='=')) { + if (!keyv->keyword[0]) + return ARGV_ERROR_KEYVAL_KEY; + + keyv->flags = ARGV_KEYVAL_ASSIGN; + keyv->value = ++dst; + + } else if ((ch[0]==',')) { + for (; isblank(cint = ch[1]); ) + ch++; + + if (ch[1]) { + keyv++; + keyv->keyword = ++dst; + } + } else { + *dst++ = *ch; + } + } + + /* keyval string buffer */ + meta->keyvmark = ++dst; + + return ARGV_ERROR_OK; +} + +static inline int argv_scan_keyval_pair(struct argv_meta_impl * meta, struct argv_entry * entry) +{ + const char * ch; + char * dst; + struct argv_keyval * keyv; + + /* keyval string buffer */ + dst = meta->keyvmark; + + /* allocate keyval array */ + if (!(entry->keyv = calloc(2,sizeof(*entry->keyv)))) + return ARGV_ERROR_KEYVAL_ALLOC; + + /* create keyval array */ + entry->keyv->keyword = dst; + + for (ch=entry->arg,keyv=entry->keyv; *ch && !keyv->flags; ch++) { + if ((ch[0]=='\\') && (ch[1]==',')) { + *dst++ = ','; + ch++; + + } else if ((ch[0]==':') && (ch[1]=='=')) { + if (!keyv->keyword[0]) + return ARGV_ERROR_KEYVAL_KEY; + + keyv->flags = ARGV_KEYVAL_OVERRIDE; + keyv->value = ++dst; + ch++; + + } else if ((ch[0]=='=')) { + if (!keyv->keyword[0]) + return ARGV_ERROR_KEYVAL_KEY; + + keyv->flags = ARGV_KEYVAL_ASSIGN; + keyv->value = ++dst; + + } else { + *dst++ = *ch; + } + } + + for (; *ch; ) + *dst++ = *ch++; + + /* keyval string buffer */ + meta->keyvmark = ++dst; + + return ARGV_ERROR_OK; +} + static void argv_scan( char ** argv, const struct argv_option ** optv, struct argv_ctx * ctx, struct argv_meta * meta) { + struct argv_meta_impl * imeta; + uintptr_t addr; char ** parg; const char * ch; const char * val; @@ -324,6 +468,9 @@ static void argv_scan( bool fhybrid; bool fnoscan; + addr = (uintptr_t)meta - offsetof(struct argv_meta_impl,meta); + imeta = (struct argv_meta_impl *)addr; + parg = &argv[1]; ch = *parg; ferr = ARGV_ERROR_OK; @@ -495,13 +642,20 @@ static void argv_scan( if (!option && !ctx->unitidx) ctx->unitidx = parg - argv; + if (ferr == ARGV_ERROR_OK) + if (option && (option->flags & ARGV_OPTION_KEYVAL_MASK)) + if (ctx->mode == ARGV_MODE_SCAN) + ctx->keyvlen += strlen(ch) + 1; + if (ferr != ARGV_ERROR_OK) { ctx->errcode = ferr; ctx->errch = ctx->errch ? ctx->errch : ch; ctx->erropt = option; ctx->erridx = parg - argv; return; - } else if (ctx->mode == ARGV_MODE_SCAN) { + } + + if (ctx->mode == ARGV_MODE_SCAN) { if (!fnoscan) ctx->nentries++; else if (fval) @@ -511,12 +665,12 @@ static void argv_scan( parg++; ch = *parg; } + } else if (ctx->mode == ARGV_MODE_COPY) { if (fnoscan) { if (fval) { mentry->arg = ch; mentry->fnoscan = true; - mentry++; } parg++; @@ -526,7 +680,6 @@ static void argv_scan( mentry->tag = option->tag; mentry->fopt = true; mentry->fval = fval; - mentry++; if (fval) { parg++; @@ -534,11 +687,28 @@ static void argv_scan( } } else { mentry->arg = ch; - mentry++; parg++; ch = *parg; } } + + if (option && (option->flags & ARGV_OPTION_KEYVAL_PAIR)) + if (ctx->mode == ARGV_MODE_COPY) + ferr = argv_scan_keyval_pair(imeta,mentry); + + if (option && (option->flags & ARGV_OPTION_KEYVAL_ARRAY)) + if (ctx->mode == ARGV_MODE_COPY) + ferr = argv_scan_keyval_array(imeta,mentry); + + if (ferr != ARGV_ERROR_OK) { + ctx->errcode = ferr; + ctx->errch = ctx->errch ? ctx->errch : ch; + ctx->erropt = option; + ctx->erridx = parg - argv; + return; + } + + mentry++; } } @@ -663,6 +833,14 @@ static void argv_show_error(int fd, struct argv_ctx * ctx) break; + case ARGV_ERROR_KEYVAL_KEY: + argv_dprintf(fd,"illegal key detected in keyval argument\n"); + break; + + case ARGV_ERROR_KEYVAL_VALUE: + argv_dprintf(fd,"illegal value detected in keyval argument\n"); + break; + case ARGV_ERROR_INTERNAL: argv_dprintf(fd,"internal error"); break; @@ -678,8 +856,10 @@ static void argv_show_status( struct argv_ctx * ctx, struct argv_meta * meta) { + int i; int argc; char ** argv; + struct argv_keyval * keyv; struct argv_entry * entry; const struct argv_option * option; char short_name[2] = {0}; @@ -698,7 +878,7 @@ static void argv_show_status( argv_dprintf(fd,"argv[%d]: %s\n",argc,*argv); argv_dprintf(fd,"\n\nparsed entries:\n"); - for (entry=meta->entries; entry->arg || entry->fopt; entry++) + for (entry=meta->entries; entry->arg || entry->fopt; entry++) { if (entry->fopt) { option = option_from_tag(optv,entry->tag); short_name[0] = option->short_name; @@ -709,14 +889,48 @@ static void argv_show_status( else argv_dprintf(fd,"[-%s,--%s]\n", short_name,option->long_name); - } else + + if (entry->keyv) { + for (i=0,keyv=entry->keyv; keyv->keyword; i++,keyv++) { + switch (keyv->flags) { + case ARGV_KEYVAL_ASSIGN: + argv_dprintf(fd,"\tkeyval[%d]: <%s>=%s\n", + i,keyv->keyword,keyv->value); + break; + + case ARGV_KEYVAL_OVERRIDE: + argv_dprintf(fd,"\tkeyval[%d]: <%s>:=%s\n", + i,keyv->keyword,keyv->value); + break; + + default: + argv_dprintf(fd,"\tkeyval[%d]: <%s>\n", + i,keyv->keyword); + break; + } + } + } + } else { argv_dprintf(fd,"<program arg> := %s\n",entry->arg); + } + } argv_dprintf(fd,"\n\n"); } static struct argv_meta * argv_free_impl(struct argv_meta_impl * imeta) { + struct argv_entry * entry; + void * addr; + + if (imeta->keyvbuf) + for (entry=imeta->meta.entries; entry->fopt || entry->arg; entry++) + if (entry->keyv) + free((addr = entry->keyv)); + + if (imeta->keyvbuf) + free(imeta->keyvbuf); + if (imeta->argv) free(imeta->argv); @@ -750,7 +964,8 @@ static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx) if (!(imeta->argv = calloc(argc+1,sizeof(char *)))) return argv_free_impl(imeta); - else if (!(imeta->strbuf = calloc(1,size+1))) + + if (!(imeta->strbuf = calloc(1,size+1))) return argv_free_impl(imeta); for (i=0,dst=imeta->strbuf; i<argc; i++) { @@ -760,15 +975,27 @@ static struct argv_meta * argv_alloc(char ** argv, struct argv_ctx * ctx) } imeta->meta.argv = imeta->argv; - } else + } else { imeta->meta.argv = argv; + } - if (!(imeta->meta.entries = calloc( - ctx->nentries+1, - sizeof(struct argv_entry)))) + imeta->meta.entries = calloc( + ctx->nentries+1, + sizeof(struct argv_entry)); + + if (!imeta->meta.entries) return argv_free_impl(imeta); - else - return &imeta->meta; + + if (ctx->keyvlen) { + imeta->keyvbuf = calloc( + ctx->keyvlen, + sizeof(char)); + + if (!(imeta->keyvmark = imeta->keyvbuf)) + return argv_free_impl(imeta); + } + + return &imeta->meta; } static struct argv_meta * argv_get( @@ -778,7 +1005,7 @@ static struct argv_meta * argv_get( int fd) { struct argv_meta * meta; - struct argv_ctx ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0}; + struct argv_ctx ctx = {flags,ARGV_MODE_SCAN,0,0,0,0,0,0,0,0}; argv_scan(argv,optv,&ctx,0); @@ -833,6 +1060,7 @@ static void argv_usage_impl( { const struct argv_option ** optv; const struct argv_option * option; + int nlong; bool fshort,flong,fboth; size_t len,optlen,desclen; char cache; @@ -865,7 +1093,7 @@ static void argv_usage_impl( if (header) argv_dprintf(fd,"%s",header); - for (optlen=0,optv=options; *optv; optv++) { + for (optlen=0,nlong=0,optv=options; *optv; optv++) { option = *optv; /* indent + comma */ @@ -884,6 +1112,11 @@ static void argv_usage_impl( /* optlen */ if (len > optlen) optlen = len; + + /* long (vs. hybrid-only) option? */ + if (option->long_name) + if (!(option->flags & ARGV_OPTION_HYBRID_ONLY)) + nlong++; } if (optlen >= optcap) { @@ -916,7 +1149,11 @@ static void argv_usage_impl( /* long/hybrid option prefix (-/--) */ prefix = option->flags & ARGV_OPTION_HYBRID_ONLY - ? " -" : "--"; + ? " -" : " --"; + + /* avoid extra <stace> when all long opts are hybrid-only */ + if (nlong == 0) + prefix++; /* option string */ if (fboth && option->short_name && option->long_name) diff --git a/src/internal/tpax_dprintf_impl.c b/src/internal/tpax_dprintf_impl.c index b8d2b0b..2bc83a8 100644 --- a/src/internal/tpax_dprintf_impl.c +++ b/src/internal/tpax_dprintf_impl.c @@ -1,6 +1,6 @@ /**************************************************************/ /* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ @@ -10,7 +10,9 @@ #include <unistd.h> #include <errno.h> -int tpax_dprintf(int fd, const char * fmt, ...) +#include "tpax_visibility_impl.h" + +tpax_hidden int tpax_dprintf(int fd, const char * fmt, ...) { int ret; int cnt; diff --git a/src/internal/tpax_driver_impl.h b/src/internal/tpax_driver_impl.h index 5fabb0a..d340748 100644 --- a/src/internal/tpax_driver_impl.h +++ b/src/internal/tpax_driver_impl.h @@ -1,6 +1,6 @@ /**************************************************************/ /* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ @@ -26,27 +26,42 @@ (TPAX_DRIVER_EXEC_MODE_WRITE | \ TPAX_DRIVER_EXEC_MODE_COPY) +#define TPAX_ITEM_EXPLICIT 0X1 +#define TPAX_ITEM_IMPLICIT 0X2 +#define TPAX_ITEM_SYMLINK 0X4 +#define TPAX_ITEM_NAMEREF 0x8 + extern const struct argv_option tpax_default_options[]; enum app_tags { TAG_HELP, TAG_VERSION, + TAG_VERBOSE, TAG_LIST, TAG_READ, TAG_WRITE, TAG_COPY, + TAG_FILE, TAG_FORMAT, TAG_BLKSIZE, + TAG_OPTIONS, TAG_RECURSE, TAG_NORECURSE, TAG_STRICT_PATH, TAG_PURE_PATH, + TAG_PRESERVE_ATIME, + TAG_PAX_SYMLINK_ARGS, + TAG_PAX_SYMLINK_ITEMS, + TAG_STRICT_DEVICE_ID, }; struct tpax_dirent { int fdat; int depth; + int flags; + dev_t stdev; size_t nsize; + const char * prefix; const struct tpax_dirent * parent; struct dirent dirent; }; @@ -60,19 +75,28 @@ struct tpax_dirent_buffer { }; struct tpax_driver_ctx_impl { + const char * file; struct tpax_common_ctx cctx; struct tpax_driver_ctx ctx; struct tpax_fd_ctx fdctx; const struct tpax_unit_ctx * euctx; const char * eunit; + struct argv_keyval ** keyvalv; struct tpax_error_info ** errinfp; 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 ** direntv; struct tpax_dirent_buffer * dirents; + struct tpax_dirent * dirmark; void * dirbuff; void * bufaddr; size_t bufsize; + size_t nqueued; off_t cpos; }; @@ -143,42 +167,42 @@ static inline void tpax_driver_set_ectx( static inline int tpax_driver_fdin(const struct tpax_driver_ctx * dctx) { struct tpax_fd_ctx fdctx; - tpax_get_driver_fdctx(dctx,&fdctx); + tpax_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fdin; } static inline int tpax_driver_fdout(const struct tpax_driver_ctx * dctx) { struct tpax_fd_ctx fdctx; - tpax_get_driver_fdctx(dctx,&fdctx); + tpax_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fdout; } static inline int tpax_driver_fderr(const struct tpax_driver_ctx * dctx) { struct tpax_fd_ctx fdctx; - tpax_get_driver_fdctx(dctx,&fdctx); + tpax_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fderr; } static inline int tpax_driver_fdlog(const struct tpax_driver_ctx * dctx) { struct tpax_fd_ctx fdctx; - tpax_get_driver_fdctx(dctx,&fdctx); + tpax_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fdlog; } static inline int tpax_driver_fdcwd(const struct tpax_driver_ctx * dctx) { struct tpax_fd_ctx fdctx; - tpax_get_driver_fdctx(dctx,&fdctx); + tpax_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fdcwd; } static inline int tpax_driver_fddst(const struct tpax_driver_ctx * dctx) { struct tpax_fd_ctx fdctx; - tpax_get_driver_fdctx(dctx,&fdctx); + tpax_lib_get_driver_fdctx(dctx,&fdctx); return fdctx.fddst; } @@ -203,6 +227,21 @@ static inline struct tpax_dirent_buffer * tpax_get_driver_dirents(const struct t return ictx->dirents; } +static inline struct tpax_dirent * tpax_get_driver_dirmark(const struct tpax_driver_ctx * dctx) +{ + struct tpax_driver_ctx_impl * ictx; + ictx = tpax_get_driver_ictx(dctx); + return ictx->dirmark; +} + +static inline void tpax_set_driver_dirmark(const struct tpax_driver_ctx * dctx, struct tpax_dirent * dirent) +{ + struct tpax_driver_ctx_impl * ictx; + ictx = tpax_get_driver_ictx(dctx); + ictx->dirmark = dirent; + ictx->nqueued++; +} + static inline off_t tpax_get_unit_hpos(const struct tpax_unit_ctx * uctx) { struct tpax_unit_ctx_impl * ictx; @@ -231,22 +270,10 @@ static inline void tpax_set_unit_dpos(const struct tpax_unit_ctx * uctx, off_t d ictx->dpos = dpos; } -static inline ssize_t tpax_get_archive_block_size(const struct tpax_driver_ctx * dctx) -{ - if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_PAX) - return TPAX_PAX_BLOCK_SIZE; - - else if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_CPIO) - return TPAX_CPIO_BLOCK_SIZE; - - else if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_USTAR) - return TPAX_USTAR_BLOCK_SIZE; +int tpax_update_queue_vector(const struct tpax_driver_ctx * dctx); - else if (dctx->cctx->drvflags & TPAX_DRIVER_WRITE_FORMAT_RUSTAR) - return TPAX_USTAR_BLOCK_SIZE; - - else - return 0; -} +const char * tpax_queue_item_full_path( + const struct tpax_driver_ctx *, + const struct tpax_dirent *); #endif diff --git a/src/internal/tpax_errinfo_impl.c b/src/internal/tpax_errinfo_impl.c index 5fd2247..50a99a5 100644 --- a/src/internal/tpax_errinfo_impl.c +++ b/src/internal/tpax_errinfo_impl.c @@ -1,14 +1,15 @@ /**************************************************************/ /* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ #include <tpax/tpax.h> #include "tpax_driver_impl.h" #include "tpax_errinfo_impl.h" +#include "tpax_visibility_impl.h" -int tpax_record_error( +tpax_hidden int tpax_record_error( const struct tpax_driver_ctx * dctx, int esyscode, int elibcode, diff --git a/src/internal/tpax_errinfo_impl.h b/src/internal/tpax_errinfo_impl.h index 99b416b..e8151c5 100644 --- a/src/internal/tpax_errinfo_impl.h +++ b/src/internal/tpax_errinfo_impl.h @@ -1,6 +1,6 @@ /**************************************************************/ /* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ diff --git a/src/internal/tpax_ftime_impl.c b/src/internal/tpax_ftime_impl.c new file mode 100644 index 0000000..19c6d7b --- /dev/null +++ b/src/internal/tpax_ftime_impl.c @@ -0,0 +1,48 @@ +/**************************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/**************************************************************/ + +#include <time.h> +#include <sys/time.h> +#include <sys/stat.h> + +#include "tpax_ftime_impl.h" +#include "tpax_driver_impl.h" +#include "tpax_visibility_impl.h" + +tpax_hidden void tpax_ftime_restore( + const struct tpax_driver_ctx * dctx, + int fd, + const struct stat * refst) +{ + struct timespec ts[2]; + + if (dctx->cctx->drvflags & TPAX_DRIVER_PRESERVE_ATIME) { + ts[0].tv_sec = refst->st_atim.tv_sec; + ts[0].tv_nsec = refst->st_atim.tv_nsec; + } else { + ts[0].tv_nsec = UTIME_OMIT; + } + + if (dctx->cctx->drvflags & TPAX_DRIVER_PRESERVE_MTIME) { + ts[1].tv_sec = refst->st_mtim.tv_sec; + ts[1].tv_nsec = refst->st_mtim.tv_nsec; + } else { + ts[1].tv_nsec = UTIME_OMIT; + } + + if ((ts[0].tv_nsec != UTIME_OMIT) || (ts[1].tv_nsec != UTIME_OMIT)) { + futimens(fd,ts); + } +} + +tpax_hidden void tpax_ftime_restore_and_close( + const struct tpax_driver_ctx * dctx, + int fd, + const struct stat * refst) +{ + tpax_ftime_restore(dctx,fd,refst); + close(fd); +} diff --git a/src/internal/tpax_ftime_impl.h b/src/internal/tpax_ftime_impl.h new file mode 100644 index 0000000..2d0e981 --- /dev/null +++ b/src/internal/tpax_ftime_impl.h @@ -0,0 +1,24 @@ +/**************************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/**************************************************************/ + +#ifndef TPAX_FTIME_IMPL_H +#define TPAX_FTIME_IMPL_H + +#include <time.h> +#include <sys/time.h> +#include <sys/stat.h> + +#include "tpax_driver_impl.h" + +void tpax_ftime_restore( + const struct tpax_driver_ctx *, + int fd, const struct stat *); + +void tpax_ftime_restore_and_close( + const struct tpax_driver_ctx *, + int fd, const struct stat *); + +#endif diff --git a/src/internal/tpax_getdents_impl.h b/src/internal/tpax_getdents_impl.h index 42b9da0..2f46d63 100644 --- a/src/internal/tpax_getdents_impl.h +++ b/src/internal/tpax_getdents_impl.h @@ -1,6 +1,6 @@ /**************************************************************/ /* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ diff --git a/src/internal/tpax_readlink_impl.h b/src/internal/tpax_readlink_impl.h index d6c5580..e2febe1 100644 --- a/src/internal/tpax_readlink_impl.h +++ b/src/internal/tpax_readlink_impl.h @@ -1,6 +1,6 @@ /**************************************************************/ /* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ diff --git a/src/internal/tpax_tmpfile_impl.c b/src/internal/tpax_tmpfile_impl.c index 9dd9d40..aa78e40 100644 --- a/src/internal/tpax_tmpfile_impl.c +++ b/src/internal/tpax_tmpfile_impl.c @@ -1,6 +1,6 @@ /**************************************************************/ /* tpax: a topological pax implementation */ -/* Copyright (C) 2020--2021 SysDeer Technologies, LLC */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ @@ -14,6 +14,8 @@ #include <stdio.h> #include <inttypes.h> +#include "tpax_visibility_impl.h" + #define PPRIX64 "%"PRIx64 /* mkostemp might be guarded by non-standard macros */ @@ -55,7 +57,7 @@ static int tpax_mkostemp(char * tmplate) return fd; } -int tpax_tmpfile(void) +tpax_hidden int tpax_tmpfile(void) { int fd; void * addr; diff --git a/src/internal/tpax_visibility_impl.h b/src/internal/tpax_visibility_impl.h new file mode 100644 index 0000000..6812494 --- /dev/null +++ b/src/internal/tpax_visibility_impl.h @@ -0,0 +1,26 @@ +#ifndef TPAX_VISIBILITY_IMPL_H +#define TPAX_VISIBILITY_IMPL_H + +/**********************************************************************/ +/* PE targets: __dllexport suffices for the purpose of exporting only */ +/* the desired subset of global symbols; this makes the visibility */ +/* attribute not only redundant, but also tricky if not properly */ +/* supported by the toolchain. */ +/* */ +/* When targeting Midipix, __PE__, __dllexport and __dllimport are */ +/* always defined by the toolchain. Otherwise, the absnece of these */ +/* macros has been detected by sofort's ccenv.sh during ./configure, */ +/* and they have accordingly been added to CFLAGS_OS. */ +/**********************************************************************/ + +#ifdef __PE__ +#define tpax_hidden +#else +#ifdef _ATTR_VISIBILITY_HIDDEN +#define tpax_hidden _ATTR_VISIBILITY_HIDDEN +#else +#define tpax_hidden +#endif +#endif + +#endif |