Example #1
0
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;
}
Example #2
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);
}
Example #3
0
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);
}
Example #4
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 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;
}
Example #5
0
static void free_instance(struct fsck_instance *i)
{
	if (lockdisk)
		unlock_disk(i);
	free(i->prog);
	mnt_unref_fs(i->fs);
	free(i);
	return;
}
Example #6
0
/**
 * 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;
}
Example #7
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;
}