/* * The default is to use fstype from cxt->fs, this could be overwritten by * @try_type argument. * * Returns: 0 on success, * >0 in case of mount(2) error (returns syscall errno), * <0 in case of other errors. */ static int do_mount(struct libmnt_context *cxt, const char *try_type) { int rc = 0; const char *src, *target, *type; unsigned long flags; assert(cxt); assert(cxt->fs); assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); if (try_type && !cxt->helper) { rc = mnt_context_prepare_helper(cxt, "mount", try_type); if (!rc) return rc; } if (cxt->helper) return exec_helper(cxt); flags = cxt->mountflags; src = mnt_fs_get_srcpath(cxt->fs); target = mnt_fs_get_target(cxt->fs); if (!src || !target) return -EINVAL; type = try_type ? : mnt_fs_get_fstype(cxt->fs); if (!(flags & MS_MGC_MSK)) flags |= MS_MGC_VAL; DBG(CXT, mnt_debug_h(cxt, "%smount(2) " "[source=%s, target=%s, type=%s, " " mountflags=0x%08lx, mountdata=%s]", (cxt->flags & MNT_FL_FAKE) ? "(FAKE) " : "", src, target, type, flags, cxt->mountdata ? "yes" : "<none>")); if (cxt->flags & MNT_FL_FAKE) cxt->syscall_status = 0; else { if (mount(src, target, type, flags, cxt->mountdata)) { cxt->syscall_status = -errno; DBG(CXT, mnt_debug_h(cxt, "mount(2) failed [errno=%d %m]", -cxt->syscall_status)); return -cxt->syscall_status; } DBG(CXT, mnt_debug_h(cxt, "mount(2) success")); cxt->syscall_status = 0; } if (try_type && cxt->update) { struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); if (fs) rc = mnt_fs_set_fstype(fs, try_type); } return rc; }
static void fs_interpret_type(struct libmnt_fs *fs) { const char *device; const char *type = mnt_fs_get_fstype(fs); if (type && strcmp(type, "auto") != 0) return; mnt_fs_set_fstype(fs, NULL); device = fs_get_device(fs); if (device) { int ambi = 0; type = mnt_get_fstype(device, &ambi, mnt_table_get_cache(fstab)); if (!ambi) mnt_fs_set_fstype(fs, type); } }
static int test_add(struct libmnt_test *ts, int argc, char *argv[]) { struct libmnt_fs *fs = mnt_new_fs(); int rc; if (argc < 5 || !fs) return -1; mnt_fs_set_source(fs, argv[1]); mnt_fs_set_target(fs, argv[2]); mnt_fs_set_fstype(fs, argv[3]); mnt_fs_set_options(fs, argv[4]); rc = update(NULL, fs, 0); mnt_free_fs(fs); return rc; }
/* * Parses one line from /proc/swaps */ static int mnt_parse_swaps_line(struct libmnt_fs *fs, char *s) { uintmax_t fsz, usz; int rc; char *src = NULL; rc = sscanf(s, UL_SCNsA" " /* (1) source */ UL_SCNsA" " /* (2) type */ "%jd" /* (3) size */ "%jd" /* (4) used */ "%d", /* priority */ &src, &fs->swaptype, &fsz, &usz, &fs->priority); if (rc == 5) { size_t sz; fs->size = fsz; fs->usedsize = usz; unmangle_string(src); /* remove "(deleted)" suffix */ sz = strlen(src); if (sz > PATH_DELETED_SUFFIX_SZ) { char *p = src + (sz - PATH_DELETED_SUFFIX_SZ); if (strcmp(p, PATH_DELETED_SUFFIX) == 0) *p = '\0'; } rc = mnt_fs_set_source(fs, src); if (!rc) mnt_fs_set_fstype(fs, "swap"); free(src); } else { DBG(TAB, mnt_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s)); rc = -EINVAL; } return rc; }
/* * Sets fs-root and fs-type to @upd->fs according to the @fs template and * @mountfalgs. For MS_BIND mountflag it reads information about source * filesystem from /proc/self/mountinfo. */ static int set_fs_root(struct libmnt_update *upd, struct libmnt_fs *fs, unsigned long mountflags) { struct libmnt_fs *src_fs; char *fsroot = NULL; const char *src; int rc = 0; DBG(UPDATE, mnt_debug("setting FS root")); assert(upd); assert(upd->fs); assert(fs); if (mountflags & MS_BIND) { if (!upd->mountinfo) upd->mountinfo = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO); src = mnt_fs_get_srcpath(fs); if (src) { rc = mnt_fs_set_bindsrc(upd->fs, src); if (rc) goto err; } } src_fs = mnt_table_get_fs_root(upd->mountinfo, fs, mountflags, &fsroot); if (src_fs) { src = mnt_fs_get_srcpath(src_fs); rc = mnt_fs_set_source(upd->fs, src); if (rc) goto err; mnt_fs_set_fstype(upd->fs, mnt_fs_get_fstype(src_fs)); } upd->fs->root = fsroot; return 0; err: free(fsroot); return rc; }
/* this is umount replacement to mnt_context_apply_fstab(), use * mnt_context_tab_applied() to check result. */ static int lookup_umount_fs(struct libmnt_context *cxt) { const char *tgt; struct stat st; struct libmnt_fs *fs = NULL; int rc = 0; assert(cxt); assert(cxt->fs); tgt = mnt_fs_get_target(cxt->fs); if (!tgt) { DBG(CXT, ul_debugobj(cxt, "umount: undefined target")); return -EINVAL; } /* * Let's try to avoid mountinfo usage at all to minimize performance * degradation. Don't forget that kernel has to compose *whole* * mountinfo about all mountpoints although we look for only one entry. * * All we need is fstype and to check if there is no userspace mount * options for the target (e.g. helper=udisks to call /sbin/umount.udisks). * * So, let's use statfs() if possible (it's bad idea for --lazy/--force * umounts as target is probably unreachable NFS, also for --detach-loop * as this additionally needs to know the name of the loop device). */ if (!mnt_context_is_restricted(cxt) && *tgt == '/' && !(cxt->flags & MNT_FL_HELPER) && !mnt_context_mtab_writable(cxt) && !mnt_context_is_force(cxt) && !mnt_context_is_lazy(cxt) && !mnt_context_is_loopdel(cxt) && mnt_stat_mountpoint(tgt, &st) == 0 && S_ISDIR(st.st_mode) && !has_utab_entry(cxt, tgt)) { const char *type = mnt_fs_get_fstype(cxt->fs); /* !mnt_context_mtab_writable(cxt) && has_utab_entry() verified that there * is no stuff in utab, so disable all mtab/utab related actions */ mnt_context_disable_mtab(cxt, TRUE); if (!type) { struct statfs vfs; if (statfs(tgt, &vfs) == 0) type = mnt_statfs_get_fstype(&vfs); if (type) { rc = mnt_fs_set_fstype(cxt->fs, type); if (rc) return rc; } } if (type) { DBG(CXT, ul_debugobj(cxt, "umount: mountinfo unnecessary [type=%s]", type)); return 0; } } rc = mnt_context_find_umount_fs(cxt, tgt, &fs); if (rc < 0) return rc; if (rc == 1 || !fs) { DBG(CXT, ul_debugobj(cxt, "umount: cannot find '%s' in mtab", tgt)); return 0; /* this is correct! */ } if (fs != cxt->fs) { /* copy from mtab to our FS description */ mnt_fs_set_source(cxt->fs, NULL); mnt_fs_set_target(cxt->fs, NULL); if (!mnt_copy_fs(cxt->fs, fs)) { DBG(CXT, ul_debugobj(cxt, "umount: failed to copy FS")); return -errno; } DBG(CXT, ul_debugobj(cxt, "umount: mtab applied")); } cxt->flags |= MNT_FL_TAB_APPLIED; return rc; }
/* * The default is to use fstype from cxt->fs, this could be overwritten by * @try_type argument. * * Returns: 0 on success, * >0 in case of mount(2) error (returns syscall errno), * <0 in case of other errors. */ static int do_mount(struct libmnt_context *cxt, const char *try_type) { int rc = 0; const char *src, *target, *type; unsigned long flags; assert(cxt); assert(cxt->fs); assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED)); if (try_type && !cxt->helper) { rc = mnt_context_prepare_helper(cxt, "mount", try_type); if (rc) return rc; } if (cxt->helper) return exec_helper(cxt); flags = cxt->mountflags; src = mnt_fs_get_srcpath(cxt->fs); target = mnt_fs_get_target(cxt->fs); if (!target) return -EINVAL; if (!src) { /* unnecessary, should be already resolved in * mnt_context_prepare_srcpath(), but for sure... */ DBG(CXT, mnt_debug_h(cxt, "WARNING: source is NULL -- using \"none\"!")); src = "none"; } type = try_type ? : mnt_fs_get_fstype(cxt->fs); if (!(flags & MS_MGC_MSK)) flags |= MS_MGC_VAL; DBG(CXT, mnt_debug_h(cxt, "%smount(2) " "[source=%s, target=%s, type=%s, " " mountflags=0x%08lx, mountdata=%s]", mnt_context_is_fake(cxt) ? "(FAKE) " : "", src, target, type, flags, cxt->mountdata ? "yes" : "<none>")); if (mnt_context_is_fake(cxt)) cxt->syscall_status = 0; else { if (mount(src, target, type, flags, cxt->mountdata)) { cxt->syscall_status = -errno; DBG(CXT, mnt_debug_h(cxt, "mount(2) failed [errno=%d %m]", -cxt->syscall_status)); return -cxt->syscall_status; } DBG(CXT, mnt_debug_h(cxt, "mount(2) success")); cxt->syscall_status = 0; } if (try_type && cxt->update) { struct libmnt_fs *fs = mnt_update_get_fs(cxt->update); if (fs) rc = mnt_fs_set_fstype(fs, try_type); } return rc; }