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)
|
||||
|
||||
all: libhaggis.a libhaggis.so
|
||||
all: shared static
|
||||
|
||||
shared: libhaggis.so
|
||||
|
||||
|
|
86
haggis.c
86
haggis.c
|
@ -36,6 +36,7 @@
|
|||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h> // PATH_MAX
|
||||
#include <linux/limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> // uint<x>_t
|
||||
#include <sys/unistd.h>
|
||||
|
@ -592,7 +593,7 @@ int haggis_init_dev_node(
|
|||
}
|
||||
}
|
||||
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);
|
||||
haggis_mq_push(mq, msg);
|
||||
return 0;
|
||||
|
@ -711,6 +712,17 @@ char* get_full_path(haggis_filename *fname, char *basedir) {
|
|||
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) {
|
||||
dev_t dev;
|
||||
mode_t mode;
|
||||
|
@ -722,10 +734,18 @@ int haggis_extract_dev(haggis_node *node, char *basedir) {
|
|||
path = get_full_path(&node->name, basedir);
|
||||
if (path == NULL)
|
||||
return errno;
|
||||
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
|
||||
free(path);
|
||||
return 2;
|
||||
}
|
||||
major = (int)node->filetype.f_type.dev.major.val;
|
||||
minor = (int)node->filetype.f_type.dev.minor.val;
|
||||
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);
|
||||
free(path);
|
||||
return ret;
|
||||
|
@ -740,6 +760,10 @@ int haggis_extract_fifo(haggis_node *node, char *basedir) {
|
|||
path = get_full_path(&node->name, basedir);
|
||||
if (path == NULL)
|
||||
return 1;
|
||||
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
|
||||
free(path);
|
||||
return 2;
|
||||
}
|
||||
mode = (mode_t)node->mode.val;
|
||||
ret = mkfifo(path, mode);
|
||||
free(path);
|
||||
|
@ -756,6 +780,10 @@ int haggis_extract_symlink(haggis_node *node, char *basedir) {
|
|||
path = get_full_path(&node->name, basedir);
|
||||
if (path == NULL)
|
||||
return 1;
|
||||
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
|
||||
free(path);
|
||||
return 2;
|
||||
}
|
||||
target = node->filetype.f_type.target.name;
|
||||
ret = symlink(target, path);
|
||||
free(path);
|
||||
|
@ -773,6 +801,10 @@ int haggis_extract_hardlink(haggis_node *node, char *basedir) {
|
|||
path = get_full_path(&node->name, basedir);
|
||||
if (path == NULL)
|
||||
return 1;
|
||||
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
|
||||
free(path);
|
||||
return 2;
|
||||
}
|
||||
target = get_full_path(&node->filetype.f_type.target, basedir);
|
||||
if (target == NULL) {
|
||||
free(path);
|
||||
|
@ -780,6 +812,10 @@ int haggis_extract_hardlink(haggis_node *node, char *basedir) {
|
|||
}
|
||||
if (access(target, F_OK) == -1) {
|
||||
fd = fopen(target, "w");
|
||||
if (mkdir_p(dirname(strndup(target, PATH_MAX)))) {
|
||||
free(path);
|
||||
return 2;
|
||||
}
|
||||
if (fd == NULL) {
|
||||
free(path);
|
||||
free(target);
|
||||
|
@ -795,17 +831,6 @@ int haggis_extract_hardlink(haggis_node *node, char *basedir) {
|
|||
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) {
|
||||
char *path;
|
||||
|
||||
|
@ -819,7 +844,7 @@ int haggis_extract_dir(haggis_node *node, char *basedir) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int haggis_extract_file(haggis_node *node, char *basedir) {
|
||||
char* haggis_extract_file(haggis_node *node, char *basedir) {
|
||||
char *path;
|
||||
FILE *fd;
|
||||
size_t len;
|
||||
|
@ -828,32 +853,33 @@ int haggis_extract_file(haggis_node *node, char *basedir) {
|
|||
assert(node->filetype.tag == normal);
|
||||
path = get_full_path(&node->name, basedir);
|
||||
if (path == NULL) {
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
|
||||
free(path);
|
||||
return errno;
|
||||
return NULL;
|
||||
}
|
||||
fd = fopen(path, "w");
|
||||
if (fd == NULL) {
|
||||
free(path);
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
len = (size_t)node->filetype.f_type.file.len.val;
|
||||
ret = fwrite(node->filetype.f_type.file.data, len, 1, fd);
|
||||
if (ret != len) {
|
||||
return 2;
|
||||
free(path);
|
||||
fclose(fd);
|
||||
return NULL;
|
||||
}
|
||||
fflush(fd);
|
||||
fclose(fd);
|
||||
free(path);
|
||||
return 0;
|
||||
return path;
|
||||
}
|
||||
|
||||
int haggis_extract_node(FILE *stream, char *basedir, haggis_node *node) {
|
||||
// todo: take a `haggis_mq` pointer as a parameter
|
||||
char *path, *dir;
|
||||
int ret;
|
||||
int haggis_extract_node(char *basedir, haggis_node *node, haggis_mq *mq) {
|
||||
haggis_msg *msg;
|
||||
char *path, *dir, *fullpath;
|
||||
int ret;
|
||||
|
||||
path = get_full_path(&node->name, basedir);
|
||||
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);
|
||||
break;
|
||||
case normal:
|
||||
ret = haggis_extract_file(node, basedir);
|
||||
fullpath = haggis_extract_file(node, basedir);
|
||||
if (fullpath == NULL) {
|
||||
ret = errno;
|
||||
}
|
||||
break;
|
||||
case eof:
|
||||
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);
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
void haggis_node_deinit(haggis_node *node);
|
||||
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_store_node(FILE *stream, haggis_node *node);
|
||||
|
||||
|
|
14
mq.c
14
mq.c
|
@ -33,6 +33,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h> // free, malloc
|
||||
|
||||
#include "haggis.h"
|
||||
#include "mq.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 ret;
|
||||
|
||||
|
|
|
@ -71,25 +71,30 @@ tests += create_fifo_node
|
|||
tests += create_dev_node
|
||||
tests += create_file_node
|
||||
tests += mq_push_pop
|
||||
tests += extract_dev_node
|
||||
|
||||
total != echo $(tests) | wc -w | awk '{ print $$1 }'
|
||||
|
||||
.PHONY: test
|
||||
test: $(tests) output
|
||||
@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} ; \
|
||||
idx=$$(expr $${idx} + 1) ; \
|
||||
./$${t} ; \
|
||||
if [ $$? -eq 0 ] ; \
|
||||
retval=$$? ; \
|
||||
if [ $${retval} -eq 0 ] ; \
|
||||
then echo -e '\e[0;32mSuccess\e[0m' ; \
|
||||
success=$$(expr $${success} + 1) ; \
|
||||
elif [ $${retval} -eq 255 ] ; \
|
||||
then echo Skipped ; \
|
||||
skip=$$(expr $${skip} + 1) ; \
|
||||
else echo -e '\e[0;31mFailure\e[0m' ; \
|
||||
fail=$$(expr $${fail} + 1) ; \
|
||||
fi ; done || true ; \
|
||||
if [ $${fail} == 0 ] ; \
|
||||
then echo -e '\nResults: \e[0;32mOk\e[0m.' "$${success} succeeded; $${fail} failed" ; \
|
||||
else echo -e '\nResults: \e[0;31mFAILED\e[0m.' "$${success} succeeded; $${fail} failed\n" ; \
|
||||
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; $${skip} skipped" ; \
|
||||
fi
|
||||
|
||||
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