summaryrefslogtreecommitdiff
path: root/src/logic/tpax_queue_vector.c
blob: cae4da0954680a7ac4f40ebc755ab20eb75d0d0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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;
}