diff options
Diffstat (limited to 'mtab.c')
-rw-r--r-- | mtab.c | 246 |
1 files changed, 0 insertions, 246 deletions
@@ -1,246 +0,0 @@ -/**************************************************************************** - * bfs * - * Copyright (C) 2017-2020 Tavian Barnes <tavianator@tavianator.com> * - * * - * Permission to use, copy, modify, and/or distribute this software for any * - * purpose with or without fee is hereby granted. * - * * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - ****************************************************************************/ - -#include "mtab.h" -#include "darray.h" -#include "stat.h" -#include "trie.h" -#include "util.h" -#include <errno.h> -#include <fcntl.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> - -#if BFS_HAS_SYS_PARAM -# include <sys/param.h> -#endif - -#if BFS_HAS_MNTENT -# define BFS_MNTENT 1 -#elif BSD -# define BFS_MNTINFO 1 -#elif __SVR4 -# define BFS_MNTTAB 1 -#endif - -#if BFS_MNTENT -# include <mntent.h> -# include <paths.h> -# include <stdio.h> -#elif BFS_MNTINFO -# include <sys/mount.h> -# include <sys/ucred.h> -#elif BFS_MNTTAB -# include <stdio.h> -# 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 { - /** 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) { - struct bfs_mtab_entry entry = { - .path = strdup(path), - .type = strdup(type), - }; - - if (!entry.path || !entry.type) { - goto fail_entry; - } - - if (DARRAY_PUSH(&mtab->entries, &entry) != 0) { - goto fail_entry; - } - - if (!trie_insert_str(&mtab->names, xbasename(path))) { - goto fail; - } - - return 0; - -fail_entry: - free(entry.type); - free(entry.path); -fail: - return -1; -} - -struct bfs_mtab *bfs_mtab_parse(void) { - struct bfs_mtab *mtab = malloc(sizeof(*mtab)); - if (!mtab) { - return NULL; - } - - mtab->entries = NULL; - trie_init(&mtab->names); - trie_init(&mtab->types); - mtab->types_filled = false; - - int error = 0; - -#if BFS_MNTENT - - FILE *file = setmntent(_PATH_MOUNTED, "r"); - if (!file) { - // In case we're in a chroot or something with /proc but no /etc/mtab - error = errno; - file = setmntent("/proc/mounts", "r"); - } - if (!file) { - goto fail; - } - - struct mntent *mnt; - while ((mnt = getmntent(file))) { - if (bfs_mtab_add(mtab, mnt->mnt_dir, mnt->mnt_type) != 0) { - error = errno; - endmntent(file); - goto fail; - } - } - - endmntent(file); - -#elif BFS_MNTINFO - -#if __NetBSD__ - typedef struct statvfs bfs_statfs; -#else - typedef struct statfs bfs_statfs; -#endif - - bfs_statfs *mntbuf; - int size = getmntinfo(&mntbuf, MNT_WAIT); - if (size < 0) { - error = errno; - goto fail; - } - - for (bfs_statfs *mnt = mntbuf; mnt < mntbuf + size; ++mnt) { - if (bfs_mtab_add(mtab, mnt->f_mntonname, mnt->f_fstypename) != 0) { - error = errno; - goto fail; - } - } - -#elif BFS_MNTTAB - - FILE *file = xfopen(MNTTAB, O_RDONLY | O_CLOEXEC); - if (!file) { - error = errno; - goto fail; - } - - struct mnttab mnt; - while (getmntent(file, &mnt) == 0) { - if (bfs_mtab_add(mtab, mnt.mnt_mountp, mnt.mnt_fstype) != 0) { - error = errno; - fclose(file); - goto fail; - } - } - - fclose(file); - -#else - - error = ENOTSUP; - goto fail; - -#endif - - return mtab; - -fail: - bfs_mtab_free(mtab); - errno = error; - 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; - } else { - return "unknown"; - } -} - -bool bfs_might_be_mount(const struct bfs_mtab *mtab, const char *path) { - const char *name = xbasename(path); - return trie_find_str(&mtab->names, name); -} - -void bfs_mtab_free(struct bfs_mtab *mtab) { - if (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); - } -} |