core: Generate output source file

This commit reduces the amount of passes required to 2 as well as
generating the actual output file.

Signed-off-by: Ian Moffett <ian@mirocom.org>
This commit is contained in:
2026-02-09 19:27:48 -05:00
parent b93394bef4
commit 5637aa0e85

View File

@@ -1,4 +1,5 @@
#define _DEFAULT_SOURCE
#include <sys/mman.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <stdio.h>
@@ -12,7 +13,7 @@
#include <string.h>
#define MAGIC_SIZE 5
#define CAV_PASSES 3
#define CAV_PASSES 2
#define CAV_VERSION "0.0.1"
#define CAV_OFF_INDEX(INDEX) \
@@ -57,7 +58,7 @@ struct cav_offset {
char magic[MAGIC_SIZE];
uint32_t off;
size_t size;
};
} __attribute__((packed));
/*
* Represents an offset descriptor used before holding
@@ -163,7 +164,7 @@ state_init(struct cav_state *state)
return -1;
}
state->out_fd = open(output_name, O_WRONLY | O_CREAT, 0600);
state->out_fd = open(output_name, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (state->out_fd < 0) {
close(state->dir_fd);
return -1;
@@ -264,6 +265,79 @@ consume_scan(const char *dir_path, struct cav_state *state, DIR *subdir)
}
}
/*
* File a file segment within the archive
*
* @state: Cav state
* @desc: Offset descriptor
*/
static void
fill_segment(struct cav_state *state, struct cav_offdesc *desc)
{
struct cav_offset *off;
void *mem;
int fd;
if (state == NULL || desc == NULL) {
return;
}
off = &desc->off;
fd = open(desc->path, O_RDONLY);
if (fd < 0) {
perror("open");
return;
}
/* Map the file */
mem = mmap(
NULL,
off->size,
PROT_READ,
MAP_SHARED,
fd,
0
);
/* File name goes before file contents */
write(state->out_fd, desc->path, strlen(desc->path) + 1);
write(state->out_fd, mem, off->size);
/* Clean up */
munmap(mem, off->size);
close(fd);
}
/*
* Construct the on-disk offset table
*
* @state: Cav state
*/
static void
build_offtab(struct cav_state *state)
{
struct cav_offdesc *off_desc;
struct cav_offset *off;
if (state == NULL) {
return;
}
/* First, write out the offset table */
TAILQ_FOREACH(off_desc, &state->offq, link) {
off = &off_desc->off;
off->off = state->cur_off;
state->cur_off += off->size;
write(state->out_fd, off, sizeof(*off));
}
/* Next, write out the segments */
TAILQ_FOREACH(off_desc, &state->offq, link) {
fill_segment(state, off_desc);
}
}
/*
* Consume a single pass in our yummy yummy consumption
* process only to be thrown up again along with stomach
@@ -272,8 +346,6 @@ consume_scan(const char *dir_path, struct cav_state *state, DIR *subdir)
static void
consume_pass(struct cav_state *state)
{
struct cav_offdesc *off;
if (state == NULL) {
return;
}
@@ -287,11 +359,11 @@ consume_pass(struct cav_state *state)
state->file_count,
state->cur_off
);
TAILQ_FOREACH(off, &state->offq, link) {
printf("[*] %s\n", off->path);
}
break;
case 1:
printf("[pass 1] building offset table + segments...\n");
state->cur_off = CAV_OFF_INDEX(state->file_count);
build_offtab(state);
break;
}
}
@@ -333,9 +405,9 @@ main(int argc, char **argv)
/*
* There are three passes required in the consumption operation
*
* pass 0): Obtain number of files for offset table creation
* pass 1): Construct an offset table using what we know
* pass 2): Construct the archive segments
* pass 0): Obtain number of files for offset table creation.
* pass 1): Construct an offset table using what we know and
* populate file entries.
*/
for (int i = 0; i < CAV_PASSES; ++i) {
consume_pass(&state);