]> err.no Git - util-linux/commitdiff
libmount: allow to overwrite mtab/fstab paths
authorKarel Zak <kzak@redhat.com>
Thu, 21 Oct 2010 06:57:02 +0000 (08:57 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Jan 2011 11:28:45 +0000 (12:28 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/mount/src/context.c
shlibs/mount/src/lock.c
shlibs/mount/src/mount.h.in
shlibs/mount/src/mount.sym
shlibs/mount/src/tab_parse.c
shlibs/mount/src/tab_update.c
shlibs/mount/src/utils.c

index 863003926dfd6019e8c15e3ed72680dbb10bc68f..21a5d8a1d029d33902c9257505975a25458e3fcd 100644 (file)
@@ -547,7 +547,7 @@ int mnt_context_get_fstab(mnt_context *cxt, mnt_tab **tb)
                if (!cxt->fstab)
                        return -ENOMEM;
                cxt->flags &= ~MNT_FL_EXTERN_FSTAB;
-               rc = mnt_tab_parse_fstab(cxt->fstab);
+               rc = mnt_tab_parse_fstab(cxt->fstab, NULL);
                if (rc)
                        return rc;
        }
@@ -585,7 +585,7 @@ int mnt_context_get_mtab(mnt_context *cxt, mnt_tab **tb)
                cxt->mtab = mnt_new_tab();
                if (!cxt->mtab)
                        return -ENOMEM;
-               rc = mnt_tab_parse_mtab(cxt->mtab);
+               rc = mnt_tab_parse_mtab(cxt->mtab, NULL);
                if (rc)
                        return rc;
        }
index 5e18ba250314a832d5bb74ffc58b296c91bf6c9a..9149c7b90b84d0f646d435b184c3b8bf034af4e3 100644 (file)
@@ -231,7 +231,6 @@ void mnt_unlock_file(mnt_lock *ml)
        if (!ml)
                return;
 
-       DBG(LOCKS, mnt_debug_h(ml, "(%d) unlocking/cleaning", getpid()));
 
        if (ml->locked == 0 && ml->lockfile && ml->linkfile)
        {
@@ -247,6 +246,10 @@ void mnt_unlock_file(mnt_lock *ml)
                    lo.st_dev == li.st_dev && lo.st_ino == li.st_ino)
                        ml->locked = 1;
        }
+
+       DBG(LOCKS, mnt_debug_h(ml, "(%d) %s", getpid(),
+                       ml->locked ? "unlocking" : "cleaning"));
+
        if (ml->linkfile)
                unlink(ml->linkfile);
        if (ml->lockfile_fd >= 0)
