summaryrefslogtreecommitdiffstats
path: root/shlibs
diff options
context:
space:
mode:
authorKarel Zak2010-10-21 08:57:02 +0200
committerKarel Zak2011-01-03 12:28:45 +0100
commit3a5b1b1d5d8cae6e7c4ee4f33f2fc20be3ddf6f4 (patch)
tree42eb4ffefea462d53df2d58f8b663161fff87421 /shlibs
parenttests: add quoted optstr (diff)
downloadkernel-qcow2-util-linux-3a5b1b1d5d8cae6e7c4ee4f33f2fc20be3ddf6f4.tar.gz
kernel-qcow2-util-linux-3a5b1b1d5d8cae6e7c4ee4f33f2fc20be3ddf6f4.tar.xz
kernel-qcow2-util-linux-3a5b1b1d5d8cae6e7c4ee4f33f2fc20be3ddf6f4.zip
libmount: allow to overwrite mtab/fstab paths
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs')
-rw-r--r--shlibs/mount/src/context.c4
-rw-r--r--shlibs/mount/src/lock.c11
-rw-r--r--shlibs/mount/src/mount.h.in6
-rw-r--r--shlibs/mount/src/mount.sym2
-rw-r--r--shlibs/mount/src/tab_parse.c73
-rw-r--r--shlibs/mount/src/tab_update.c58
-rw-r--r--shlibs/mount/src/utils.c48
7 files changed, 140 insertions, 62 deletions
diff --git a/shlibs/mount/src/context.c b/shlibs/mount/src/context.c
index 863003926..21a5d8a1d 100644
--- a/shlibs/mount/src/context.c
+++ b/shlibs/mount/src/context.c
@@ -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;
}
diff --git a/shlibs/mount/src/lock.c b/shlibs/mount/src/lock.c
index 5e18ba250..9149c7b90 100644
--- a/shlibs/mount/src/lock.c
+++ b/shlibs/mount/src/lock.c
@@ -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);
diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in
index a1143ee27..01ba5a6d6 100644
--- a/shlibs/mount/src/mount.h.in
+++ b/shlibs/mount/src/mount.h.in
@@ -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));
diff --git a/shlibs/mount/src/mount.sym b/shlibs/mount/src/mount.sym
index f97d0048b..2db74df34 100644
--- a/shlibs/mount/src/mount.sym
+++ b/shlibs/mount/src/mount.sym
@@ -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;
diff --git a/shlibs/mount/src/tab_parse.c b/shlibs/mount/src/tab_parse.c
index 224fcb68f..5ac51ab87 100644
--- a/shlibs/mount/src/tab_parse.c
+++ b/shlibs/mount/src/tab_parse.c
@@ -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;
}
diff --git a/shlibs/mount/src/tab_update.c b/shlibs/mount/src/tab_update.c
index 830225277..946cdc090 100644
--- a/shlibs/mount/src/tab_update.c
+++ b/shlibs/mount/src/tab_update.c
@@ -27,6 +27,12 @@
* /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);
diff --git a/shlibs/mount/src/utils.c b/shlibs/mount/src/utils.c
index 3aa8d9b82..09457345c 100644
--- a/shlibs/mount/src/utils.c
+++ b/shlibs/mount/src/utils.c
@@ -417,19 +417,55 @@ int mnt_has_regular_mtab(void)
}
/**
+ * 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 */
}