Files
2026-04-30 21:12:13 -04:00

156 lines
3.3 KiB
C

/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause
*/
#define _DEFAULT_SOURCE
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include "blobchain/common.h"
#include "blobchain/stream.h"
#include "blobchain/blob.h"
/* Input directory path */
static char *input_dir = NULL;
static void
help(void)
{
printf("usage: ./blobchain <flags>\n");
printf("... [-h] Display this help menu\n");
printf("... [-v] Display the version\n");
printf("... [-i] Input directory\n");
}
static void
version(void)
{
printf("Version v%s\n", BLOBCHAIN_VERSION);
}
static void
pack_foreach(struct blob_list *blobs, const char *input_dir)
{
struct data_stream stream;
char pathbuf[512];
struct dirent *dirent;
DIR *dir;
int error;
if (input_dir == NULL) {
return;
}
if ((dir = opendir(input_dir)) == NULL) {
perror("opendir");
return;
}
while ((dirent = readdir(dir)) != NULL) {
if (dirent->d_name[0] == '.') {
continue;
}
switch (dirent->d_type) {
case DT_DIR:
snprintf(pathbuf, sizeof(pathbuf), "%s/%s", input_dir, dirent->d_name);
pack_foreach(blobs, pathbuf);
printf("[d] %s\n", pathbuf);
break;
case DT_REG:
snprintf(pathbuf, sizeof(pathbuf), "%s/%s", input_dir, dirent->d_name);
printf("[r] %s\n", pathbuf);
error = stream_from_file(&stream, pathbuf);
if (error < 0) {
printf("fatal: could not create stream from '%s'\n", pathbuf);
return;
}
error = blob_list_append(blobs, blob_allocate(&stream));
if (error < 0) {
printf("fatal: failed to append blob '%s'\n", pathbuf);
stream_destroy(&stream);
continue;
}
stream_destroy(&stream);
break;
}
}
}
static void
pack_dir(void)
{
struct stat sb;
struct blob_list blobs;
if (stat(input_dir, &sb) < 0) {
perror("stat");
return;
}
/* Must be a directory */
if (!S_ISDIR(sb.st_mode)) {
printf("fatal: given path is not a directory!\n");
return;
}
if (blob_list_init(&blobs) < 0) {
printf("fatal: failed to initialize blob list...\n");
return;
}
pack_foreach(&blobs, input_dir);
#if BLOBCHAIN_DEBUG
blob_list_dump(&blobs);
#endif /* BLOBCHAIN_DEBUG */
blob_list_destroy(&blobs);
}
int
main(int argc, char **argv)
{
int opt;
if (argc < 2) {
printf("fatal: too few arguments!\n");
help();
return -1;
}
while ((opt = getopt(argc, argv, "hvi:")) != -1) {
switch (opt) {
case 'h':
help();
return -1;
case 'v':
version();
return -1;
case 'i':
input_dir = strdup(optarg);
if (input_dir == NULL) {
printf("fatal: out of memory\n");
return -1;
}
break;
}
}
if (input_dir == NULL) {
printf("fatal: expected input directory\n");
help();
return -1;
}
pack_dir();
free(input_dir);
return 0;
}