summaryrefslogtreecommitdiffstats
path: root/mtab.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-02-13 11:12:30 -0500
committerTavian Barnes <tavianator@tavianator.com>2019-03-06 23:01:19 -0800
commit0689a4a16f5e80e0c2368f4a68c69ce5f2fdc038 (patch)
tree60301a8961c72698b44291ecb0473e24c61f923a /mtab.c
parent7fc960a23eab7fce9f5e0666b1a9b3f5eae832af (diff)
downloadbfs-0689a4a16f5e80e0c2368f4a68c69ce5f2fdc038.tar.xz
bftw: Work around d_type being wrong for bind mounts on Linux
C.f. https://savannah.gnu.org/bugs/?54913 C.f. https://lkml.org/lkml/2019/2/11/2027 Fixes https://github.com/tavianator/bfs/issues/37
Diffstat (limited to 'mtab.c')
-rw-r--r--mtab.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/mtab.c b/mtab.c
index 0887f49..e2b89c9 100644
--- a/mtab.c
+++ b/mtab.c
@@ -19,6 +19,7 @@
#include "util.h"
#include <errno.h>
#include <fcntl.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -49,13 +50,20 @@
#endif
struct bfs_mtab {
+ /** A map from device ID to file system type. */
struct trie types;
+ /** The names of all the mount points. */
+ struct trie names;
};
/**
* Add an entry to the mount table.
*/
-static int bfs_mtab_add(struct bfs_mtab *mtab, dev_t dev, const char *type) {
+static int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, dev_t dev, const char *type) {
+ if (!trie_insert_str(&mtab->names, xbasename(path))) {
+ return -1;
+ }
+
struct trie_leaf *leaf = trie_insert_mem(&mtab->types, &dev, sizeof(dev));
if (!leaf) {
return -1;
@@ -91,6 +99,7 @@ struct bfs_mtab *parse_bfs_mtab() {
goto fail_file;
}
trie_init(&mtab->types);
+ trie_init(&mtab->names);
struct mntent *mnt;
while ((mnt = getmntent(file))) {
@@ -99,7 +108,7 @@ struct bfs_mtab *parse_bfs_mtab() {
continue;
}
- if (bfs_mtab_add(mtab, sb.dev, mnt->mnt_type) != 0) {
+ if (bfs_mtab_add(mtab, mnt->mnt_dir, sb.dev, mnt->mnt_type) != 0) {
goto fail_mtab;
}
}
@@ -127,6 +136,7 @@ fail:
goto fail;
}
trie_init(&mtab->types);
+ trie_init(&mtab->names);
for (struct statfs *mnt = mntbuf; mnt < mntbuf + size; ++mnt) {
struct bfs_stat sb;
@@ -134,7 +144,7 @@ fail:
continue;
}
- if (bfs_mtab_add(mtab, sb.dev, mnt->f_fstypename) != 0) {
+ if (bfs_mtab_add(mtab, mnt->f_mntonname, sb.dev, mnt->f_fstypename) != 0) {
goto fail_mtab;
}
}
@@ -158,6 +168,7 @@ fail:
goto fail_file;
}
trie_init(&mtab->types);
+ trie_init(&mtab->names);
struct mnttab mnt;
while (getmntent(file, &mnt) == 0) {
@@ -166,7 +177,7 @@ fail:
continue;
}
- if (bfs_mtab_add(mtab, sb.dev, mnt.mnt_fstype) != 0) {
+ if (bfs_mtab_add(mtab, mnt.mnt_mountp, sb.dev, mnt.mnt_fstype) != 0) {
goto fail_mtab;
}
}
@@ -197,15 +208,22 @@ const char *bfs_fstype(const struct bfs_mtab *mtab, const struct bfs_stat *statb
}
}
+bool bfs_maybe_mount(const struct bfs_mtab *mtab, const char *path) {
+ const char *name = xbasename(path);
+ return trie_find_str(&mtab->names, name);
+}
+
void free_bfs_mtab(struct bfs_mtab *mtab) {
if (mtab) {
+ trie_destroy(&mtab->names);
+
struct trie_leaf *leaf;
while ((leaf = trie_first_leaf(&mtab->types))) {
free((char *)leaf->value);
trie_remove_mem(&mtab->types, leaf->key, leaf->length);
}
-
trie_destroy(&mtab->types);
+
free(mtab);
}
}