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 "haggis.h"
|
||||||
#include "mq.h"
|
#include "mq.h"
|
||||||
|
#include <asm-generic/errno-base.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <limits.h> // PATH_MAX
|
#include <limits.h> // PATH_MAX
|
||||||
|
#include <linux/limits.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h> // uint<x>_t
|
#include <stdint.h> // uint<x>_t
|
||||||
#include <sys/syslimits.h>
|
|
||||||
#include <sys/unistd.h>
|
#include <sys/unistd.h>
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
@ -714,14 +717,16 @@ int haggis_extract_dev(haggis_node *node, char *basedir) {
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
char *path;
|
char *path;
|
||||||
int ret;
|
int ret, major, minor;
|
||||||
|
|
||||||
assert(geteuid() == 0);
|
assert(geteuid() == 0);
|
||||||
assert(node->filetype.tag == block || node->filetype.tag == character);
|
assert(node->filetype.tag == block || node->filetype.tag == character);
|
||||||
path = get_full_path(&node->name, basedir);
|
path = get_full_path(&node->name, basedir);
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
return errno;
|
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;
|
mode = (mode_t)node->mode.val;
|
||||||
ret = mknod(path, mode, dev);
|
ret = mknod(path, mode, dev);
|
||||||
free(path);
|
free(path);
|
||||||
|
@ -746,14 +751,15 @@ int haggis_extract_fifo(haggis_node *node, char *basedir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int haggis_extract_symlink(haggis_node *node, char *basedir) {
|
int haggis_extract_symlink(haggis_node *node, char *basedir) {
|
||||||
char *path;
|
char *path, *target;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
assert(node->filetype.tag == softlink);
|
assert(node->filetype.tag == softlink);
|
||||||
path = get_full_path(&node->name, basedir);
|
path = get_full_path(&node->name, basedir);
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
ret = symlink(node->filetype.f_type.target.name, path);
|
target = node->filetype.f_type.target.name;
|
||||||
|
ret = symlink(target, path);
|
||||||
free(path);
|
free(path);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return errno;
|
return errno;
|
||||||
|
@ -791,39 +797,103 @@ 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) {
|
||||||
// todo
|
char *path;
|
||||||
|
|
||||||
assert(node->filetype.tag == directory);
|
assert(node->filetype.tag == directory);
|
||||||
|
path = get_full_path(&node->name, basedir);
|
||||||
|
if (mkdir_p(path)) {
|
||||||
|
free(path);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int haggis_extract_file(haggis_node *node, char *basedir) {
|
int haggis_extract_file(haggis_node *node, char *basedir) {
|
||||||
// todo
|
char *path;
|
||||||
|
FILE *fd;
|
||||||
|
size_t len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
assert(node->filetype.tag == normal);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int haggis_extract_node(FILE *stream, char *basedir, haggis_node *node) {
|
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) {
|
switch (node->filetype.tag) {
|
||||||
case block:
|
case block:
|
||||||
case character:
|
case character:
|
||||||
if (geteuid() == 0)
|
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:
|
case fifo:
|
||||||
return haggis_extract_fifo(node, basedir);
|
ret = haggis_extract_fifo(node, basedir);
|
||||||
|
break;
|
||||||
case softlink:
|
case softlink:
|
||||||
return haggis_extract_symlink(node, basedir);
|
return haggis_extract_symlink(node, basedir);
|
||||||
case hardlink:
|
case hardlink:
|
||||||
return haggis_extract_hardlink(node, basedir);
|
ret = haggis_extract_hardlink(node, basedir);
|
||||||
|
break;
|
||||||
case directory:
|
case directory:
|
||||||
return haggis_extract_dir(node, basedir);
|
ret = haggis_extract_dir(node, basedir);
|
||||||
|
break;
|
||||||
case normal:
|
case normal:
|
||||||
return haggis_extract_file(node, basedir);
|
ret = haggis_extract_file(node, basedir);
|
||||||
|
break;
|
||||||
case eof:
|
case eof:
|
||||||
return 0;
|
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) {
|
int haggis_load_node(FILE *stream, haggis_node *node) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue