static int tabdiff_reset(struct libmnt_tabdiff *df) { assert(df); DBG(DIFF, ul_debugobj(df, "resetting")); /* zeroize all entries and move them to the list of unused */ while (!list_empty(&df->changes)) { struct tabdiff_entry *de = list_entry(df->changes.next, struct tabdiff_entry, changes); list_del(&de->changes); list_add_tail(&de->changes, &df->unused); mnt_unref_fs(de->new_fs); mnt_unref_fs(de->old_fs); de->new_fs = de->old_fs = NULL; de->oper = 0; } df->nchanges = 0; return 0; }
static void free_tabdiff_entry(struct tabdiff_entry *de) { if (!de) return; list_del(&de->changes); mnt_unref_fs(de->new_fs); mnt_unref_fs(de->old_fs); free(de); }
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) { mnt_unref_fs(fs); return fs; } mnt_unref_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 [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 void free_instance(struct fsck_instance *i) { if (lockdisk) unlock_disk(i); free(i->prog); mnt_unref_fs(i->fs); free(i); return; }
/** * mnt_table_remove_fs: * @tb: tab pointer * @fs: new entry * * Removes the @fs from the table and de-increment reference counter of the @fs. The * filesystem with zero reference counter will be deallocated. Don't forget to use * mnt_ref_fs() before call mnt_table_remove_fs() if you want to use @fs later. * * Returns: 0 on success or negative number in case of error. */ int mnt_table_remove_fs(struct libmnt_table *tb, struct libmnt_fs *fs) { if (!tb || !fs) return -EINVAL; list_del(&fs->ents); INIT_LIST_HEAD(&fs->ents); /* otherwise FS still points to the list */ mnt_unref_fs(fs); tb->nents--; return 0; }
/** * 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; }