/** * mnt_table_parse_mtab: * @tb: table * @filename: overwrites default (/etc/mtab or $LIBMOUNT_MTAB) or NULL * * This function parses /etc/mtab or /proc/self/mountinfo + * /run/mount/utabs or /proc/mounts. * * See also mnt_table_set_parser_errcb(). * * Returns: 0 on success or negative number in case of error. */ int mnt_table_parse_mtab(struct libmnt_table *tb, const char *filename) { int rc; const char *utab = NULL; struct libmnt_table *u_tb; assert(tb); if (mnt_has_regular_mtab(&filename, NULL)) { DBG(TAB, mnt_debug_h(tb, "force %s usage", filename)); rc = mnt_table_parse_file(tb, filename); if (!rc) return 0; filename = NULL; /* failed */ } /* * useless /etc/mtab * -- read kernel information from /proc/self/mountinfo */ tb->fmt = MNT_FMT_MOUNTINFO; rc = mnt_table_parse_file(tb, _PATH_PROC_MOUNTINFO); if (rc) { /* hmm, old kernel? ...try /proc/mounts */ tb->fmt = MNT_FMT_MTAB; return mnt_table_parse_file(tb, _PATH_PROC_MOUNTS); } if (mnt_table_get_nents(tb) == 0) return 0; /* empty, ignore utab */ /* * try to read the user specific information from /run/mount/utabs */ utab = mnt_get_utab_path(); if (!utab || is_file_empty(utab)) return 0; u_tb = mnt_new_table(); if (!u_tb) return -ENOMEM; u_tb->fmt = MNT_FMT_UTAB; mnt_table_set_parser_fltrcb(u_tb, tb->fltrcb, tb->fltrcb_data); if (mnt_table_parse_file(u_tb, utab) == 0) { struct libmnt_fs *u_fs; struct libmnt_iter itr; mnt_reset_iter(&itr, MNT_ITER_BACKWARD); /* merge user options into mountinfo from the kernel */ while(mnt_table_next_fs(u_tb, &itr, &u_fs) == 0) mnt_table_merge_user_fs(tb, u_fs); } mnt_unref_table(u_tb); return 0; }
/** * mnt_table_parse_mtab: * @tb: table * @filename: overwrites default (/etc/mtab or $LIBMOUNT_MTAB) or NULL * * This function parses /etc/mtab or /proc/self/mountinfo + * /run/mount/utabs or /proc/mounts. * * See also mnt_table_set_parser_errcb(). * * Returns: 0 on success or negative number in case of error. */ int mnt_table_parse_mtab(struct libmnt_table *tb, const char *filename) { int rc; const char *utab = NULL; if (mnt_has_regular_mtab(&filename, NULL)) { DBG(TAB, mnt_debug_h(tb, "force %s usage", filename)); rc = mnt_table_parse_file(tb, filename); if (!rc) return 0; filename = NULL; /* failed */ } /* * useless /etc/mtab * -- read kernel information from /proc/self/mountinfo */ tb->fmt = MNT_FMT_MOUNTINFO; rc = mnt_table_parse_file(tb, _PATH_PROC_MOUNTINFO); if (rc) { /* hmm, old kernel? ...try /proc/mounts */ tb->fmt = MNT_FMT_MTAB; return mnt_table_parse_file(tb, _PATH_PROC_MOUNTS); } /* * try to read user specific information from /run/mount/utabs */ utab = mnt_get_utab_path(); if (utab) { struct libmnt_table *u_tb = __mnt_new_table_from_file(utab, MNT_FMT_UTAB); if (u_tb) { struct libmnt_fs *u_fs; struct libmnt_iter itr; mnt_reset_iter(&itr, MNT_ITER_BACKWARD); /* merge user options into mountinfo from kernel */ while(mnt_table_next_fs(u_tb, &itr, &u_fs) == 0) mnt_table_merge_user_fs(tb, u_fs); mnt_free_table(u_tb); } } return 0; }
/** * mnt_table_parse_fstab: * @tb: table * @filename: overwrites default (/etc/fstab or $LIBMOUNT_FSTAB) or NULL * * This function parses /etc/fstab and appends new lines to the @tab. If the * @filename is a directory then mnt_table_parse_dir() is called. * * See also mnt_table_set_parser_errcb(). * * Returns: 0 on success or negative number in case of error. */ int mnt_table_parse_fstab(struct libmnt_table *tb, const char *filename) { struct stat st; int rc = 0; assert(tb); if (!tb) return -EINVAL; if (!filename) filename = mnt_get_fstab_path(); if (!filename || stat(filename, &st)) return -EINVAL; tb->fmt = MNT_FMT_FSTAB; if (S_ISREG(st.st_mode)) rc = mnt_table_parse_file(tb, filename); else if (S_ISDIR(st.st_mode)) rc = mnt_table_parse_dir(tb, filename); else rc = -EINVAL; return rc; }
/** * mnt_table_parse_swaps: * @tb: table * @filename: overwrites default (/proc/swaps or $LIBMOUNT_SWAPS) or NULL * * This function parses /proc/swaps and appends new lines to the @tab. * * See also mnt_table_set_parser_errcb(). * * Returns: 0 on success or negative number in case of error. */ int mnt_table_parse_swaps(struct libmnt_table *tb, const char *filename) { if (!tb) return -EINVAL; if (!filename) { filename = mnt_get_swaps_path(); if (!filename) return -EINVAL; } tb->fmt = MNT_FMT_SWAPS; return mnt_table_parse_file(tb, filename); }
/* * See if device has been mounted by looking in mount table. If so, set * device name and mount point name, and return 1, otherwise return 0. */ static int device_get_mountpoint(char **devname, char **mnt) { struct libmnt_fs *fs; int rc; *mnt = NULL; if (!mtab) { mtab = mnt_new_table(); if (!mtab) err(EXIT_FAILURE, _("failed to initialize libmount table")); cache = mnt_new_cache(); mnt_table_set_cache(mtab, cache); if (p_option) rc = mnt_table_parse_file(mtab, _PATH_PROC_MOUNTINFO); else rc = mnt_table_parse_mtab(mtab, NULL); if (rc) err(EXIT_FAILURE, _("failed to parse mount table")); } fs = mnt_table_find_source(mtab, *devname, MNT_ITER_BACKWARD); if (!fs) { /* maybe 'devname' is mountpoint rather than a real device */ fs = mnt_table_find_target(mtab, *devname, MNT_ITER_BACKWARD); if (fs) { free(*devname); *devname = xstrdup(mnt_fs_get_source(fs)); } } if (fs) { *mnt = xstrdup(mnt_fs_get_target(fs)); /* We'll call umount(), so remove the filesystem from the table * to avoid duplicate results in the next device_get_mountpoint() * call */ mnt_free_fs(fs); } return *mnt ? 0 : -1; }
struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) { struct libmnt_table *tb; struct stat st; assert(filename); if (!filename) return NULL; if (stat(filename, &st)) return NULL; tb = mnt_new_table(); if (tb) { tb->fmt = fmt; if (mnt_table_parse_file(tb, filename) != 0) { mnt_unref_table(tb); tb = NULL; } } return tb; }
struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) { struct libmnt_table *tb; struct stat st; if (!filename) return NULL; if (stat(filename, &st)) return NULL; tb = mnt_new_table(); if (tb) { DBG(TAB, ul_debugobj(tb, "new tab for file: %s", filename)); tb->fmt = fmt; if (mnt_table_parse_file(tb, filename) != 0) { mnt_unref_table(tb); tb = NULL; } } return tb; }
/* Check if there is something important in the utab file. The parsed utab is * stored in context->utab and deallocated by mnt_free_context(). * * This function exists to avoid (if possible) /proc/self/mountinfo usage, so * don't use thigs like mnt_resolve_target(), mnt_context_get_mtab() etc here. * See lookup_umount_fs() for more details. */ static int has_utab_entry(struct libmnt_context *cxt, const char *target) { struct libmnt_cache *cache = NULL; struct libmnt_fs *fs; struct libmnt_iter itr; char *cn = NULL; int rc = 0; assert(cxt); if (!cxt->utab) { const char *path = mnt_get_utab_path(); if (!path || is_file_empty(path)) return 0; cxt->utab = mnt_new_table(); if (!cxt->utab) return 0; cxt->utab->fmt = MNT_FMT_UTAB; if (mnt_table_parse_file(cxt->utab, path)) return 0; } /* paths in utab are canonicalized */ cache = mnt_context_get_cache(cxt); cn = mnt_resolve_path(target, cache); mnt_reset_iter(&itr, MNT_ITER_BACKWARD); while (mnt_table_next_fs(cxt->utab, &itr, &fs) == 0) { if (mnt_fs_streq_target(fs, cn)) { rc = 1; break; } } if (!cache) free(cn); return rc; }
/* * See if device has been mounted by looking in mount table. If so, set * device name and mount point name, and return 1, otherwise return 0. */ static int device_get_mountpoint(char **devname, char **mnt) { struct libmnt_fs *fs; int rc; *mnt = NULL; if (!mtab) { struct libmnt_cache *cache; mtab = mnt_new_table(); if (!mtab) err(EXIT_FAILURE, _("failed to initialize libmount table")); cache = mnt_new_cache(); mnt_table_set_cache(mtab, cache); mnt_unref_cache(cache); if (p_option) rc = mnt_table_parse_file(mtab, _PATH_PROC_MOUNTINFO); else rc = mnt_table_parse_mtab(mtab, NULL); if (rc) err(EXIT_FAILURE, _("failed to parse mount table")); } fs = mnt_table_find_source(mtab, *devname, MNT_ITER_BACKWARD); if (!fs) { /* maybe 'devname' is mountpoint rather than a real device */ fs = mnt_table_find_target(mtab, *devname, MNT_ITER_BACKWARD); if (fs) { free(*devname); *devname = xstrdup(mnt_fs_get_source(fs)); } } if (fs) *mnt = xstrdup(mnt_fs_get_target(fs)); return *mnt ? 0 : -1; }
/* default filename is /proc/self/mountinfo */ int __mnt_table_parse_mtab(struct libmnt_table *tb, const char *filename, struct libmnt_table *u_tb) { int rc = 0, priv_utab = 0; assert(tb); if (filename) DBG(TAB, ul_debugobj(tb, "%s reuested as mtab", filename)); #ifdef USE_LIBMOUNT_SUPPORT_MTAB if (mnt_has_regular_mtab(&filename, NULL)) { DBG(TAB, ul_debugobj(tb, "force mtab usage [filename=%s]", filename)); rc = mnt_table_parse_file(tb, filename); /* * If @filename forces us to read from /proc then also read * utab file to merge userspace mount options. */ if (rc == 0 && is_mountinfo(tb)) goto read_utab; if (!rc) return 0; filename = NULL; /* failed */ } else filename = NULL; /* mtab useless */ #endif if (!filename || strcmp(filename, _PATH_PROC_MOUNTINFO) == 0) { filename = _PATH_PROC_MOUNTINFO; tb->fmt = MNT_FMT_MOUNTINFO; DBG(TAB, ul_debugobj(tb, "mtab parse: #1 read mountinfo")); } else tb->fmt = MNT_FMT_GUESS; rc = mnt_table_parse_file(tb, filename); if (rc) { /* hmm, old kernel? ...try /proc/mounts */ tb->fmt = MNT_FMT_MTAB; return mnt_table_parse_file(tb, _PATH_PROC_MOUNTS); } if (!is_mountinfo(tb)) return 0; #ifdef USE_LIBMOUNT_SUPPORT_MTAB read_utab: #endif DBG(TAB, ul_debugobj(tb, "mtab parse: #2 read utab")); if (mnt_table_get_nents(tb) == 0) return 0; /* empty, ignore utab */ /* * try to read the user specific information from /run/mount/utabs */ if (!u_tb) { const char *utab = mnt_get_utab_path(); if (!utab || is_file_empty(utab)) return 0; u_tb = mnt_new_table(); if (!u_tb) return -ENOMEM; u_tb->fmt = MNT_FMT_UTAB; mnt_table_set_parser_fltrcb(u_tb, tb->fltrcb, tb->fltrcb_data); rc = mnt_table_parse_file(u_tb, utab); priv_utab = 1; } DBG(TAB, ul_debugobj(tb, "mtab parse: #3 merge utab")); if (rc == 0) { struct libmnt_fs *u_fs; struct libmnt_iter itr; mnt_reset_iter(&itr, MNT_ITER_BACKWARD); /* merge user options into mountinfo from the kernel */ while(mnt_table_next_fs(u_tb, &itr, &u_fs) == 0) mnt_table_merge_user_fs(tb, u_fs); } if (priv_utab) mnt_unref_table(u_tb); return 0; }