From: Karel Zak Date: Wed, 23 Jun 2010 08:18:43 +0000 (+0200) Subject: libmount: add /etc/fstab.d support X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9826a63737086a8c28353de878b4bf3e1d5caa2b;p=util-linux libmount: add /etc/fstab.d support Signed-off-by: Karel Zak --- diff --git a/include/pathnames.h b/include/pathnames.h index efbd6a65..ab21bd78 100644 --- a/include/pathnames.h +++ b/include/pathnames.h @@ -100,6 +100,8 @@ # endif #endif +#define _PATH_MNTTAB_DIR _PATH_MNTTAB ".d" + #define _PATH_MOUNTED_LOCK _PATH_MOUNTED "~" #define _PATH_MOUNTED_TMP _PATH_MOUNTED ".tmp" diff --git a/shlibs/mount/src/Makefile.am b/shlibs/mount/src/Makefile.am index aebd3cc5..0494a7a0 100644 --- a/shlibs/mount/src/Makefile.am +++ b/shlibs/mount/src/Makefile.am @@ -13,6 +13,7 @@ libmount_la_SOURCES = mountP.h version.c utils.c test.c init.c cache.c \ optstr.c optmap.c optent.c optls.c iter.c lock.c \ fs.c tab.c tab_parse.c \ $(mountinc_HEADERS) \ + $(top_srcdir)/lib/at.c \ $(top_srcdir)/include/list.h \ $(top_srcdir)/lib/mangle.c \ $(top_srcdir)/lib/canonicalize.c diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in index ac1aef40..6e76ddb2 100644 --- a/shlibs/mount/src/mount.h.in +++ b/shlibs/mount/src/mount.h.in @@ -267,6 +267,7 @@ extern int mnt_fs_print_debug(mnt_fs *ent, FILE *file); extern mnt_tab *mnt_new_tab_from_file(const char *filename); extern int mnt_tab_parse_stream(mnt_tab *tb, FILE *f, const char *filename); extern int mnt_tab_parse_file(mnt_tab *tb, const char *filename); +extern int mnt_tab_parse_fstab(mnt_tab *tb); extern int mnt_tab_set_parser_errcb(mnt_tab *tb, int (*cb)(mnt_tab *tb, const char *filename, int line, int flag)); diff --git a/shlibs/mount/src/mount.sym b/shlibs/mount/src/mount.sym index 8f930967..f3c10689 100644 --- a/shlibs/mount/src/mount.sym +++ b/shlibs/mount/src/mount.sym @@ -121,6 +121,7 @@ global: mnt_tab_next_child_fs; mnt_tab_next_fs; mnt_tab_parse_file; + mnt_tab_parse_fstab; mnt_tab_parse_stream; mnt_tab_remove_fs; mnt_tab_set_cache; diff --git a/shlibs/mount/src/mountP.h b/shlibs/mount/src/mountP.h index c804b5de..d217e3da 100644 --- a/shlibs/mount/src/mountP.h +++ b/shlibs/mount/src/mountP.h @@ -47,6 +47,9 @@ extern int libmount_debug_mask; #define DBG(m,x) #endif +/* extension for files in the /etc/fstab.d directory */ +#define MNT_MNTTABDIR_EXT ".fstab" + #ifdef TEST_PROGRAM struct mtest { const char *name; diff --git a/shlibs/mount/src/tab_parse.c b/shlibs/mount/src/tab_parse.c index d82be5ab..e7cc7ef4 100644 --- a/shlibs/mount/src/tab_parse.c +++ b/shlibs/mount/src/tab_parse.c @@ -9,10 +9,16 @@ #include #include #include +#include +#include +#include +#include #include "nls.h" +#include "at.h" #include "mangle.h" #include "mountP.h" +#include "pathnames.h" static inline char *skip_spaces(char *s) { @@ -416,7 +422,7 @@ error: * @tb: tab pointer * @filename: file * - * Parses whole table (e.g. /etc/fstab). + * Parses whole table (e.g. /etc/mtab) and appends new records to the @tab. * * * @@ -458,7 +464,10 @@ int mnt_tab_parse_file(mnt_tab *tb, const char *filename) * mnt_new_tab_from_file: * @filename: /etc/{m,fs}tab or /proc/self/mountinfo path * - * Same as mnt_new_tab() + mnt_tab_parse_file(). + * Same as mnt_new_tab() + mnt_tab_parse_file(). Use this function for private + * files only. This function does not allow to use error callback, so you + * cannot provide any feedback to end-users about broken records in files (e.g. + * fstab). * * Returns: newly allocated tab on success and NULL in case of error. */ @@ -497,3 +506,99 @@ int mnt_tab_set_parser_errcb(mnt_tab *tb, return 0; } +/** + * mnt_tab_parse_fstab: + * @tb: table + * + * This function parses /etc/fstab or /etc/fstab.d and appends new lines to the + * @tab. If the system contains classic fstab file and also fstab.d directory + * then the fstab file is parsed before the fstab.d directory. + * + * The fstab.d directory: + * - files are sorted by strverscmp(3) + * - files that starts with "." are ignored (e.g. ".10foo.fstab") + * - files without the ".fstab" extension are ignored + * + * See also mnt_tab_set_parser_errcb(). + * + * Returns: 0 on success (least one record has been sucessfully parsed) or -1. + */ +int mnt_tab_parse_fstab(mnt_tab *tb) +{ + int num, n = 0, i; + DIR *dir = NULL; + FILE *f; + struct dirent **namelist = NULL; + + assert(tb); + if (!tb) + return -1; + + num = mnt_tab_get_nents(tb); + + /* classic fstab */ + { + f = fopen(_PATH_MNTTAB, "r"); + if (f) { + mnt_tab_parse_stream(tb, f, _PATH_MNTTAB); + fclose(f); + } + } + + /* TODO: it would be nice to have a scandir() implemenation that + * is able to use already opened directory */ + n = scandir(_PATH_MNTTAB_DIR, &namelist, NULL, versionsort); + if (n <= 0) + goto done; + + /* let use "at" functions rather than play crazy games with paths... */ + dir = opendir(_PATH_MNTTAB_DIR); + if (!dir) + goto done; + + for (i = 0; i < n; i++) { + struct dirent *d = namelist[i]; + struct stat st; + size_t namesz; + +#ifdef _DIRENT_HAVE_D_TYPE + if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG && + d->d_type != DT_LNK) + continue; +#endif + if (*d->d_name == '.') + continue; + +#define MNT_MNTTABDIR_EXTSIZ (sizeof(MNT_MNTTABDIR_EXT) - 1) + + namesz = strlen(d->d_name); + if (!namesz || namesz < MNT_MNTTABDIR_EXTSIZ + 1 || + strcmp(d->d_name + (namesz - MNT_MNTTABDIR_EXTSIZ), + MNT_MNTTABDIR_EXT)) + continue; + + if (fstat_at(dirfd(dir), _PATH_MNTTAB_DIR, d->d_name, &st, 0) || + !S_ISREG(st.st_mode)) + continue; + + f = fopen_at(dirfd(dir), _PATH_MNTTAB_DIR, + d->d_name, O_RDONLY, "r"); + if (f) { + mnt_tab_parse_stream(tb, f, d->d_name); + fclose(f); + } + } +done: + for (i = 0; i < n; i++) + free(namelist[i]); + free(namelist); + if (dir) + closedir(dir); + + num = mnt_tab_get_nents(tb) - num; + + DBG(DEBUG_TAB, fprintf(stderr, + "libmount: tab %p: fstab contains %d records\n", tb, num)); + + return num > 0 ? 0 : -1; +}