Get device file ezxtraction working and tested

This commit is contained in:
Nathan Fisher 2023-10-03 01:53:59 -04:00
parent 349c9389dd
commit 7b94a728ae
6 changed files with 127 additions and 32 deletions

View file

@ -54,7 +54,7 @@ srcs += linkmap.c
objs = $(srcs:.c=.o) objs = $(srcs:.c=.o)
all: libhaggis.a libhaggis.so all: shared static
shared: libhaggis.so shared: libhaggis.so

View file

@ -36,6 +36,7 @@
#include <errno.h> #include <errno.h>
#include <libgen.h> #include <libgen.h>
#include <limits.h> // PATH_MAX #include <limits.h> // PATH_MAX
#include <linux/limits.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> // uint<x>_t #include <stdint.h> // uint<x>_t
#include <sys/unistd.h> #include <sys/unistd.h>
@ -592,7 +593,7 @@ int haggis_init_dev_node(
} }
} }
haggis_device_init(st->st_rdev, &node->filetype.f_type.dev); haggis_device_init(st->st_rdev, &node->filetype.f_type.dev);
body.f_name = node->name.name; body.f_name = strndup(node->name.name, PATH_MAX);
msg = haggis_msg_init(NodeCreated, body); msg = haggis_msg_init(NodeCreated, body);
haggis_mq_push(mq, msg); haggis_mq_push(mq, msg);
return 0; return 0;
@ -711,6 +712,17 @@ char* get_full_path(haggis_filename *fname, char *basedir) {
return path; return path;
} }
int mkdir_p(char *dir) {
struct stat st;
if (!stat(dir, &st))
return 0;
if (mkdir_p(dirname(strndup(dir, PATH_MAX))))
return 1;
return mkdir(dir, 0755);
}
int haggis_extract_dev(haggis_node *node, char *basedir) { int haggis_extract_dev(haggis_node *node, char *basedir) {
dev_t dev; dev_t dev;
mode_t mode; mode_t mode;
@ -722,10 +734,18 @@ int haggis_extract_dev(haggis_node *node, char *basedir) {
path = get_full_path(&node->name, basedir); path = get_full_path(&node->name, basedir);
if (path == NULL) if (path == NULL)
return errno; return errno;
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
free(path);
return 2;
}
major = (int)node->filetype.f_type.dev.major.val; major = (int)node->filetype.f_type.dev.major.val;
minor = (int)node->filetype.f_type.dev.minor.val; minor = (int)node->filetype.f_type.dev.minor.val;
dev = makedev(major, minor); dev = makedev(major, minor);
mode = (mode_t)node->mode.val; if (node->filetype.tag == block) {
mode = (mode_t)node->mode.val | S_IFBLK;
} else if (node->filetype.tag == character) {
mode = (mode_t)node->mode.val | S_IFCHR;
}
ret = mknod(path, mode, dev); ret = mknod(path, mode, dev);
free(path); free(path);
return ret; return ret;
@ -740,6 +760,10 @@ int haggis_extract_fifo(haggis_node *node, char *basedir) {
path = get_full_path(&node->name, basedir); path = get_full_path(&node->name, basedir);
if (path == NULL) if (path == NULL)
return 1; return 1;
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
free(path);
return 2;
}
mode = (mode_t)node->mode.val; mode = (mode_t)node->mode.val;
ret = mkfifo(path, mode); ret = mkfifo(path, mode);
free(path); free(path);
@ -756,6 +780,10 @@ int haggis_extract_symlink(haggis_node *node, char *basedir) {
path = get_full_path(&node->name, basedir); path = get_full_path(&node->name, basedir);
if (path == NULL) if (path == NULL)
return 1; return 1;
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
free(path);
return 2;
}
target = node->filetype.f_type.target.name; target = node->filetype.f_type.target.name;
ret = symlink(target, path); ret = symlink(target, path);
free(path); free(path);
@ -773,6 +801,10 @@ int haggis_extract_hardlink(haggis_node *node, char *basedir) {
path = get_full_path(&node->name, basedir); path = get_full_path(&node->name, basedir);
if (path == NULL) if (path == NULL)
return 1; return 1;
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
free(path);
return 2;
}
target = get_full_path(&node->filetype.f_type.target, basedir); target = get_full_path(&node->filetype.f_type.target, basedir);
if (target == NULL) { if (target == NULL) {
free(path); free(path);
@ -780,6 +812,10 @@ int haggis_extract_hardlink(haggis_node *node, char *basedir) {
} }
if (access(target, F_OK) == -1) { if (access(target, F_OK) == -1) {
fd = fopen(target, "w"); fd = fopen(target, "w");
if (mkdir_p(dirname(strndup(target, PATH_MAX)))) {
free(path);
return 2;
}
if (fd == NULL) { if (fd == NULL) {
free(path); free(path);
free(target); free(target);
@ -795,17 +831,6 @@ int haggis_extract_hardlink(haggis_node *node, char *basedir) {
return 0; return 0;
} }
int mkdir_p(char *dir) {
struct stat st;
if (!stat(dir, &st))
return 0;
if (mkdir_p(dirname(strndup(dir, PATH_MAX))))
return 1;
return mkdir(dir, 0755);
}
int haggis_extract_dir(haggis_node *node, char *basedir) { int haggis_extract_dir(haggis_node *node, char *basedir) {
char *path; char *path;
@ -819,7 +844,7 @@ int haggis_extract_dir(haggis_node *node, char *basedir) {
return 0; return 0;
} }
int haggis_extract_file(haggis_node *node, char *basedir) { char* haggis_extract_file(haggis_node *node, char *basedir) {
char *path; char *path;
FILE *fd; FILE *fd;
size_t len; size_t len;
@ -828,32 +853,33 @@ int haggis_extract_file(haggis_node *node, char *basedir) {
assert(node->filetype.tag == normal); assert(node->filetype.tag == normal);
path = get_full_path(&node->name, basedir); path = get_full_path(&node->name, basedir);
if (path == NULL) { if (path == NULL) {
return 1; return NULL;
} }
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) { if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
free(path); free(path);
return errno; return NULL;
} }
fd = fopen(path, "w"); fd = fopen(path, "w");
if (fd == NULL) { if (fd == NULL) {
free(path); free(path);
return 1; return NULL;
} }
len = (size_t)node->filetype.f_type.file.len.val; len = (size_t)node->filetype.f_type.file.len.val;
ret = fwrite(node->filetype.f_type.file.data, len, 1, fd); ret = fwrite(node->filetype.f_type.file.data, len, 1, fd);
if (ret != len) { if (ret != len) {
return 2; free(path);
fclose(fd);
return NULL;
} }
fflush(fd); fflush(fd);
fclose(fd); fclose(fd);
free(path); return path;
return 0;
} }
int haggis_extract_node(FILE *stream, char *basedir, haggis_node *node) { int haggis_extract_node(char *basedir, haggis_node *node, haggis_mq *mq) {
// todo: take a `haggis_mq` pointer as a parameter haggis_msg *msg;
char *path, *dir; char *path, *dir, *fullpath;
int ret; int ret;
path = get_full_path(&node->name, basedir); path = get_full_path(&node->name, basedir);
dir = dirname(strndup(path, PATH_MAX)); dir = dirname(strndup(path, PATH_MAX));
@ -879,7 +905,10 @@ int haggis_extract_node(FILE *stream, char *basedir, haggis_node *node) {
ret = haggis_extract_dir(node, basedir); ret = haggis_extract_dir(node, basedir);
break; break;
case normal: case normal:
ret = haggis_extract_file(node, basedir); fullpath = haggis_extract_file(node, basedir);
if (fullpath == NULL) {
ret = errno;
}
break; break;
case eof: case eof:
return 0; return 0;
@ -892,7 +921,12 @@ int haggis_extract_node(FILE *stream, char *basedir, haggis_node *node) {
} }
} }
ret = chmod(path, (mode_t)node->mode.val); ret = chmod(path, (mode_t)node->mode.val);
// todo: make a 'NodeCreated' message and add it to the message queue msg = calloc(1, sizeof(haggis_msg));
if (msg == NULL)
return 2;
msg->tag = NodeExtracted;
msg->body.f_name = strndup(node->name.name, PATH_MAX);
haggis_mq_push(mq, msg);
return ret; return ret;
} }

View file

@ -168,7 +168,7 @@ void haggis_linkmap_deinit(haggis_linkmap *map);
char* haggis_linkmap_get_or_add(haggis_linkmap *map, ino_t inode, char *path); char* haggis_linkmap_get_or_add(haggis_linkmap *map, ino_t inode, char *path);
void haggis_node_deinit(haggis_node *node); void haggis_node_deinit(haggis_node *node);
haggis_node* haggis_create_node(char *file, haggis_algorithm a, haggis_linkmap *map, haggis_mq *mq); haggis_node* haggis_create_node(char *file, haggis_algorithm a, haggis_linkmap *map, haggis_mq *mq);
int haggis_extract_node(FILE *stream, char *basedir, haggis_node *node); int haggis_extract_node(char *basedir, haggis_node *node, haggis_mq *mq);
int haggis_load_node(FILE *stream, haggis_node *node); int haggis_load_node(FILE *stream, haggis_node *node);
int haggis_store_node(FILE *stream, haggis_node *node); int haggis_store_node(FILE *stream, haggis_node *node);

14
mq.c
View file

@ -33,6 +33,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> // free, malloc #include <stdlib.h> // free, malloc
#include "haggis.h"
#include "mq.h" #include "mq.h"
haggis_msg* haggis_msg_init(haggis_message_type tag, haggis_message_body body) { haggis_msg* haggis_msg_init(haggis_message_type tag, haggis_message_body body) {
@ -45,6 +46,19 @@ haggis_msg* haggis_msg_init(haggis_message_type tag, haggis_message_body body) {
return msg; return msg;
} }
void haggis_msg_deinit(haggis_msg *msg) {
switch (msg->tag) {
case NodeCreated:
case NodeExtracted:
free(msg->body.f_name);
break;
case EndOfArchive:
case ArchiveError:
break;
}
free(msg);
}
int haggis_mq_init(haggis_mq *mq) { int haggis_mq_init(haggis_mq *mq) {
int ret; int ret;

View file

@ -71,25 +71,30 @@ tests += create_fifo_node
tests += create_dev_node tests += create_dev_node
tests += create_file_node tests += create_file_node
tests += mq_push_pop tests += mq_push_pop
tests += extract_dev_node
total != echo $(tests) | wc -w | awk '{ print $$1 }' total != echo $(tests) | wc -w | awk '{ print $$1 }'
.PHONY: test .PHONY: test
test: $(tests) output test: $(tests) output
@echo -e "\n\t=== \e[0;33mRunning $(total) tests\e[0m ===\n" @echo -e "\n\t=== \e[0;33mRunning $(total) tests\e[0m ===\n"
@idx=1 ; success=0 ; fail=0; for t in $(tests) ; \ @idx=1 ; success=0 ; fail=0; skip=0; for t in $(tests) ; \
do printf "[%02i/$(total)] %-25s" $${idx} $${t} ; \ do printf "[%02i/$(total)] %-25s" $${idx} $${t} ; \
idx=$$(expr $${idx} + 1) ; \ idx=$$(expr $${idx} + 1) ; \
./$${t} ; \ ./$${t} ; \
if [ $$? -eq 0 ] ; \ retval=$$? ; \
if [ $${retval} -eq 0 ] ; \
then echo -e '\e[0;32mSuccess\e[0m' ; \ then echo -e '\e[0;32mSuccess\e[0m' ; \
success=$$(expr $${success} + 1) ; \ success=$$(expr $${success} + 1) ; \
elif [ $${retval} -eq 255 ] ; \
then echo Skipped ; \
skip=$$(expr $${skip} + 1) ; \
else echo -e '\e[0;31mFailure\e[0m' ; \ else echo -e '\e[0;31mFailure\e[0m' ; \
fail=$$(expr $${fail} + 1) ; \ fail=$$(expr $${fail} + 1) ; \
fi ; done || true ; \ fi ; done || true ; \
if [ $${fail} == 0 ] ; \ if [ $${fail} == 0 ] ; \
then echo -e '\nResults: \e[0;32mOk\e[0m.' "$${success} succeeded; $${fail} failed" ; \ then echo -e '\nResults: \e[0;32mOk\e[0m.' "$${success} succeeded; $${fail} failed; $${skip} skipped" ; \
else echo -e '\nResults: \e[0;31mFAILED\e[0m.' "$${success} succeeded; $${fail} failed\n" ; \ else echo -e '\nResults: \e[0;31mFAILED\e[0m.' "$${success} succeeded; $${fail} failed; $${skip} skipped" ; \
fi fi
output: output:

42
test/extract_dev_node.c Normal file
View file

@ -0,0 +1,42 @@
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "haggis.h"
#include "mq.h"
int main() {
haggis_node *node = NULL;
haggis_linkmap *map = NULL;
haggis_mq mq;
haggis_msg *msg;
char *path = "/dev/null", *msg_text;
int ret = 0;
if (geteuid() != 0)
return -1;
map = haggis_linkmap_init();
assert(map != NULL);
if (haggis_mq_init(&mq))
return errno;
node = haggis_create_node(path, sha256, map, &mq);
assert(node != NULL);
assert(node->filetype.tag == block || node->filetype.tag == character);
assert(memcmp(node->name.name, "dev/null", 8) == 0);
msg = haggis_mq_pop(&mq);
assert(msg->tag == NodeCreated);
assert(memcmp(msg->body.f_name, "dev/null", 8) == 0);
haggis_msg_deinit(msg);
ret = haggis_extract_node("output/extracted", node, &mq);
msg = haggis_mq_pop(&mq);
assert(msg->tag == NodeExtracted);
assert(memcmp(msg->body.f_name, "dev/null", 8) == 0);
haggis_msg_deinit(msg);
haggis_node_deinit(node);
haggis_linkmap_deinit(map);
return 0;
}