Blob Blame History Raw
/**************************************************************/
/*  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