/* * Called by mtab parser to filter out entries, nonzero means that * entry has to be filter out. */ static int mtab_filter(struct libmnt_fs *fs, void *data) { if (!fs || !data) return 0; if (mnt_fs_streq_target(fs, data)) return 0; if (mnt_fs_streq_srcpath(fs, data)) return 0; return 1; }
/* * 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 *r = mnt_fs_get_root(fs); if (fs->flags & MNT_FS_MERGED) continue; if (r && strcmp(r, root) == 0 && mnt_fs_streq_target(fs, target) && mnt_fs_streq_srcpath(fs, src)) 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_resolve_target: * @path: "native" path, a potential mount point * @cache: cache for results or NULL. * * Like mnt_resolve_path(), unless @cache is not NULL and * mnt_cache_set_targets(cache, mtab) was called: if @path is found in the * cached @mtab and the matching entry was provided by the kernel, assume that * @path is already canonicalized. By avoiding a call to realpath(2) on * known mount points, there is a lower risk of stepping on a stale mount * point, which can result in an application freeze. This is also faster in * general, as stat(2) on a mount point is slower than on a regular file. * * Returns: absolute path or NULL in case of error. The result has to be * deallocated by free() if @cache is NULL. */ char *mnt_resolve_target(const char *path, struct libmnt_cache *cache) { char *p = NULL; /*DBG(CACHE, ul_debugobj(cache, "resolving target %s", path));*/ if (!cache || !cache->mtab) return mnt_resolve_path(path, cache); p = (char *) cache_find_path(cache, path); if (p) return p; else { struct libmnt_iter itr; struct libmnt_fs *fs = NULL; mnt_reset_iter(&itr, MNT_ITER_BACKWARD); while (mnt_table_next_fs(cache->mtab, &itr, &fs) == 0) { if (!mnt_fs_is_kernel(fs) || mnt_fs_is_swaparea(fs) || !mnt_fs_streq_target(fs, path)) continue; p = strdup(path); if (!p) return NULL; /* ENOMEM */ if (cache_add_entry(cache, p, p, MNT_CACHE_ISPATH)) { free(p); return NULL; /* ENOMEM */ } break; } } if (!p) p = canonicalize_path_and_cache(path, cache); return p; }
/* 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; }