diff options
Diffstat (limited to 'src/mtab.c')
-rw-r--r-- | src/mtab.c | 101 |
1 files changed, 57 insertions, 44 deletions
@@ -2,24 +2,27 @@ // SPDX-License-Identifier: 0BSD #include "mtab.h" + #include "alloc.h" +#include "bfs.h" #include "bfstd.h" -#include "config.h" -#include "darray.h" #include "stat.h" #include "trie.h" + #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> -#if !defined(BFS_USE_MNTENT) && BFS_USE_MNTENT_H -# define BFS_USE_MNTENT true -#elif !defined(BFS_USE_MNTINFO) && BSD -# define BFS_USE_MNTINFO true -#elif !defined(BFS_USE_MNTTAB) && __SVR4 -# define BFS_USE_MNTTAB true +#ifndef BFS_USE_MNTENT +# define BFS_USE_MNTENT BFS_HAS_GETMNTENT_1 +#endif +#ifndef BFS_USE_MNTINFO +# define BFS_USE_MNTINFO (!BFS_USE_MNTENT && BFS_HAS_GETMNTINFO) +#endif +#ifndef BFS_USE_MNTTAB +# define BFS_USE_MNTTAB (!BFS_USE_MNTINFO && BFS_HAS_GETMNTENT_2) #endif #if BFS_USE_MNTENT @@ -28,7 +31,6 @@ # include <stdio.h> #elif BFS_USE_MNTINFO # include <sys/mount.h> -# include <sys/ucred.h> #elif BFS_USE_MNTTAB # include <stdio.h> # include <sys/mnttab.h> @@ -37,16 +39,24 @@ /** * A mount point in the table. */ -struct bfs_mtab_entry { +struct bfs_mount { /** The path to the mount point. */ char *path; /** The filesystem type. */ char *type; + /** Buffer for the strings. */ + char buf[]; }; struct bfs_mtab { + /** Mount point arena. */ + struct varena varena; + /** The array of mount points. */ - struct bfs_mtab_entry *entries; + struct bfs_mount **mounts; + /** The number of mount points. */ + size_t nmounts; + /** The basenames of every mount point. */ struct trie names; @@ -59,31 +69,39 @@ struct bfs_mtab { /** * Add an entry to the mount table. */ -static inline int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *type) { - struct bfs_mtab_entry entry = { - .path = strdup(path), - .type = strdup(type), - }; - - if (!entry.path || !entry.type) { - goto fail_entry; +_maybe_unused +static int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *type) { + size_t path_size = strlen(path) + 1; + size_t type_size = strlen(type) + 1; + size_t size = path_size + type_size; + struct bfs_mount *mount = varena_alloc(&mtab->varena, size); + if (!mount) { + return -1; } - if (DARRAY_PUSH(&mtab->entries, &entry) != 0) { - goto fail_entry; + struct bfs_mount **ptr = RESERVE(struct bfs_mount *, &mtab->mounts, &mtab->nmounts); + if (!ptr) { + goto free; } + *ptr = mount; + + mount->path = mount->buf; + memcpy(mount->path, path, path_size); + + mount->type = mount->buf + path_size; + memcpy(mount->type, type, type_size); const char *name = path + xbaseoff(path); if (!trie_insert_str(&mtab->names, name)) { - goto fail; + goto shrink; } return 0; -fail_entry: - free(entry.type); - free(entry.path); -fail: +shrink: + --mtab->nmounts; +free: + varena_free(&mtab->varena, mount, size); return -1; } @@ -93,6 +111,8 @@ struct bfs_mtab *bfs_mtab_parse(void) { return NULL; } + VARENA_INIT(&mtab->varena, struct bfs_mount, buf); + trie_init(&mtab->names); trie_init(&mtab->types); @@ -131,7 +151,7 @@ struct bfs_mtab *bfs_mtab_parse(void) { bfs_statfs *mntbuf; int size = getmntinfo(&mntbuf, MNT_WAIT); - if (size < 0) { + if (size <= 0) { error = errno; goto fail; } @@ -193,9 +213,9 @@ static int bfs_mtab_fill_types(struct bfs_mtab *mtab) { int parent_ret = -1; struct bfs_stat parent_stat; - for (size_t i = 0; i < darray_length(mtab->entries); ++i) { - struct bfs_mtab_entry *entry = &mtab->entries[i]; - const char *path = entry->path; + for (size_t i = 0; i < mtab->nmounts; ++i) { + struct bfs_mount *mount = mtab->mounts[i]; + const char *path = mount->path; int fd = AT_FDCWD; char *dir = xdirname(path); @@ -236,10 +256,7 @@ static int bfs_mtab_fill_types(struct bfs_mtab *mtab) { continue; } - struct trie_leaf *leaf = trie_insert_mem(&mtab->types, &sb.dev, sizeof(sb.dev)); - if (leaf) { - leaf->value = entry->type; - } else { + if (trie_set_mem(&mtab->types, &sb.mnt_id, sizeof(sb.mnt_id), mount->type) != 0) { goto fail; } } @@ -262,16 +279,15 @@ const char *bfs_fstype(const struct bfs_mtab *mtab, const struct bfs_stat *statb } } - const struct trie_leaf *leaf = trie_find_mem(&mtab->types, &statbuf->dev, sizeof(statbuf->dev)); - if (leaf) { - return leaf->value; + const char *type = trie_get_mem(&mtab->types, &statbuf->mnt_id, sizeof(statbuf->mnt_id)); + if (type) { + return type; } else { return "unknown"; } } -bool bfs_might_be_mount(const struct bfs_mtab *mtab, const char *path) { - const char *name = path + xbaseoff(path); +bool bfs_might_be_mount(const struct bfs_mtab *mtab, const char *name) { return trie_find_str(&mtab->names, name); } @@ -280,11 +296,8 @@ void bfs_mtab_free(struct bfs_mtab *mtab) { trie_destroy(&mtab->types); trie_destroy(&mtab->names); - for (size_t i = 0; i < darray_length(mtab->entries); ++i) { - free(mtab->entries[i].type); - free(mtab->entries[i].path); - } - darray_free(mtab->entries); + free(mtab->mounts); + varena_destroy(&mtab->varena); free(mtab); } |