Wrote the extract_node
functionality; TODO: test it;
This commit is contained in:
parent
58ba56f852
commit
2bc5861dc0
1 changed files with 84 additions and 14 deletions
98
haggis.c
98
haggis.c
|
@ -32,11 +32,14 @@
|
|||
|
||||
#include "haggis.h"
|
||||
#include "mq.h"
|
||||
#include <asm-generic/errno-base.h>
|
||||
#include <assert.h>
|
||||
#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/syslimits.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
|
@ -714,14 +717,16 @@ int haggis_extract_dev(haggis_node *node, char *basedir) {
|
|||
dev_t dev;
|
||||
mode_t mode;
|
||||
char *path;
|
||||
int ret;
|
||||
int ret, major, minor;
|
||||
|
||||
assert(geteuid() == 0);
|
||||
assert(node->filetype.tag == block || node->filetype.tag == character);
|
||||
path = get_full_path(&node->name, basedir);
|
||||
if (path == NULL)
|
||||
return errno;
|
||||
dev = makedev((int)node->filetype.f_type.dev.major.val, (int)node->filetype.f_type.dev.minor.val);
|
||||
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;
|
||||
ret = mknod(path, mode, dev);
|
||||
free(path);
|
||||
|
@ -746,14 +751,15 @@ int haggis_extract_fifo(haggis_node *node, char *basedir) {
|
|||
}
|
||||
|
||||
int haggis_extract_symlink(haggis_node *node, char *basedir) {
|
||||
char *path;
|
||||
char *path, *target;
|
||||
int ret;
|
||||
|
||||
assert(node->filetype.tag == softlink);
|
||||
path = get_full_path(&node->name, basedir);
|
||||
if (path == NULL)
|
||||
return 1;
|
||||
ret = symlink(node->filetype.f_type.target.name, path);
|
||||
target = node->filetype.f_type.target.name;
|
||||
ret = symlink(target, path);
|
||||
free(path);
|
||||
if (ret != 0)
|
||||
return errno;
|
||||
|
@ -791,39 +797,103 @@ 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) {
|
||||
// todo
|
||||
char *path;
|
||||
|
||||
assert(node->filetype.tag == directory);
|
||||
path = get_full_path(&node->name, basedir);
|
||||
if (mkdir_p(path)) {
|
||||
free(path);
|
||||
return errno;
|
||||
}
|
||||
free(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int haggis_extract_file(haggis_node *node, char *basedir) {
|
||||
// todo
|
||||
char *path;
|
||||
FILE *fd;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
assert(node->filetype.tag == normal);
|
||||
path = get_full_path(&node->name, basedir);
|
||||
if (path == NULL) {
|
||||
return 1;
|
||||
}
|
||||
if (mkdir_p(dirname(strndup(path, PATH_MAX)))) {
|
||||
free(path);
|
||||
return errno;
|
||||
}
|
||||
fd = fopen(path, "w");
|
||||
if (fd == NULL) {
|
||||
free(path);
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int haggis_extract_node(FILE *stream, char *basedir, haggis_node *node) {
|
||||
// todo
|
||||
// todo: take a `haggis_mq` pointer as a parameter
|
||||
char *path, *dir;
|
||||
int ret;
|
||||
|
||||
path = get_full_path(&node->name, basedir);
|
||||
dir = dirname(strndup(path, PATH_MAX));
|
||||
mkdir_p(dir);
|
||||
switch (node->filetype.tag) {
|
||||
case block:
|
||||
case character:
|
||||
if (geteuid() == 0)
|
||||
return haggis_extract_dev(node, basedir);
|
||||
ret = haggis_extract_dev(node, basedir);
|
||||
// todo: Add message type for skipped file and add it to queue if we're
|
||||
// not root when calling this. We want this to be a warning, but not a
|
||||
// fatal error.
|
||||
break;
|
||||
case fifo:
|
||||
return haggis_extract_fifo(node, basedir);
|
||||
ret = haggis_extract_fifo(node, basedir);
|
||||
break;
|
||||
case softlink:
|
||||
return haggis_extract_symlink(node, basedir);
|
||||
case hardlink:
|
||||
return haggis_extract_hardlink(node, basedir);
|
||||
ret = haggis_extract_hardlink(node, basedir);
|
||||
break;
|
||||
case directory:
|
||||
return haggis_extract_dir(node, basedir);
|
||||
ret = haggis_extract_dir(node, basedir);
|
||||
break;
|
||||
case normal:
|
||||
return haggis_extract_file(node, basedir);
|
||||
ret = haggis_extract_file(node, basedir);
|
||||
break;
|
||||
case eof:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
if (geteuid() == 0) {
|
||||
ret = chown(path, (uid_t)node->uid.val, (gid_t)node->gid.val);
|
||||
if (ret != 0) {
|
||||
free(path);
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
ret = chmod(path, (mode_t)node->mode.val);
|
||||
// todo: make a 'NodeCreated' message and add it to the message queue
|
||||
return ret;
|
||||
}
|
||||
|
||||
int haggis_load_node(FILE *stream, haggis_node *node) {
|
||||
|
|
Loading…
Add table
Reference in a new issue