static int update_add_entry(struct libmnt_update *upd, struct libmnt_lock *lc) { struct libmnt_table *tb; int rc = 0; assert(upd); assert(upd->fs); DBG(UPDATE, mnt_debug_h(upd, "%s: add entry", upd->filename)); if (lc) rc = mnt_lock_file(lc); if (rc) return rc; tb = __mnt_new_table_from_file(upd->filename, upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB); if (tb) { struct libmnt_fs *fs = mnt_copy_fs(NULL, upd->fs); if (!fs) rc = -ENOMEM; else { mnt_table_add_fs(tb, fs); rc = update_table(upd, tb); } } if (lc) mnt_unlock_file(lc); mnt_free_table(tb); return rc; }
/** * mnt_table_parse_stream: * @tb: tab pointer * @f: file stream * @filename: filename used for debug and error messages * * Returns: 0 on success, negative number in case of error. */ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) { int nlines = 0; int rc = -1; int flags = 0; pid_t tid = -1; assert(tb); assert(f); assert(filename); DBG(TAB, mnt_debug_h(tb, "%s: start parsing [entries=%d, filter=%s]", filename, mnt_table_get_nents(tb), tb->fltrcb ? "yes" : "not")); /* necessary for /proc/mounts only, the /proc/self/mountinfo * parser sets the flag properly */ if (filename && strcmp(filename, _PATH_PROC_MOUNTS) == 0) flags = MNT_FS_KERNEL; while (!feof(f)) { struct libmnt_fs *fs = mnt_new_fs(); if (!fs) goto err; rc = mnt_table_parse_next(tb, f, fs, filename, &nlines); if (!rc && tb->fltrcb && tb->fltrcb(fs, tb->fltrcb_data)) rc = 1; /* filtered out by callback... */ if (!rc) { rc = mnt_table_add_fs(tb, fs); fs->flags |= flags; if (rc == 0 && tb->fmt == MNT_FMT_MOUNTINFO) rc = kernel_fs_postparse(tb, fs, &tid, filename); } mnt_unref_fs(fs); if (rc) { if (rc == 1) continue; /* recoverable error */ if (feof(f)) break; goto err; /* fatal error */ } } DBG(TAB, mnt_debug_h(tb, "%s: stop parsing (%d entries)", filename, mnt_table_get_nents(tb))); return 0; err: DBG(TAB, mnt_debug_h(tb, "%s: parse error (rc=%d)", filename, rc)); return rc; }
static struct libmnt_fs *add_dummy_fs(const char *device) { struct libmnt_fs *fs = mnt_new_fs(); if (fs && mnt_fs_set_source(fs, device) == 0 && mnt_table_add_fs(fstab, fs) == 0) return fs; mnt_free_fs(fs); err(FSCK_EX_ERROR, _("failed to setup description for %s"), device); }
/** * mnt_table_parse_stream: * @tb: tab pointer * @f: file stream * @filename: filename used for debug and error messages * * Returns: 0 on success, negative number in case of error. */ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) { int nlines = 0; int rc = -1; int flags = 0; pid_t tid = -1; assert(tb); assert(f); assert(filename); DBG(TAB, mnt_debug_h(tb, "%s: start parsing (%d entries)", filename, mnt_table_get_nents(tb))); /* necessary for /proc/mounts only, the /proc/self/mountinfo * parser sets the flag properly */ if (filename && strcmp(filename, _PATH_PROC_MOUNTS) == 0) flags = MNT_FS_KERNEL; while (!feof(f)) { struct libmnt_fs *fs = mnt_new_fs(); if (!fs) goto err; rc = mnt_table_parse_next(tb, f, fs, filename, &nlines); if (!rc) { rc = mnt_table_add_fs(tb, fs); fs->flags |= flags; if (tb->fmt == MNT_FMT_MOUNTINFO && filename) { if (tid == -1) tid = path_to_tid(filename); fs->tid = tid; } } if (rc) { mnt_free_fs(fs); if (rc == 1) continue; /* recoverable error */ if (feof(f)) break; goto err; /* fatal error */ } } DBG(TAB, mnt_debug_h(tb, "%s: stop parsing (%d entries)", filename, mnt_table_get_nents(tb))); return 0; err: DBG(TAB, mnt_debug_h(tb, "%s: parse error (rc=%d)", filename, rc)); return rc; }
/** * mnt_table_parse_stream: * @tb: tab pointer * @f: file stream * @filename: filename used for debug and error messages * * Returns: 0 on success, negative number in case of error. */ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filename) { int rc = -1; int flags = 0; pid_t tid = -1; struct libmnt_fs *fs = NULL; struct libmnt_parser pa = { .line = 0 }; assert(tb); assert(f); assert(filename); DBG(TAB, ul_debugobj(tb, "%s: start parsing [entries=%d, filter=%s]", filename, mnt_table_get_nents(tb), tb->fltrcb ? "yes" : "not")); pa.filename = filename; pa.f = f; /* necessary for /proc/mounts only, the /proc/self/mountinfo * parser sets the flag properly */ if (filename && strcmp(filename, _PATH_PROC_MOUNTS) == 0) flags = MNT_FS_KERNEL; while (!feof(f)) { if (!fs) { fs = mnt_new_fs(); if (!fs) goto err; } rc = mnt_table_parse_next(&pa, tb, fs); if (!rc && tb->fltrcb && tb->fltrcb(fs, tb->fltrcb_data)) rc = 1; /* filtered out by callback... */ if (!rc) { rc = mnt_table_add_fs(tb, fs); fs->flags |= flags; if (rc == 0 && tb->fmt == MNT_FMT_MOUNTINFO) { rc = kernel_fs_postparse(tb, fs, &tid, filename); if (rc) mnt_table_remove_fs(tb, fs); } } if (rc) { if (rc > 0) { mnt_reset_fs(fs); assert(fs->refcount == 1); continue; /* recoverable error, reuse fs*/ } mnt_unref_fs(fs); if (feof(f)) break; goto err; /* fatal error */ } mnt_unref_fs(fs); fs = NULL; } DBG(TAB, ul_debugobj(tb, "%s: stop parsing (%d entries)", filename, mnt_table_get_nents(tb))); parser_cleanup(&pa); return 0; err: DBG(TAB, ul_debugobj(tb, "%s: parse error (rc=%d)", filename, rc)); parser_cleanup(&pa); return rc; } /** * mnt_table_parse_file: * @tb: tab pointer * @filename: file * * Parses the whole table (e.g. /etc/fstab) and appends new records to the @tab. * * The libmount parser ignores broken (syntax error) lines, these lines are * reported to the caller by the errcb() function (see mnt_table_set_parser_errcb()). * * Returns: 0 on success, negative number in case of error. */ int mnt_table_parse_file(struct libmnt_table *tb, const char *filename) { FILE *f; int rc; if (!filename || !tb) return -EINVAL; f = fopen(filename, "r" UL_CLOEXECSTR); if (f) { rc = mnt_table_parse_stream(tb, f, filename); fclose(f); } else rc = -errno; DBG(TAB, ul_debugobj(tb, "parsing done [filename=%s, rc=%d]", filename, rc)); return rc; }