]> err.no Git - util-linux/commitdiff
libmount: add /etc/fstab.d support
authorKarel Zak <kzak@redhat.com>
Wed, 23 Jun 2010 08:18:43 +0000 (10:18 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Jan 2011 11:28:39 +0000 (12:28 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
include/pathnames.h
shlibs/mount/src/Makefile.am
shlibs/mount/src/mount.h.in
shlibs/mount/src/mount.sym
shlibs/mount/src/mountP.h
shlibs/mount/src/tab_parse.c

index efbd6a65c393c6c18e0ea2f4517898d0675f64f2..ab21bd785a287903cf39101e4b601f0995dc8681 100644 (file)
 # endif
 #endif
 
+#define _PATH_MNTTAB_DIR       _PATH_MNTTAB ".d"
+
 #define _PATH_MOUNTED_LOCK     _PATH_MOUNTED "~"
 #define _PATH_MOUNTED_TMP      _PATH_MOUNTED ".tmp"
 
index aebd3cc510691b35d0d1a1c6bfac78cc5ef5b7c9..0494a7a049b6266ab990986aaca4e1b2b1078e7c 100644 (file)
@@ -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
index ac1aef403f7099a6246de88f1465f227db7e736b..6e76ddb28ba64b9300a771d9eaf24bf4721f767a 100644 (file)
@@ -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));
 
index 8f930967cba0f587cf115c4a73112e3d49072435..f3c10689ae770295af15c2e522e321a18c883b21 100644 (file)
@@ -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;
index c804b5de4c54d33687614ac210560712b047f61e..d217e3da310a0a5306a1e22e10bc807128346bbc 100644 (file)
@@ -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;
index d82be5abab236d48974bf13e73ef41d444c0f3de..e7cc7ef4977baf5d47031d2faca3b5650f9c6659 100644 (file)
@@ -9,10 +9,16 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
 
 #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.
  *
  * <informalexample>
  *   <programlisting>
@@ -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;
+}