diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2019-08-29 23:45:45 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2019-08-29 23:45:45 -0400 |
commit | 41ac289ca572cf0ed5ecfcc1c73ae59eef461a9e (patch) | |
tree | 1354f9064ef2951f8d4eb6daa6a807d1d7eb276b /mtab.c | |
parent | 7716a6ef1a60d4597e06cc4d412c3483b29877bc (diff) | |
download | bfs-41ac289ca572cf0ed5ecfcc1c73ae59eef461a9e.tar.xz |
mtab: Lazy-load the device IDs from the mount table
Fixes #50.
Diffstat (limited to 'mtab.c')
-rw-r--r-- | mtab.c | 93 |
1 files changed, 66 insertions, 27 deletions
@@ -15,6 +15,7 @@ ****************************************************************************/ #include "mtab.h" +#include "darray.h" #include "trie.h" #include "util.h" #include <errno.h> @@ -49,42 +50,56 @@ # include <sys/mnttab.h> #endif +/** + * A mount point in the table. + */ +struct bfs_mtab_entry { + /** The path to the mount point. */ + char *path; + /** The filesystem type. */ + char *type; +}; + struct bfs_mtab { - /** A map from device ID to file system type. */ - struct trie types; - /** The names of all the mount points. */ + /** The list of mount points. */ + struct bfs_mtab_entry *entries; + /** The basenames of every mount point. */ struct trie names; + + /** A map from device ID to fstype (populated lazily). */ + struct trie types; + /** Whether the types map has been populated. */ + bool types_filled; }; /** * Add an entry to the mount table. */ static int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *type) { - if (!trie_insert_str(&mtab->names, xbasename(path))) { - return -1; - } + struct bfs_mtab_entry entry = { + .path = strdup(path), + .type = strdup(type), + }; - struct bfs_stat sb; - if (bfs_stat(AT_FDCWD, path, BFS_STAT_NOFOLLOW | BFS_STAT_NOSYNC, &sb) != 0) { - return 0; + if (!entry.path || !entry.type) { + goto fail_entry; } - struct trie_leaf *leaf = trie_insert_mem(&mtab->types, &sb.dev, sizeof(sb.dev)); - if (!leaf) { - return -1; + if (DARRAY_PUSH(&mtab->entries, &entry) != 0) { + goto fail_entry; } - if (leaf->value) { - return 0; + if (!trie_insert_str(&mtab->names, xbasename(path))) { + goto fail; } - leaf->value = strdup(type); - if (leaf->value) { - return 0; - } else { - trie_remove(&mtab->types, leaf); - return -1; - } + return 0; + +fail_entry: + free(entry.type); + free(entry.path); +fail: + return -1; } struct bfs_mtab *parse_bfs_mtab() { @@ -93,8 +108,10 @@ struct bfs_mtab *parse_bfs_mtab() { return NULL; } - trie_init(&mtab->types); + mtab->entries = NULL; trie_init(&mtab->names); + trie_init(&mtab->types); + mtab->types_filled = false; int error = 0; @@ -171,7 +188,29 @@ fail: return NULL; } +static void bfs_mtab_fill_types(struct bfs_mtab *mtab) { + for (size_t i = 0; i < darray_length(mtab->entries); ++i) { + struct bfs_mtab_entry *entry = mtab->entries + i; + + struct bfs_stat sb; + if (bfs_stat(AT_FDCWD, entry->path, BFS_STAT_NOFOLLOW | BFS_STAT_NOSYNC, &sb) != 0) { + continue; + } + + struct trie_leaf *leaf = trie_insert_mem(&mtab->types, &sb.dev, sizeof(sb.dev)); + if (leaf) { + leaf->value = entry->type; + } + } + + mtab->types_filled = true; +} + const char *bfs_fstype(const struct bfs_mtab *mtab, const struct bfs_stat *statbuf) { + if (!mtab->types_filled) { + bfs_mtab_fill_types((struct bfs_mtab *)mtab); + } + const struct trie_leaf *leaf = trie_find_mem(&mtab->types, &statbuf->dev, sizeof(statbuf->dev)); if (leaf) { return leaf->value; @@ -187,14 +226,14 @@ bool bfs_maybe_mount(const struct bfs_mtab *mtab, const char *path) { void free_bfs_mtab(struct bfs_mtab *mtab) { if (mtab) { + trie_destroy(&mtab->types); trie_destroy(&mtab->names); - struct trie_leaf *leaf; - while ((leaf = trie_first_leaf(&mtab->types))) { - free(leaf->value); - trie_remove(&mtab->types, leaf); + for (size_t i = 0; i < darray_length(mtab->entries); ++i) { + free(mtab->entries[i].type); + free(mtab->entries[i].path); } - trie_destroy(&mtab->types); + darray_free(mtab->entries); free(mtab); } |