diff options
Diffstat (limited to 'src/logic/tpax_queue_vector.c')
-rw-r--r-- | src/logic/tpax_queue_vector.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/logic/tpax_queue_vector.c b/src/logic/tpax_queue_vector.c new file mode 100644 index 0000000..cae4da0 --- /dev/null +++ b/src/logic/tpax_queue_vector.c @@ -0,0 +1,101 @@ +/**************************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/**************************************************************/ + +#include <stdint.h> +#include <stdlib.h> + +#include <tpax/tpax.h> +#include "tpax_driver_impl.h" +#include "tpax_errinfo_impl.h" +#include "tpax_visibility_impl.h" + +#define TPAX_MAX_DEPTH 512 + +tpax_hidden const char * tpax_queue_item_full_path( + const struct tpax_driver_ctx * dctx, + const struct tpax_dirent * cdent) +{ + char * ch; + char * pathbuf; + const struct tpax_dirent * pparent; + const struct tpax_dirent ** pdirent; + const struct tpax_dirent * dirstck[TPAX_MAX_DEPTH]; + + if (cdent->depth >= TPAX_MAX_DEPTH) + return 0; + + ch = pathbuf = (tpax_get_driver_ictx(dctx))->dirbuff; + + for (pparent=cdent,pdirent=dirstck; pparent; pparent=pparent->parent) + *pdirent++ = pparent; + + *pdirent-- = 0; + + if (pdirent[0]->prefix) + ch += sprintf(ch,"%s",pdirent[0]->prefix); + + for (; pdirent > dirstck; ) { + if (!(pdirent[0]->flags & TPAX_ITEM_SYMLINK)) + ch += sprintf(ch,"%s/",pdirent[0]->dirent.d_name); + + pdirent--; + } + + if (pdirent[0]->flags & TPAX_ITEM_SYMLINK) { + *--ch = '\0'; + } else { + sprintf(ch,"%s",pdirent[0]->dirent.d_name); + } + + return pathbuf; +} + +tpax_hidden int tpax_update_queue_vector(const struct tpax_driver_ctx * dctx) +{ + uintptr_t addr; + struct tpax_driver_ctx_impl * ictx; + struct tpax_dirent_buffer * dentbuf; + struct tpax_dirent ** direntv; + struct tpax_dirent * cdent; + struct tpax_dirent * cnext; + size_t arrsize; + + /* driver */ + ictx = tpax_get_driver_ictx(dctx); + + /* vector alloc */ + if (ictx->direntv) + free(ictx->direntv); + + arrsize = ictx->nqueued + 1; + + if (!(ictx->direntv = calloc(arrsize,sizeof(struct tpax_dirent *)))) + return TPAX_SYSTEM_ERROR(dctx); + + if (ictx->nqueued == 0) + return 0; + + /* queue vector */ + dentbuf = tpax_get_driver_dirents(dctx); + cdent = dentbuf->dbuf; + + for (direntv=ictx->direntv; cdent; direntv++) { + *direntv = cdent; + + addr = (uintptr_t)cdent; + addr += cdent->nsize; + cnext = (struct tpax_dirent *)addr; + + if (cnext == dentbuf->cdent) { + dentbuf = dentbuf->next; + cnext = dentbuf ? dentbuf->dbuf : 0; + } + + cdent = cnext; + } + + return 0; +} |