Compare commits
7 Commits
0f31d51743
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e35d8cf136 | |||
| 1d4bb8769a | |||
| d991988fd8 | |||
| d7c0f78d02 | |||
| 83a0ef6e2e | |||
| 09e0774d12 | |||
| e1181bed6f |
@@ -8,6 +8,8 @@ DFILES = $(CFILES:.c=.d)
|
|||||||
OFILES = $(CFILES:.c=.o)
|
OFILES = $(CFILES:.c=.o)
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
LIBS = $(shell pkg-config --libs "openssl")
|
||||||
|
|
||||||
CFLAGS = \
|
CFLAGS = \
|
||||||
-Wall \
|
-Wall \
|
||||||
-pedantic \
|
-pedantic \
|
||||||
@@ -19,7 +21,7 @@ all: blobchain
|
|||||||
|
|
||||||
.PHONY: blobchain
|
.PHONY: blobchain
|
||||||
blobchain: $(OFILES)
|
blobchain: $(OFILES)
|
||||||
$(CC) $^ -o $@
|
$(CC) $(LIBS) $^ -o $@
|
||||||
|
|
||||||
-include $(DFILES)
|
-include $(DFILES)
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
|
|||||||
+61
-1
@@ -3,10 +3,25 @@
|
|||||||
* Provided under the BSD-3 clause
|
* Provided under the BSD-3 clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "blobchain/blob.h"
|
#include "blobchain/blob.h"
|
||||||
#include "blobchain/memlib.h"
|
#include "blobchain/memlib.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
dump_bytes(void *buf, size_t len)
|
||||||
|
{
|
||||||
|
char *p = buf;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
while ((i++) < len) {
|
||||||
|
printf("%02X ", p[i] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
blob_list_init(struct blob_list *lp)
|
blob_list_init(struct blob_list *lp)
|
||||||
{
|
{
|
||||||
@@ -44,5 +59,50 @@ blob_list_append(struct blob_list *lp, struct blob *blob)
|
|||||||
|
|
||||||
++lp->count;
|
++lp->count;
|
||||||
return 0;
|
return 0;
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blob_list_destroy(struct blob_list *lp)
|
||||||
|
{
|
||||||
|
struct blob *bp, *tmp;
|
||||||
|
|
||||||
|
if (lp == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bp = lp->head;
|
||||||
|
while (bp != NULL) {
|
||||||
|
tmp = bp;
|
||||||
|
bp = bp->next;
|
||||||
|
|
||||||
|
free(tmp->data);
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
blob_list_dump(struct blob_list *lp)
|
||||||
|
{
|
||||||
|
const size_t DUMP_SIZE = 4;
|
||||||
|
struct blob *blob;
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
if (lp == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
blob = lp->head;
|
||||||
|
while (blob != NULL) {
|
||||||
|
printf("blob %zd/%zd\n", count++, lp->count);
|
||||||
|
printf("... length :: %zd\n", blob->length);
|
||||||
|
printf("... hash :: ");
|
||||||
|
dump_bytes(blob->hash, SHA256_N_BYTES);
|
||||||
|
|
||||||
|
printf("... data :: ");
|
||||||
|
dump_bytes(blob->data, blob->length < DUMP_SIZE
|
||||||
|
? blob->length
|
||||||
|
: DUMP_SIZE);
|
||||||
|
|
||||||
|
blob = blob->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ blob_allocate(struct data_stream *stmp)
|
|||||||
|
|
||||||
bp = xmalloc(sizeof(*bp));
|
bp = xmalloc(sizeof(*bp));
|
||||||
bp->length = (stmp != NULL) ? stmp->length : 0;
|
bp->length = (stmp != NULL) ? stmp->length : 0;
|
||||||
|
bp->next = NULL;
|
||||||
if (stmp == NULL) {
|
if (stmp == NULL) {
|
||||||
bp->data = NULL;
|
bp->data = NULL;
|
||||||
} else {
|
} else {
|
||||||
@@ -21,5 +22,6 @@ blob_allocate(struct data_stream *stmp)
|
|||||||
memcpy(bp->data, stmp->data, stmp->length);
|
memcpy(bp->data, stmp->data, stmp->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(bp->hash, stmp->hash, SHA256_N_BYTES);
|
||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|||||||
+109
-1
@@ -3,9 +3,19 @@
|
|||||||
* Provided under the BSD-3 clause
|
* Provided under the BSD-3 clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define _DEFAULT_SOURCE
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include "blobchain/common.h"
|
#include "blobchain/common.h"
|
||||||
|
#include "blobchain/stream.h"
|
||||||
|
#include "blobchain/blob.h"
|
||||||
|
|
||||||
|
/* Input directory path */
|
||||||
|
static char *input_dir = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
help(void)
|
help(void)
|
||||||
@@ -13,6 +23,7 @@ help(void)
|
|||||||
printf("usage: ./blobchain <flags>\n");
|
printf("usage: ./blobchain <flags>\n");
|
||||||
printf("... [-h] Display this help menu\n");
|
printf("... [-h] Display this help menu\n");
|
||||||
printf("... [-v] Display the version\n");
|
printf("... [-v] Display the version\n");
|
||||||
|
printf("... [-i] Input directory\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -21,6 +32,87 @@ version(void)
|
|||||||
printf("Version v%s\n", BLOBCHAIN_VERSION);
|
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
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -32,7 +124,7 @@ main(int argc, char **argv)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "hv")) != -1) {
|
while ((opt = getopt(argc, argv, "hvi:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'h':
|
case 'h':
|
||||||
help();
|
help();
|
||||||
@@ -40,8 +132,24 @@ main(int argc, char **argv)
|
|||||||
case 'v':
|
case 'v':
|
||||||
version();
|
version();
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2026, Chloe M.
|
||||||
|
* Provided under the BSD-3 clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include "blobchain/memlib.h"
|
||||||
|
#include "blobchain/stream.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
stream_from_file(struct data_stream *stmp, const char *path)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
void *p;
|
||||||
|
ssize_t readlen;
|
||||||
|
int error, fd;
|
||||||
|
|
||||||
|
if (stmp == NULL || path == NULL) {
|
||||||
|
errno = -EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = stat(path, &sb);
|
||||||
|
if (error < 0) {
|
||||||
|
perror("stat");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("open");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we want to allocate a whole block of memory to
|
||||||
|
* contain the entire file.
|
||||||
|
*
|
||||||
|
* XXX: For this reason, it is a good idea to only work with
|
||||||
|
* one file at a time to avoid saturating all of your RAM...
|
||||||
|
*/
|
||||||
|
p = xmalloc(sb.st_size);
|
||||||
|
stmp->length = sb.st_size;
|
||||||
|
stmp->data = p;
|
||||||
|
|
||||||
|
readlen = read(fd, p, stmp->length);
|
||||||
|
if (readlen < 0) {
|
||||||
|
perror("read");
|
||||||
|
close(fd);
|
||||||
|
free(p);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHA256(stmp->data, stmp->length, stmp->hash);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stream_destroy(struct data_stream *stmp)
|
||||||
|
{
|
||||||
|
if (stmp == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stmp->data == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(stmp->data);
|
||||||
|
stmp->length = 0;
|
||||||
|
stmp->data = NULL;
|
||||||
|
}
|
||||||
@@ -9,17 +9,20 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "blobchain/stream.h"
|
#include "blobchain/stream.h"
|
||||||
|
#include "blobchain/common.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Represents a single blob of data
|
* Represents a single blob of data
|
||||||
*
|
*
|
||||||
* @data: Buffer containing blob data
|
* @data: Buffer containing blob data
|
||||||
* @length: Length of blob
|
* @length: Length of blob
|
||||||
|
* @hash: Hash of file contents
|
||||||
* @next: Next blob
|
* @next: Next blob
|
||||||
*/
|
*/
|
||||||
struct blob {
|
struct blob {
|
||||||
void *data;
|
void *data;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
uint8_t hash[SHA256_N_BYTES];
|
||||||
struct blob *next;
|
struct blob *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,4 +63,18 @@ int blob_list_append(struct blob_list *lp, struct blob *blob);
|
|||||||
*/
|
*/
|
||||||
int blob_list_init(struct blob_list *lp);
|
int blob_list_init(struct blob_list *lp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy a blob list
|
||||||
|
*
|
||||||
|
* @lp: Bloblist to destroy
|
||||||
|
*/
|
||||||
|
void blob_list_destroy(struct blob_list *lp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump a blob list for debugging purposes
|
||||||
|
*
|
||||||
|
* @lp: Blob list to dump
|
||||||
|
*/
|
||||||
|
void blob_list_dump(struct blob_list *lp);
|
||||||
|
|
||||||
#endif /* !BLOBCHAIN_BLOB_H */
|
#endif /* !BLOBCHAIN_BLOB_H */
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#ifndef BLOBCHAIN_COMMON_H
|
#ifndef BLOBCHAIN_COMMON_H
|
||||||
#define BLOBCHAIN_COMMON_H 1
|
#define BLOBCHAIN_COMMON_H 1
|
||||||
|
|
||||||
|
#define SHA256_N_BYTES 32
|
||||||
|
|
||||||
|
#define BLOBCHAIN_DEBUG 1
|
||||||
#define BLOBCHAIN_VERSION "0.0.1"
|
#define BLOBCHAIN_VERSION "0.0.1"
|
||||||
|
|
||||||
#endif /* !BLOBCHAIN_COMMON_H */
|
#endif /* !BLOBCHAIN_COMMON_H */
|
||||||
|
|||||||
@@ -6,17 +6,36 @@
|
|||||||
#ifndef BLOBCHAIN_STREAM_H
|
#ifndef BLOBCHAIN_STREAM_H
|
||||||
#define BLOBCHAIN_STREAM_H 1
|
#define BLOBCHAIN_STREAM_H 1
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include "blobchain/common.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Represents a data stream
|
* Represents a data stream
|
||||||
*
|
*
|
||||||
* @data: Data buffer
|
* @data: Data buffer
|
||||||
* @length: Number of bytes in data buffer
|
* @length: Number of bytes in data buffer
|
||||||
|
* @hash: SHA256 hash of file contents
|
||||||
*/
|
*/
|
||||||
struct data_stream {
|
struct data_stream {
|
||||||
void *data;
|
void *data;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
uint8_t hash[SHA256_N_BYTES];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain a stream from a file
|
||||||
|
*
|
||||||
|
* @stmp: Stream pointer result
|
||||||
|
* @path: Path of file to obtain stream from
|
||||||
|
*
|
||||||
|
* Returns zero on success
|
||||||
|
*/
|
||||||
|
int stream_from_file(struct data_stream *stmp, const char *path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy a data stream
|
||||||
|
*/
|
||||||
|
void stream_destroy(struct data_stream *stmp);
|
||||||
|
|
||||||
#endif /* !BLOBCHAIN_STREAM_H */
|
#endif /* !BLOBCHAIN_STREAM_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user