/* * This function uses @uf to found corresponding record in @tb, then the record * from @tb is updated (user specific mount options are added). * * Note that @uf must contain only user specific mount options instead of * VFS options (note that FS options are ignored). * * Returns modified filesystem (from @tb) or NULL. */ static struct libmnt_fs *mnt_table_merge_user_fs(struct libmnt_table *tb, struct libmnt_fs *uf) { struct libmnt_fs *fs; struct libmnt_iter itr; const char *optstr, *src, *target, *root, *attrs; assert(tb); assert(uf); if (!tb || !uf) return NULL; DBG(TAB, mnt_debug_h(tb, "merging user fs")); src = mnt_fs_get_srcpath(uf); target = mnt_fs_get_target(uf); optstr = mnt_fs_get_user_options(uf); attrs = mnt_fs_get_attributes(uf); root = mnt_fs_get_root(uf); if (!src || !target || !root || (!attrs && !optstr)) return NULL; mnt_reset_iter(&itr, MNT_ITER_BACKWARD); while(mnt_table_next_fs(tb, &itr, &fs) == 0) { const char *s = mnt_fs_get_srcpath(fs), *t = mnt_fs_get_target(fs), *r = mnt_fs_get_root(fs); if (fs->flags & MNT_FS_MERGED) continue; if (s && t && r && !strcmp(t, target) && !strcmp(s, src) && !strcmp(r, root)) break; } if (fs) { DBG(TAB, mnt_debug_h(tb, "found fs -- appending user optstr")); mnt_fs_append_options(fs, optstr); mnt_fs_append_attributes(fs, attrs); mnt_fs_set_bindsrc(fs, mnt_fs_get_bindsrc(uf)); fs->flags |= MNT_FS_MERGED; DBG(TAB, mnt_debug_h(tb, "found fs:")); DBG(TAB, mnt_fs_print_debug(fs, stderr)); } return fs; }
/** * mnt_update_table: * @upd: update * @lc: lock or NULL * * High-level API to update /etc/mtab (or private /run/mount/utab file). * * The @lc lock is optional and will be created if necessary. Note that * the automatically created lock blocks all signals. * * See also mnt_lock_block_signals() and mnt_context_get_lock(). * * Returns: 0 on success, negative number on error. */ int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc) { struct libmnt_lock *lc0 = lc; int rc = -EINVAL; assert(upd); if (!upd->filename || !upd) return -EINVAL; if (!upd->ready) return 0; DBG(UPDATE, mnt_debug_h(upd, "%s: update tab", upd->filename)); if (upd->fs) { DBG(UPDATE, mnt_fs_print_debug(upd->fs, stderr)); } if (!lc) { lc = mnt_new_lock(upd->filename, 0); if (lc) mnt_lock_block_signals(lc, TRUE); } if (lc && upd->userspace_only) mnt_lock_use_simplelock(lc, TRUE); /* use flock */ if (!upd->fs && upd->target) rc = update_remove_entry(upd, lc); /* umount */ else if (upd->mountflags & MS_MOVE) rc = update_modify_target(upd, lc); /* move */ else if (upd->mountflags & MS_REMOUNT) rc = update_modify_options(upd, lc); /* remount */ else if (upd->fs) rc = update_add_entry(upd, lc); /* mount */ upd->ready = FALSE; DBG(UPDATE, mnt_debug_h(upd, "%s: update tab: done [rc=%d]", upd->filename, rc)); if (lc != lc0) mnt_free_lock(lc); return rc; }
/** * mnt_update_set_fs: * @upd: update handler * @mountflags: MS_* flags * @target: umount target, must be NULL for mount * @fs: mount filesystem description, must be NULL for umount * * Returns: <0 in case on error, 0 on success, 1 if update is unnecessary. */ int mnt_update_set_fs(struct libmnt_update *upd, unsigned long mountflags, const char *target, struct libmnt_fs *fs) { int rc; assert(upd); assert(target || fs); if (!upd) return -EINVAL; if ((mountflags & MS_MOVE) && (!fs || !mnt_fs_get_srcpath(fs))) return -EINVAL; if (target && fs) return -EINVAL; DBG(UPDATE, mnt_debug_h(upd, "reseting FS [fs=0x%p, target=%s, flags=0x%08lx]", fs, target, mountflags)); if (fs) { DBG(UPDATE, mnt_debug_h(upd, "FS template:")); DBG(UPDATE, mnt_fs_print_debug(fs, stderr)); } mnt_free_fs(upd->fs); free(upd->target); upd->ready = FALSE; upd->fs = NULL; upd->target = NULL; upd->mountflags = 0; if (mountflags & MS_PROPAGATION) return 1; upd->mountflags = mountflags; rc = mnt_update_set_filename(upd, NULL, 0); if (rc) { DBG(UPDATE, mnt_debug_h(upd, "no writable file available [rc=%d]", rc)); return rc; /* error or no file available (rc = 1) */ } if (target) { upd->target = strdup(target); if (!upd->target) return -ENOMEM; } else if (fs) { if (upd->userspace_only && !(mountflags & MS_MOVE)) { int rc = utab_new_entry(upd, fs, mountflags); if (rc) return rc; } else { upd->fs = mnt_copy_mtab_fs(fs); if (!upd->fs) return -ENOMEM; } } DBG(UPDATE, mnt_debug_h(upd, "ready")); upd->ready = TRUE; return 0; }