aboutsummaryrefslogtreecommitdiff
path: root/lib/fstree/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fstree/src')
-rw-r--r--lib/fstree/src/add_by_path.c54
-rw-r--r--lib/fstree/src/fstree.c217
-rw-r--r--lib/fstree/src/get_by_path.c84
-rw-r--r--lib/fstree/src/mknode.c101
4 files changed, 207 insertions, 249 deletions
diff --git a/lib/fstree/src/add_by_path.c b/lib/fstree/src/add_by_path.c
deleted file mode 100644
index 344b586..0000000
--- a/lib/fstree/src/add_by_path.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * add_by_path.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include "fstree.h"
-
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-
-tree_node_t *fstree_add_generic(fstree_t *fs, const char *path,
- const struct stat *sb, const char *extra)
-{
- tree_node_t *child, *parent;
- const char *name;
-
- if (*path == '\0') {
- child = fs->root;
- assert(child != NULL);
- goto out;
- }
-
- parent = fstree_get_node_by_path(fs, fs->root, path, true, true);
- if (parent == NULL)
- return NULL;
-
- name = strrchr(path, '/');
- name = (name == NULL ? path : (name + 1));
-
- child = parent->data.children;
- while (child != NULL && strcmp(child->name, name) != 0)
- child = child->next;
-out:
- if (child != NULL) {
- if (!S_ISDIR(child->mode) || !S_ISDIR(sb->st_mode) ||
- !(child->flags & FLAG_DIR_CREATED_IMPLICITLY)) {
- errno = EEXIST;
- return NULL;
- }
-
- child->uid = sb->st_uid;
- child->gid = sb->st_gid;
- child->mode = sb->st_mode;
- child->mod_time = sb->st_mtime;
- child->flags &= ~FLAG_DIR_CREATED_IMPLICITLY;
- return child;
- }
-
- return fstree_mknode(parent, name, strlen(name), extra, sb);
-}
diff --git a/lib/fstree/src/fstree.c b/lib/fstree/src/fstree.c
index bf84c17..43a6ccc 100644
--- a/lib/fstree/src/fstree.c
+++ b/lib/fstree/src/fstree.c
@@ -9,7 +9,9 @@
#include <string.h>
#include <stdlib.h>
+#include <assert.h>
#include <stdio.h>
+#include <errno.h>
static void free_recursive(tree_node_t *n)
{
@@ -27,26 +29,120 @@ static void free_recursive(tree_node_t *n)
free(n);
}
-int fstree_init(fstree_t *fs, const fstree_defaults_t *defaults)
+static tree_node_t *child_by_name(tree_node_t *root, const char *name,
+ size_t len)
{
- struct stat sb;
+ tree_node_t *n = root->data.children;
- memset(fs, 0, sizeof(*fs));
- fs->defaults = *defaults;
+ while (n != NULL) {
+ if (strncmp(n->name, name, len) == 0 && n->name[len] == '\0')
+ break;
+
+ n = n->next;
+ }
+
+ return n;
+}
+
+static void insert_sorted(tree_node_t *root, tree_node_t *n)
+{
+ tree_node_t *it = root->data.children, *prev = NULL;
+
+ while (it != NULL && strcmp(it->name, n->name) < 0) {
+ prev = it;
+ it = it->next;
+ }
+
+ n->parent = root;
+ n->next = it;
+
+ if (prev == NULL) {
+ root->data.children = n;
+ } else {
+ prev->next = n;
+ }
+}
+
+static tree_node_t *mknode(tree_node_t *parent, const char *name,
+ size_t name_len, const char *extra,
+ const struct stat *sb)
+{
+ tree_node_t *n;
+ size_t size;
+ char *ptr;
+
+ size = sizeof(tree_node_t) + name_len + 1;
+ if (extra != NULL)
+ size += strlen(extra) + 1;
+
+ n = calloc(1, size);
+ if (n == NULL)
+ return NULL;
+
+ n->xattr_idx = 0xFFFFFFFF;
+ n->uid = sb->st_uid;
+ n->gid = sb->st_gid;
+ n->mode = sb->st_mode;
+ n->mod_time = sb->st_mtime;
+ n->link_count = 1;
+ n->name = (char *)n->payload;
+ memcpy(n->name, name, name_len);
+
+ if (extra != NULL) {
+ ptr = n->name + name_len + 1;
+ strcpy(ptr, extra);
+ } else {
+ ptr = NULL;
+ }
+
+ switch (sb->st_mode & S_IFMT) {
+ case S_IFREG:
+ n->data.file.input_file = ptr;
+ break;
+ case S_IFLNK:
+ n->mode = S_IFLNK | 0777;
+ n->data.target = ptr;
+ break;
+ case S_IFBLK:
+ case S_IFCHR:
+ n->data.devno = sb->st_rdev;
+ break;
+ case S_IFDIR:
+ n->link_count = 2;
+ break;
+ default:
+ break;
+ }
- memset(&sb, 0, sizeof(sb));
- sb.st_mode = S_IFDIR | (defaults->mode & 07777);
- sb.st_uid = defaults->uid;
- sb.st_gid = defaults->gid;
- sb.st_mtime = defaults->mtime;
+ if (parent->link_count == 0xFFFFFFFF) {
+ free(n);
+ errno = EMLINK;
+ return NULL;
+ }
+
+ insert_sorted(parent, n);
+ parent->link_count++;
+ return n;
+}
- fs->root = fstree_mknode(NULL, "", 0, NULL, &sb);
+int fstree_init(fstree_t *fs, const fstree_defaults_t *defaults)
+{
+ memset(fs, 0, sizeof(*fs));
+ fs->defaults = *defaults;
+ fs->root = calloc(1, sizeof(tree_node_t) + 1);
if (fs->root == NULL) {
perror("initializing file system tree");
return -1;
}
+ fs->root->xattr_idx = 0xFFFFFFFF;
+ fs->root->uid = defaults->uid;
+ fs->root->gid = defaults->gid;
+ fs->root->mode = S_IFDIR | (defaults->mode & 07777);
+ fs->root->mod_time = defaults->mtime;
+ fs->root->link_count = 2;
+ fs->root->name = (char *)fs->root->payload;
fs->root->flags |= FLAG_DIR_CREATED_IMPLICITLY;
return 0;
}
@@ -57,3 +153,104 @@ void fstree_cleanup(fstree_t *fs)
free(fs->inodes);
memset(fs, 0, sizeof(*fs));
}
+
+tree_node_t *fstree_get_node_by_path(fstree_t *fs, tree_node_t *root,
+ const char *path, bool create_implicitly,
+ bool stop_at_parent)
+{
+ const char *end;
+ tree_node_t *n;
+ size_t len;
+
+ while (*path != '\0') {
+ while (*path == '/')
+ ++path;
+
+ if (!S_ISDIR(root->mode)) {
+ errno = ENOTDIR;
+ return NULL;
+ }
+
+ end = strchr(path, '/');
+ if (end == NULL) {
+ if (stop_at_parent)
+ break;
+
+ len = strlen(path);
+ } else {
+ len = end - path;
+ }
+
+ n = child_by_name(root, path, len);
+
+ if (n == NULL) {
+ struct stat sb;
+
+ if (!create_implicitly) {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ memset(&sb, 0, sizeof(sb));
+ sb.st_mode = S_IFDIR | (fs->defaults.mode & 07777);
+ sb.st_uid = fs->defaults.uid;
+ sb.st_gid = fs->defaults.gid;
+ sb.st_mtime = fs->defaults.mtime;
+
+ n = mknode(root, path, len, NULL, &sb);
+ if (n == NULL)
+ return NULL;
+
+ n->flags |= FLAG_DIR_CREATED_IMPLICITLY;
+ }
+
+ root = n;
+ path = path + len;
+ }
+
+ return root;
+}
+
+tree_node_t *fstree_add_generic(fstree_t *fs, const char *path,
+ const struct stat *sb, const char *extra)
+{
+ tree_node_t *child, *parent;
+ const char *name;
+
+ if (S_ISLNK(sb->st_mode) && extra == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (*path == '\0') {
+ child = fs->root;
+ assert(child != NULL);
+ goto out;
+ }
+
+ parent = fstree_get_node_by_path(fs, fs->root, path, true, true);
+ if (parent == NULL)
+ return NULL;
+
+ name = strrchr(path, '/');
+ name = (name == NULL ? path : (name + 1));
+
+ child = child_by_name(parent, name, strlen(name));
+out:
+ if (child != NULL) {
+ if (!S_ISDIR(child->mode) || !S_ISDIR(sb->st_mode) ||
+ !(child->flags & FLAG_DIR_CREATED_IMPLICITLY)) {
+ errno = EEXIST;
+ return NULL;
+ }
+
+ child->uid = sb->st_uid;
+ child->gid = sb->st_gid;
+ child->mode = sb->st_mode;
+ child->mod_time = sb->st_mtime;
+ child->flags &= ~FLAG_DIR_CREATED_IMPLICITLY;
+ return child;
+ }
+
+ return mknode(parent, name, strlen(name), extra, sb);
+}
diff --git a/lib/fstree/src/get_by_path.c b/lib/fstree/src/get_by_path.c
deleted file mode 100644
index 133f412..0000000
--- a/lib/fstree/src/get_by_path.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * get_by_path.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include "fstree.h"
-
-#include <string.h>
-#include <errno.h>
-
-static tree_node_t *child_by_name(tree_node_t *root, const char *name,
- size_t len)
-{
- tree_node_t *n = root->data.children;
-
- while (n != NULL) {
- if (strncmp(n->name, name, len) == 0 && n->name[len] == '\0')
- break;
-
- n = n->next;
- }
-
- return n;
-}
-
-tree_node_t *fstree_get_node_by_path(fstree_t *fs, tree_node_t *root,
- const char *path, bool create_implicitly,
- bool stop_at_parent)
-{
- const char *end;
- tree_node_t *n;
- size_t len;
-
- while (*path != '\0') {
- while (*path == '/')
- ++path;
-
- if (!S_ISDIR(root->mode)) {
- errno = ENOTDIR;
- return NULL;
- }
-
- end = strchr(path, '/');
- if (end == NULL) {
- if (stop_at_parent)
- break;
-
- len = strlen(path);
- } else {
- len = end - path;
- }
-
- n = child_by_name(root, path, len);
-
- if (n == NULL) {
- struct stat sb;
-
- if (!create_implicitly) {
- errno = ENOENT;
- return NULL;
- }
-
- memset(&sb, 0, sizeof(sb));
- sb.st_mode = S_IFDIR | (fs->defaults.mode & 07777);
- sb.st_uid = fs->defaults.uid;
- sb.st_gid = fs->defaults.gid;
- sb.st_mtime = fs->defaults.mtime;
-
- n = fstree_mknode(root, path, len, NULL, &sb);
- if (n == NULL)
- return NULL;
-
- n->flags |= FLAG_DIR_CREATED_IMPLICITLY;
- }
-
- root = n;
- path = path + len;
- }
-
- return root;
-}
diff --git a/lib/fstree/src/mknode.c b/lib/fstree/src/mknode.c
deleted file mode 100644
index a48cf06..0000000
--- a/lib/fstree/src/mknode.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * mknode.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-#include "fstree.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-static void insert_sorted(tree_node_t *root, tree_node_t *n)
-{
- tree_node_t *it = root->data.children, *prev = NULL;
-
- while (it != NULL && strcmp(it->name, n->name) < 0) {
- prev = it;
- it = it->next;
- }
-
- n->parent = root;
- n->next = it;
-
- if (prev == NULL) {
- root->data.children = n;
- } else {
- prev->next = n;
- }
-}
-
-tree_node_t *fstree_mknode(tree_node_t *parent, const char *name,
- size_t name_len, const char *extra,
- const struct stat *sb)
-{
- tree_node_t *n;
- size_t size;
- char *ptr;
-
- if (S_ISLNK(sb->st_mode) && extra == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- size = sizeof(tree_node_t) + name_len + 1;
- if (extra != NULL)
- size += strlen(extra) + 1;
-
- n = calloc(1, size);
- if (n == NULL)
- return NULL;
-
- n->xattr_idx = 0xFFFFFFFF;
- n->uid = sb->st_uid;
- n->gid = sb->st_gid;
- n->mode = sb->st_mode;
- n->mod_time = sb->st_mtime;
- n->link_count = 1;
- n->name = (char *)n->payload;
- memcpy(n->name, name, name_len);
-
- if (extra != NULL) {
- ptr = n->name + name_len + 1;
- strcpy(ptr, extra);
- } else {
- ptr = NULL;
- }
-
- switch (sb->st_mode & S_IFMT) {
- case S_IFREG:
- n->data.file.input_file = ptr;
- break;
- case S_IFLNK:
- n->mode = S_IFLNK | 0777;
- n->data.target = ptr;
- break;
- case S_IFBLK:
- case S_IFCHR:
- n->data.devno = sb->st_rdev;
- break;
- case S_IFDIR:
- n->link_count = 2;
- break;
- default:
- break;
- }
-
- if (parent != NULL) {
- if (parent->link_count == 0xFFFFFFFF) {
- free(n);
- errno = EMLINK;
- return NULL;
- }
-
- insert_sorted(parent, n);
- parent->link_count++;
- }
-
- return n;
-}