From 41ac289ca572cf0ed5ecfcc1c73ae59eef461a9e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 29 Aug 2019 23:45:45 -0400 Subject: mtab: Lazy-load the device IDs from the mount table Fixes #50. --- mtab.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/mtab.c b/mtab.c index a06508b..57ea402 100644 --- a/mtab.c +++ b/mtab.c @@ -15,6 +15,7 @@ ****************************************************************************/ #include "mtab.h" +#include "darray.h" #include "trie.h" #include "util.h" #include @@ -49,42 +50,56 @@ # include #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); } -- cgit v1.2.3