/**************************************************************/
/* tpax: a topological pax implementation */
/* Copyright (C) 2020--2024 SysDeer Technologies, LLC */
/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */
/**************************************************************/
#ifndef TPAX_DRIVER_IMPL_H
#define TPAX_DRIVER_IMPL_H
#include <regex.h>
#include <stdint.h>
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <tpax/tpax.h>
#include <tpax/tpax_specs.h>
#include "tpax_dprintf_impl.h"
#include "argv/argv.h"
#define TPAX_OPTV_ELEMENTS 64
#define TPAX_DIRENT_BUFLEN 65536
#define TPAX_FILEIO_BUFLEN (4096 * 1024)
#define TPAX_DRIVER_EXEC_MODE_WRITE_COPY \
(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
#define TPAX_REPL_GLOBAL 0x01
#define TPAX_REPL_PRINT 0x02
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_REPLSTR,
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;
};
struct tpax_dirent_buffer {
struct tpax_dirent_buffer * next;
size_t size;
size_t nfree;
struct tpax_dirent * cdent;
struct tpax_dirent dbuf[];
};
struct tpax_replstr {
const char * replarg;
const char * replstr;
const char * regexp;
regex_t regex;
uint32_t flags;
};
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_replstr * replstrv;
char * replstrs;
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;
};
struct tpax_unit_ctx_impl {
const char * path;
struct tpax_unit_ctx uctx;
struct stat st;
off_t hpos;
off_t dpos;
const char * link;
char linkbuf[1024];
size_t hdrbuf[];
};
static inline struct tpax_driver_ctx_impl * tpax_get_driver_ictx(
const struct tpax_driver_ctx * dctx)
{
uintptr_t addr;
if (dctx) {
addr = (uintptr_t)dctx - offsetof(struct tpax_driver_ctx_impl,ctx);
return (struct tpax_driver_ctx_impl *)addr;
}
return 0;
}
static inline struct tpax_unit_ctx_impl * tpax_get_unit_ictx(
const struct tpax_unit_ctx * uctx)
{
struct tpax_unit_ctx_impl * ictx;
uintptr_t addr;
addr = (uintptr_t)uctx - offsetof(struct tpax_unit_ctx_impl,uctx);
ictx = (struct tpax_unit_ctx_impl *)addr;
return ictx;
}
static inline void * tpax_get_driver_anon_map_addr(
const struct tpax_driver_ctx * dctx,
size_t * size)
{
struct tpax_driver_ctx_impl * ictx = tpax_get_driver_ictx(dctx);
*size = ictx->bufsize;
return ictx->bufaddr;
}
static inline void * tpax_get_driver_getdents_buffer(
const struct tpax_driver_ctx * dctx)
{
struct tpax_driver_ctx_impl * ictx = tpax_get_driver_ictx(dctx);
return ictx->dirbuff;
}
static inline void tpax_driver_set_ectx(
const struct tpax_driver_ctx * dctx,
const struct tpax_unit_ctx * uctx,
const char * unit)
{
struct tpax_driver_ctx_impl * ictx;
ictx = tpax_get_driver_ictx(dctx);
ictx->euctx = uctx;
ictx->eunit = unit;
}
static inline int tpax_driver_fdin(const struct tpax_driver_ctx * dctx)
{
struct tpax_fd_ctx 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_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_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_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_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_lib_get_driver_fdctx(dctx,&fdctx);
return fdctx.fddst;
}
static inline off_t tpax_get_driver_cpos(const struct tpax_driver_ctx * dctx)
{
struct tpax_driver_ctx_impl * ictx;
ictx = tpax_get_driver_ictx(dctx);
return ictx->cpos;
}
static inline void tpax_set_driver_cpos(const struct tpax_driver_ctx * dctx, off_t cpos)
{
struct tpax_driver_ctx_impl * ictx;
ictx = tpax_get_driver_ictx(dctx);
ictx->cpos = cpos;
}
static inline struct tpax_dirent_buffer * tpax_get_driver_dirents(const struct tpax_driver_ctx * dctx)
{
struct tpax_driver_ctx_impl * ictx;
ictx = tpax_get_driver_ictx(dctx);
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;
ictx = tpax_get_unit_ictx(uctx);
return ictx->hpos;
}
static inline void tpax_set_unit_hpos(const struct tpax_unit_ctx * uctx, off_t hpos)
{
struct tpax_unit_ctx_impl * ictx;
ictx = tpax_get_unit_ictx(uctx);
ictx->hpos = hpos;
}
static inline off_t tpax_get_unit_dpos(const struct tpax_unit_ctx * uctx)
{
struct tpax_unit_ctx_impl * ictx;
ictx = tpax_get_unit_ictx(uctx);
return ictx->dpos;
}
static inline void tpax_set_unit_dpos(const struct tpax_unit_ctx * uctx, off_t dpos)
{
struct tpax_unit_ctx_impl * ictx;
ictx = tpax_get_unit_ictx(uctx);
ictx->dpos = dpos;
}
int tpax_update_queue_vector(const struct tpax_driver_ctx * dctx);
const char * tpax_queue_item_full_path(
const struct tpax_driver_ctx *,
const struct tpax_dirent *);
#endif