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;
}
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;
}
if (!ml)
return;
- DBG(LOCKS, mnt_debug_h(ml, "(%d) unlocking/cleaning", getpid()));
if (ml->locked == 0 && ml->lockfile && ml->linkfile)
{
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)
void clean_lock(void)
{
- fprintf(stderr, "%d: cleaning\n", getpid());
if (!lock)
return;
mnt_unlock_file(lock);
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);
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);
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));
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;
/**
* 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
* 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
/**
* 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;
}
* /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
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;
{
assert(upd);
if (!upd)
- return -1;
+ return -EINVAL;
upd->action = action;
return 0;
}
{
assert(upd);
if (!upd)
- return -1;
+ return -EINVAL;
upd->format = format;
return 0;
}
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);
{
assert(upd);
if (!upd)
- return -1;
+ return -EINVAL;
upd->mountflags = flags;
return 0;
}
char *p = NULL;
if (!upd)
- return -1;
- if (p) {
+ return -EINVAL;
+ if (target) {
p = strdup(target);
if (!p)
return -1;
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));
assert(f);
if (!fs || !f)
- return -1;
+ return -EINVAL;
m1 = mangle(mnt_fs_get_source(fs));
m2 = mangle(mnt_fs_get_target(fs));
assert(tb);
if (!tb)
- goto error;
+ return -EINVAL;
DBG(UPDATE, mnt_debug("%s: update from tab %p", filename, tb));
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)
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;
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) {
/* 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
u = NULL;
}
+done:
if (!upd->nolock && !upd->lc) {
upd->lc = mnt_new_lock(upd->filename, 0);
if (!upd->lc) {
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;
}
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);
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;
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 */
}