Get device file ezxtraction working and tested
This commit is contained in:
parent
349c9389dd
commit
7b94a728ae
6 changed files with 127 additions and 32 deletions
2
Makefile
2
Makefile
|
@ -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
|
||||||
|
|
||||||
|
|
86
haggis.c
86
haggis.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
14
mq.c
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
42
test/extract_dev_node.c
Normal 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;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue