[systemd-devel] [PATCH ] Adding /etc/fstab.d/*.fstab support

Masatake YAMATO yamato at redhat.com
Thu Jan 19 22:52:45 PST 2012


mount command in the latest version of util-linux(2.21-rc1[1])
supports /etc/fstab.d; mount command reads /etc/fstab.d/*.fstab
files as if they are written in /etc/fstab.

The benefits of .d mechanism are explained in [2][3].

With this patch, systemd can handle /etc/fstab.d/*.fstab.

How to try it:

    1. get the latest source code of uilt-linux[1]
    2. Build and install it with ./configure --enable-libmount-mount --prefix=/usr
    3. Apply this patch to systemd, build, and install
    4. Prepare /etc/fstab.d/
    5. Make /etc/fstab.d/test.fstab with something following contents:
       /dev/something-new-mkfs.ext4'ed-partition /mnt-or-somewhere ext4 defaults 1 3
    6. Reboot
    7. You will see a file system is monuted on /mnt-or-somewhere

[1] http://marc.info/?l=util-linux-ng&m=132696552311802&w=2
[2] http://article.gmane.org/gmane.linux.nfs/38882/match=exports+d
[3] http://comments.gmane.org/gmane.linux.kernel.autofs/5939

Signed-off-by: Masatake YAMATO <yamato at redhat.com>


index 47422cc..d319104 100644
--- a/src/mount.c
+++ b/src/mount.c
@@ -19,6 +19,10 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
 #include <errno.h>
 #include <stdio.h>
 #include <mntent.h>
@@ -1503,7 +1507,7 @@ static int mount_find_pri(char *options) {
         return (int) r;
 }
 
-static int mount_load_etc_fstab(Manager *m) {
+static int mount_load_etc_fstab(Manager *m, const char* fname) {
         FILE *f;
         int r = 0;
         struct mntent* me;
@@ -1511,7 +1515,7 @@ static int mount_load_etc_fstab(Manager *m) {
         assert(m);
 
         errno = 0;
-        if (!(f = setmntent("/etc/fstab", "r")))
+        if (!(f = setmntent(fname, "r")))
                 return -errno;
 
         while ((me = getmntent(f))) {
@@ -1565,6 +1569,68 @@ finish:
         return r;
 }
 
+/* This code is based on mnt_table_parse_dir() 
+   in util-linux/libmount/src/tab_parse.c */
+static int mount_load_etc_fstab_d(Manager *m, const char* dname) {
+        DIR* dir;
+        int n, i, r = 0;
+        struct dirent **namelist = NULL;
+
+        n = scandir(dname, &namelist, NULL, versionsort);
+        if (n <= 0)
+                return 0;
+
+        dir = opendir(dname);
+        if (!dir) {
+                r = -errno;
+                goto out;
+        }
+
+        for (i = 0; i < n; i++) {
+                struct dirent *d = namelist[i];
+                struct stat st;
+		size_t namesz;
+		FILE *f;
+                char fstab[PATH_MAX];
+                int rc;
+
+#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_EXT	".fstab"
+#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 (fstatat(dirfd(dir), d->d_name, &st, 0) ||
+		    !S_ISREG(st.st_mode))
+			continue;
+
+                rc = snprintf(fstab, sizeof(fstab), "%s/%s", dname, d->d_name);
+                if (rc < 0 || (size_t) rc >= sizeof(fstab))
+                        continue;
+
+                mount_load_etc_fstab(m, fstab);
+        }
+
+ out:
+        if (dir)
+                closedir(dir);
+        for (i = 0; i < n; i++)
+                free(namelist[i]);
+        free(namelist);
+        return r;
+}
+
 static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
         int r = 0;
         unsigned i;
@@ -1672,9 +1738,13 @@ static int mount_enumerate(Manager *m) {
                         return -errno;
         }
 
-        if ((r = mount_load_etc_fstab(m)) < 0)
+        if ((r = mount_load_etc_fstab(m, "/etc/fstab")) < 0)
                 goto fail;
 
+        /* No need to check the return value here: /etc/fstab.d is optional. */
+        mount_load_etc_fstab_d(m,"/etc/fstab.d");
+
+
         if ((r = mount_load_proc_self_mountinfo(m, false)) < 0)
                 goto fail;


More information about the systemd-devel mailing list