From f7a1c5dacbb04001bafc5515373385fc2063f04f Mon Sep 17 00:00:00 2001 From: Chloe M Date: Mon, 27 Jul 2026 22:56:42 -0400 Subject: packer: Introduce idata_desc, data_desc and tables This commit introduces three kinds of primitives: Internal data descriptors (idata_desc), embeddable data descriptors (data_desc) and data descriptor tables. The internal data descriptors are used by the packer to keep state and link information while the embeddable data descriptors mirror more closely to what will actually be on disk. There is a special %root% entry which should offset into a root file containing information about the archive as a whole. Signed-off-by: Chloe M --- core/rdar.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) (limited to 'core/rdar.c') diff --git a/core/rdar.c b/core/rdar.c index a5f3b48..2cd1e66 100644 --- a/core/rdar.c +++ b/core/rdar.c @@ -4,13 +4,27 @@ */ #define _DEFAULT_SOURCE +#include #include #include #include #include +#include #include #include +/* Forward declarations */ +struct idata_desc; + +/* Data descriptor constants */ +#define RDAR_MAX_PATHLEN 32 +#define RDAR_MAGIC ">RDAR!" +#define RDAR_MAGIC_LEN 6 + +/* Data descriptor file flags */ +#define DATA_ROOT (1 << 0) /* Is root data descriptor */ +#define DATA_AVL (1 << 1) /* Available to consumer software; not touched by us */ + /* Version conversion macros */ #define VERSION_U16(MAJOR, MINOR) \ (((MINOR) << 8) | (MAJOR)) @@ -19,6 +33,10 @@ #define VERSION_MINOR(VERSION) \ (((VERSION) >> 8) & 0xFF) +/* Pushes idata descriptor to table */ +#define IDATA_PUSH(IDATA_P) \ + TAILQ_INSERT_TAIL(&d_desc_table, (IDATA_P), link); + /* * Software version * @@ -33,6 +51,36 @@ /* Globals */ static const char *input_dir = NULL; static const char *output_path = NULL; +static TAILQ_HEAD(, idata_desc) d_desc_table; + +/* + * A data descriptor holds information about a specific + * file along with an offset to which it is located at + * in the offset. + * + * @magic: Format magic + * @path: File path + * @off: File data offset + * @flags: File flags + */ +struct data_desc { + char magic[RDAR_MAGIC_LEN]; + char path[RDAR_MAX_PATHLEN]; + off_t off; + uint16_t flags; +}; + +/* + * Internal data descriptor, used to hold data + * before being flushed to the archive + * + * @data: Actual data descriptor + * @link: TAILQ link + */ +struct idata_desc { + struct data_desc data; + TAILQ_ENTRY(idata_desc) link; +}; static void help(void) @@ -54,11 +102,84 @@ version(void) printf("Version v%d.%d\n", Major, Minor); } +/* + * Allocate an internal data descriptor + * + * @path: Path of file + */ +static struct idata_desc * +idata_from_file(const char *path) +{ + struct idata_desc *idata_desc; + struct data_desc *data_desc; + size_t path_len; + + path_len = strlen(path); + if (path_len >= RDAR_MAX_PATHLEN - 1) { + printf("fatal: path '%s' is too long!\n", path); + return NULL; + } + + idata_desc = malloc(sizeof(*idata_desc)); + if (idata_desc == NULL) { + printf("fatal: failed to allocate idata_desc\n"); + printf("* last file processed: %s\n", path); + return NULL; + } + + /* Initialize the data descriptor */ + data_desc = &idata_desc->data; + memcpy(data_desc->magic, RDAR_MAGIC, RDAR_MAGIC_LEN); + memcpy(data_desc->path, path, path_len); + data_desc->path[path_len] = '\0'; + data_desc->flags = 0; + data_desc->off = 0; + return idata_desc; +} + +/* + * Push the root descriptor to the table. + * + * The root descriptor is to contain an offset into a special + * %root% file entry which contains data (e.g., version, file count) + * encoded within. + */ +static int +idata_push_root(void) +{ + struct idata_desc *root; + + root = idata_from_file("%root%"); + if (root == NULL) { + return -1; + } + + IDATA_PUSH(root); + return 0; +} + +static void +idata_table_destroy(void) +{ + struct idata_desc *desc, *next; + + printf("* dumping idata_table\n"); + desc = TAILQ_FIRST(&d_desc_table); + while (desc != NULL) { + printf("-- %s\n", desc->data.path); + + next = TAILQ_NEXT(desc, link); + TAILQ_REMOVE(&d_desc_table, desc, link); + desc = next; + } +} + static void recurse_dir(const char *dirpath) { DIR *dir; struct dirent *dirent; + struct idata_desc *idata_desc; char pathbuf[264]; dir = opendir(dirpath); @@ -77,6 +198,14 @@ recurse_dir(const char *dirpath) case DT_REG: snprintf(pathbuf, sizeof(pathbuf), "%s/%s", dirpath, dirent->d_name); printf("[f] %s\n", pathbuf); + + idata_desc = idata_from_file(pathbuf); + if (idata_desc == NULL) { + printf("warn: ignoring '%s'\n", pathbuf); + break; + } + + IDATA_PUSH(idata_desc); break; case DT_DIR: snprintf(pathbuf, sizeof(pathbuf), "%s/%s", dirpath, dirent->d_name); @@ -137,6 +266,9 @@ main(int argc, char **argv) output_path = FALLBACK_OUTPUT_PATH; } + TAILQ_INIT(&d_desc_table); + idata_push_root(); recurse_dir(input_dir); + idata_table_destroy(); return 0; } -- cgit v1.2.3