@@ -468,7 +471,6 @@ void increment_data(const char *filename, int verbose, int loopno)
 
 void clean_lock(void)
 {
-       fprintf(stderr, "%d: cleaning\n", getpid());
        if (!lock)
                return;
        mnt_unlock_file(lock);
@@ -508,8 +510,9 @@ int test_lock(struct mtest *ts, int argc, char *argv[])
        if (!datafile || !loops)
                return -EINVAL;
 
-       fprintf(stderr, "%d: start: synctime=%u, verbose=%d, datafile=%s, loops=%d\n",
-                getpid(), (int) synctime, verbose, datafile, loops);
+       if (verbose)
+               fprintf(stderr, "%d: start: synctime=%u, datafile=%s, loops=%d\n",
+                        getpid(), (int) synctime, datafile, loops);
 
        atexit(clean_lock);
 
index a1143ee273c92bcc3b9b3d84a77a2b16fc69d472..01ba5a6d6624c909a66608c49728b533798047e7 100644 (file)
@@ -132,6 +132,8 @@ extern int mnt_fstype_is_pseudofs(const char *type);
 extern int mnt_match_fstype(const char *type, const char *pattern);
 extern int mnt_match_options(const char *optstr, const char *pattern);
 extern const char *mnt_get_writable_mtab_path(void);
+extern const char *mnt_get_fstab_path(void);
+extern const char *mnt_get_mtab_path(void);
 
 /* cache.c */
 extern mnt_cache *mnt_new_cache(void);
@@ -251,8 +253,8 @@ 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_parse_mtab(mnt_tab *tb);
+extern int mnt_tab_parse_fstab(mnt_tab *tb, const char *filename);
+extern int mnt_tab_parse_mtab(mnt_tab *tb, const char *filename);
 extern int mnt_tab_set_parser_errcb(mnt_tab *tb,
                 int (*cb)(mnt_tab *tb, const char *filename, int line));
 
index f97d0048bbe8dc0bb2a659c23f4651566911b65c..2db74df34dc6d6a40b42310b56f2ab6fbac38edc 100644 (file)
@@ -55,6 +55,8 @@ global:
        mnt_get_builtin_optmap;
        mnt_get_library_version;
        mnt_get_writable_mtab_path;
+       mnt_get_fstab_path;
+       mnt_get_mtab_path;
        mnt_init_debug;
        mnt_iter_get_direction;
        mnt_lock_file;
index 224fcb68f15395818b80479ddc7d2a28bb151d04..5ac51ab8739fe4058d8b6d7ee510eb2afdf8c68b 100644 (file)
@@ -437,6 +437,7 @@ int mnt_tab_set_parser_errcb(mnt_tab *tb,
 /**
  * mnt_tab_parse_fstab:
  * @tb: table
+ * @filename: overwrites default (/etc/fstab or $LIBMOUNT_FSTAB) or NULL
  *
  * 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
@@ -452,28 +453,30 @@ int mnt_tab_set_parser_errcb(mnt_tab *tb,
  * Returns: 0 on success (least one record has been successfully parsed) or
  *          negative number in case of error.
  */
-int mnt_tab_parse_fstab(mnt_tab *tb)
+int mnt_tab_parse_fstab(mnt_tab *tb, const char *filename)
 {
        int num, n = 0, i;
        DIR *dir = NULL;
        FILE *f;
        struct dirent **namelist = NULL;
-       const char *env;
 
        assert(tb);
        if (!tb)
                return -EINVAL;
 
        num = mnt_tab_get_nents(tb);
-       env = mnt_getenv_safe("LIBMOUNT_FSTAB");
 
-       f = fopen(env ? : _PATH_MNTTAB, "r");
+       if (!filename)
+               filename = mnt_get_fstab_path();
+
+       f = fopen(filename, "r");
        if (f) {
-               mnt_tab_parse_stream(tb, f, _PATH_MNTTAB);
+               mnt_tab_parse_stream(tb, f, filename);
                fclose(f);
 
-               if (env)
-                       goto done;      /* ignore /etc/fstab.d if $LIBMOUNT_FSTAB defined */
+               if (strcmp(filename, _PATH_MNTTAB))
+                       /* /etc/fstab.d sould be used together with /etc/fstab only */
+                       goto done;
        }
 
        /* TODO: it would be nice to have a scandir() implementaion that
@@ -581,46 +584,66 @@ static mnt_fs *mnt_tab_merge_userspace_fs(mnt_tab *tb, mnt_fs *uf)
 /**
  * mnt_tab_parse_mtab:
  * @tb: table
+ * @filename: overwrites default (/etc/mtab or $LIBMOUNT_MTAB) or NULL
  *
  * This function parses /etc/mtab or {/proc/self,/var/run/mount}/mountinfo or
  * /proc/mounts. Note that the /var/run/mount/mountinfo file is optional and
  * contains userspace specific mount options only.
  *
+ * Note that /var/run/mount/mountinfo is ignored if /etc/mtab is writable or
+ * $LIBMOUNT_MTAB or @filename does not end with "mountinfo" postfix.
+ *
  * See also mnt_tab_set_parser_errcb().
  *
  * Returns: 0 on success or negative number in case of error.
  */
-int mnt_tab_parse_mtab(mnt_tab *tb)
+int mnt_tab_parse_mtab(mnt_tab *tb, const char *filename)
 {
        int rc;
-       mnt_tab *u_tb;
-       mnt_fs *u_fs;
-       mnt_iter itr;
-       const char *env = mnt_getenv_safe("LIBMOUNT_MTAB");
 
-       if ((env && !endswith(env, "mountinfo")) || mnt_has_regular_mtab()) {
-               rc = mnt_tab_parse_file(tb, env ? : _PATH_MOUNTED);
+       if (!filename)
+               filename = mnt_get_writable_mtab_path();
+
+       /*
+        * Regular mtab file
+        */
+       if (filename && !endswith(filename, "mountinfo")) {
+               rc = mnt_tab_parse_file(tb, filename);
                if (!rc)
-                       return 0;               /* system with regular mtab */
+                       return 0;
+               filename = NULL;
        }
 
-       /* read kernel information from /proc/self/mountinfo */
+       /*
+        * useless /etc/mtab or /var/run/mount/mountinfo is supported
+        * -- read kernel information from /proc/self/mountinfo
+        */
        rc = mnt_tab_parse_file(tb, _PATH_PROC_MOUNTINFO);
        if (rc)
                /* hmm, old kernel? ...try /proc/mounts */
                return mnt_tab_parse_file(tb, _PATH_PROC_MOUNTS);
 
-       /* try to read userspace specific information from /var/run/mount */
-       u_tb = mnt_new_tab_from_file(env ? : MNT_PATH_MOUNTINFO);
-       if (!u_tb)
-               return 0;       /* private mountinfo does not exist */
+       /*
+        * try to read userspace specific information from
+        * /var/run/mount/mountinfo
+        */
+       if (filename) {
+               mnt_tab *u_tb = mnt_new_tab_from_file(filename);
+
+               assert(endswith(filename, "mountinfo"));
 
-       mnt_reset_iter(&itr, MNT_ITER_BACKWARD);
+               if (u_tb) {
+                       mnt_fs *u_fs;
+                       mnt_iter itr;
 
-       /*  merge userspace options into mountinfo from kernel */
-       while(mnt_tab_next_fs(u_tb, &itr, &u_fs) == 0)
-               mnt_tab_merge_userspace_fs(tb, u_fs);
+                       mnt_reset_iter(&itr, MNT_ITER_BACKWARD);
 
-       mnt_free_tab(u_tb);
+                       /*  merge userspace options into mountinfo from kernel */
+                       while(mnt_tab_next_fs(u_tb, &itr, &u_fs) == 0)
+                               mnt_tab_merge_userspace_fs(tb, u_fs);
+
+                       mnt_free_tab(u_tb);
+               }
+       }
        return 0;
 }
index 830225277511499f00c1ed77d2dd79c023d0d54e..946cdc09001eaa577c0f24e417ddfcc3d312a91b 100644 (file)
  *   /var/run/mount/mountinfo file (the file format compatible to
  *   /proc/self/mountinfo)
  *
+ * Note that mnt_update_* interface does not manage mount options. It's callers
+ * responsibility set the right mount options (for example merge options from
+ * mtab with command line on MS_REMOUNT).
+ *
+ * The small exception is the /var/run/mount/mountinfo file where are store
+ * userspace mount options only. This is done by mnt_prepare_update().
  *
  * The mtab is always updated in two steps. The first step is to prepare a new
  * update entry -- mnt_prepare_update(), this step has to be done before
@@ -126,11 +132,11 @@ int mnt_update_set_filename(mnt_update *upd, const char *filename)
 
        assert(upd);
        if (!upd)
-               return -1;
+               return -EINVAL;
        if (filename) {
                p = strdup(filename);
                if (!p)
-                       return -1;
+                       return -ENOMEM;
        }
        free(upd->filename);
        upd->filename = p;
@@ -164,7 +170,7 @@ int mnt_update_set_action(mnt_update *upd, int action)
 {
        assert(upd);
        if (!upd)
-               return -1;
+               return -EINVAL;
        upd->action = action;
        return 0;
 }
@@ -184,7 +190,7 @@ int mnt_update_set_format(mnt_update *upd, int format)
 {
        assert(upd);
        if (!upd)
-               return -1;
+               return -EINVAL;
        upd->format = format;
        return 0;
 }
@@ -219,11 +225,11 @@ int mnt_update_set_fs(mnt_update *upd, const mnt_fs *fs)
 
        assert(upd);
        if (!upd)
-               return -1;
+               return -EINVAL;
        if (fs) {
                x = mnt_copy_fs(fs);
                if (!x)
-                       return -1;
+                       return -ENOMEM;
        }
 
        mnt_free_fs(upd->fs);
@@ -247,7 +253,7 @@ int mnt_update_set_mountflags(mnt_update *upd, unsigned long flags)
 {
        assert(upd);
        if (!upd)
-               return -1;
+               return -EINVAL;
        upd->mountflags = flags;
        return 0;
 }
@@ -305,8 +311,8 @@ int mnt_update_set_old_target(mnt_update *upd, const char *target)
        char *p = NULL;
 
        if (!upd)
-               return -1;
-       if (p) {
+               return -EINVAL;
+       if (target) {
                p = strdup(target);
                if (!p)
                        return -1;
@@ -331,7 +337,7 @@ static int fprintf_mountinfo_fs(FILE *f, mnt_fs *fs)
        assert(f);
 
        if (!fs || !f)
-               return -1;
+               return -EINVAL;
        devno = mnt_fs_get_devno(fs);
        source = mangle(mnt_fs_get_source(fs));
        root = mangle(mnt_fs_get_root(fs));
@@ -372,7 +378,7 @@ static int fprintf_mtab_fs(FILE *f, mnt_fs *fs)
        assert(f);
 
        if (!fs || !f)
-               return -1;
+               return -EINVAL;
 
        m1 = mangle(mnt_fs_get_source(fs));
        m2 = mangle(mnt_fs_get_target(fs));
@@ -408,7 +414,7 @@ static int update_file(const char *filename, int fmt, mnt_tab *tb)
 
        assert(tb);
        if (!tb)
-               goto error;
+               return -EINVAL;
 
        DBG(UPDATE, mnt_debug("%s: update from tab %p", filename, tb));
 
@@ -450,7 +456,7 @@ error:
        DBG(UPDATE, mnt_debug("%s: update from tab %p failed", filename, tb));
        if (f)
                fclose(f);
-       return -1;
+       return errno ? -errno : -1;
 }
 
 static int set_fs_root(mnt_update *upd, mnt_fs *fs)
@@ -602,10 +608,8 @@ int mnt_prepare_update(mnt_update *upd)
                mnt_fs_get_optstr(upd->fs)));
 
        if (!upd->filename) {
-               const char *p = mnt_getenv_safe("LIBMOUNT_MTAB");
+               const char *p = mnt_get_writable_mtab_path();
 
-               if (!p)
-                       p = mnt_get_writable_mtab_path();
                if (!p) {
                        if (errno) {
                                rc = -errno;
@@ -631,6 +635,10 @@ int mnt_prepare_update(mnt_update *upd)
                        upd->format = MNT_FMT_MTAB;
        }
 
+       DBG(UPDATE, mnt_debug_h(upd, "format: %s",
+                       upd->format == MNT_FMT_MOUNTINFO ? "mountinfo" :
+                       upd->format == MNT_FMT_FSTAB ? "fstab" : "mtab"));
+
        /* TODO: cannonicalize source and target paths on mnt->fs */
 
        if (upd->format != MNT_FMT_FSTAB) {
@@ -643,13 +651,13 @@ int mnt_prepare_update(mnt_update *upd)
 
        /* umount */
        if (upd->action == MNT_ACT_UMOUNT)
-               return 0;
+               goto done;
 
        /*
         * A) classic /etc/mtab or /etc/fstab update
         */
        if (upd->format != MNT_FMT_MOUNTINFO)
-               return 0;
+               goto done;
 
        /*
         * B) /var/run/mount/mountinfo
@@ -680,6 +688,7 @@ int mnt_prepare_update(mnt_update *upd)
                u = NULL;
        }
 
+done:
        if (!upd->nolock && !upd->lc) {
                upd->lc = mnt_new_lock(upd->filename, 0);
                if (!upd->lc) {
@@ -908,15 +917,17 @@ static int update(mnt_update *upd)
        rc = mnt_prepare_update(upd);
        if (!rc) {
                /* setup lock fallback */
+               int rc;
+
                lock = mnt_update_get_lock(upd);
                atexit(lock_fallback);
 
-               return mnt_update_file(upd);
+               rc = mnt_update_file(upd);
+               lock = NULL;
+               return rc;
        }
-       if (rc == 1) {
-               printf("update: update is not reuquired\n");
+       if (rc == 1)
                return 0;
-       }
        fprintf(stderr, "update: failed to prepare update\n");
        return -1;
 }
@@ -966,7 +977,8 @@ int test_add_fstab(struct mtest *ts, int argc, char *argv[])
                return -1;
 
        mnt_update_disable_lock(upd, TRUE);             /* lock is unnecessary */
-       mnt_update_set_filename(upd, _PATH_MNTTAB);     /* fstab */
+
+       mnt_update_set_filename(upd, mnt_get_fstab_path());
        mnt_update_set_format(upd, MNT_FMT_FSTAB);
 
        rc = update(upd);
index 3aa8d9b828dc0bca4ec56450da47c300ebe8981c..09457345c3b76861ab2fc7bea5c148407f9c22e0 100644 (file)
@@ -416,20 +416,56 @@ int mnt_has_regular_mtab(void)
        return 0;
 }
 
+/**
+ * mnt_get_fstab_path:
+ *
+ * Returns: path to /etc/fstab or $LIBMOUNT_FSTAB.
+ */
+const char *mnt_get_fstab_path(void)
+{
+       const char *p = mnt_getenv_safe("LIBMOUNT_FSTAB");
+       return p ? : _PATH_MNTTAB;
+}
+
+/**
+ * mnt_get_mtab_path:
+ *
+ * This function returns *default* location of the mtab file. The result does not have to
+ * be writable. See also mnt_get_writable_mtab_path().
+ *
+ * It's possible that libmount uses /proc/self/mountinfo together with
+ * /var/run/mount/mountinfo file (or files). The ideal solution is to use
+ * mnt_tab_parse_mtab() that provides abstraction and returns mtab records
+ * independently on the way how things are managed by libmount.
+ *
+ * Returns: path to /etc/mtab or $LIBMOUNT_MTAB.
+ */
+const char *mnt_get_mtab_path(void)
+{
+       const char *p = mnt_getenv_safe("LIBMOUNT_MTAB");
+       return p ? : _PATH_MOUNTED;
+}
+
 /**
  * mnt_get_writable_mtab_path:
  *
- * It's not error if this function return NULL and errno is not set. In case of
+ * It's not error if this function returns NULL and errno is not set. In case of
  * error the errno is set by open(2).
  *
- * Returns: pointer to the static string with path to mtab or NULL.
+ * Note that writable mtab does not have to contains all necessary information.
+ * For example /var/run/mount/mountinfo is used for userspace mount options
+ * only. FS depend information are usually maintaibed by kernel only.
+ *
+ * Returns: pointer to the static string with path to mtab or NULL if writable
+ *          mtab is unsupported.
  */
 const char *mnt_get_writable_mtab_path(void)
 {
        struct stat mst, ist;
        int mtab, info;
+       const char *path = mnt_get_mtab_path();
 
-       mtab = !lstat(_PATH_MOUNTED, &mst);
+       mtab = !lstat(path, &mst);
        info = !stat(MNT_PATH_RUNDIR, &ist);
 
        errno = 0;
@@ -444,12 +480,12 @@ const char *mnt_get_writable_mtab_path(void)
                return NULL;    /* probably EACCES */
        }
 
-       /* B) classis system with /etc/mtab */
+       /* B) classis system with /etc/mtab or $LIBMOUNT_MTAB */
        if (mtab && S_ISREG(mst.st_mode)) {
-               int fd = open(_PATH_MOUNTED, O_RDWR, 0644);
+               int fd = open(path, O_RDWR, 0644);
                if (fd >= 0) {
                        close(fd);
-                       return _PATH_MOUNTED;
+                       return path;
                }
                return NULL;    /* probably EACCES */
        }