static int poll_table(struct libmnt_table *tb, const char *tabfile,
		  int timeout, struct libscols_table *table, int direction)
{
	FILE *f = NULL;
	int rc = -1;
	struct libmnt_iter *itr = NULL;
	struct libmnt_table *tb_new;
	struct libmnt_tabdiff *diff = NULL;
	struct pollfd fds[1];

	tb_new = mnt_new_table();
	if (!tb_new) {
		warn(_("failed to initialize libmount table"));
		goto done;
	}

	itr = mnt_new_iter(direction);
	if (!itr) {
		warn(_("failed to initialize libmount iterator"));
		goto done;
	}

	diff = mnt_new_tabdiff();
	if (!diff) {
		warn(_("failed to initialize libmount tabdiff"));
		goto done;
	}

	/* cache is unnecessary to detect changes */
	mnt_table_set_cache(tb, NULL);
	mnt_table_set_cache(tb_new, NULL);

	f = fopen(tabfile, "r");
	if (!f) {
		warn(_("cannot open %s"), tabfile);
		goto done;
	}

	mnt_table_set_parser_errcb(tb_new, parser_errcb);

	fds[0].fd = fileno(f);
	fds[0].events = POLLPRI;

	while (1) {
		struct libmnt_table *tmp;
		struct libmnt_fs *old, *new;
		int change, count;

		count = poll(fds, 1, timeout);
		if (count == 0)
			break;	/* timeout */
		if (count < 0) {
			warn(_("poll() failed"));
			goto done;
		}

		rewind(f);
		rc = mnt_table_parse_stream(tb_new, f, tabfile);
		if (!rc)
			rc = mnt_diff_tables(diff, tb, tb_new);
		if (rc < 0)
			goto done;

		count = 0;
		mnt_reset_iter(itr, direction);
		while(mnt_tabdiff_next_change(
				diff, itr, &old, &new, &change) == 0) {

			if (!has_poll_action(change))
				continue;
			if (!poll_match(new ? new : old))
				continue;
			count++;
			rc = !add_tabdiff_line(table, new, old, change);
			if (rc)
				goto done;
			if (flags & FL_FIRSTONLY)
				break;
		}

		if (count) {
			rc = scols_table_print_range(table, NULL, NULL);
			if (rc == 0)
				fputc('\n', scols_table_get_stream(table));
			fflush(stdout);
			if (rc)
				goto done;
		}

		/* swap tables */
		tmp = tb;
		tb = tb_new;
		tb_new = tmp;

		/* remove already printed lines to reduce memory usage */
		scols_table_remove_lines(table);
		mnt_reset_table(tb_new);

		if (count && (flags & FL_FIRSTONLY))
			break;
	}

	rc = 0;
done:
	mnt_unref_table(tb_new);
	mnt_free_tabdiff(diff);
	mnt_free_iter(itr);
	if (f)
		fclose(f);
	return rc;
}
static int poll_table(struct libmnt_table *tb, const char *tabfile,
		  int timeout, struct libscols_table *table, int direction)
{
	FILE *f = NULL;
	int rc = -1;
	struct libmnt_iter *itr = NULL;
	struct libmnt_table *tb_new;
	struct libmnt_tabdiff *diff = NULL;
	struct pollfd fds[1];

	tb_new = mnt_new_table();
	if (!tb_new) {
		warn(_("failed to initialize libmount table"));
		goto done;
	}

	itr = mnt_new_iter(direction);
	if (!itr) {
		warn(_("failed to initialize libmount iterator"));
		goto done;
	}

	diff = mnt_new_tabdiff();
	if (!diff) {
		warn(_("failed to initialize libmount tabdiff"));
		goto done;
	}

	 
	mnt_table_set_cache(tb, NULL);
	mnt_table_set_cache(tb_new, NULL);

	f = fopen(tabfile, "r");
	if (!f) {
		warn(_("cannot open %s"), tabfile);
		goto done;
	}

	mnt_table_set_parser_errcb(tb_new, parser_errcb);

	fds[0].fd = fileno(f);
	fds[0].events = POLLPRI;

	while (1) {
		struct libmnt_table *tmp;
		struct libmnt_fs *old, *new;
		int change, count;

		count = poll(fds, 1, timeout);
		if (count == 0)
			break;	 
		if (count < 0) {
			warn(_("poll() failed"));
			goto done;
		}

		rewind(f);
		rc = mnt_table_parse_stream(tb_new, f, tabfile);
		if (!rc)
			rc = mnt_diff_tables(diff, tb, tb_new);
		if (rc < 0)
			goto done;

		count = 0;
		mnt_reset_iter(itr, direction);
		while(mnt_tabdiff_next_change(
				diff, itr, &old, &new, &change) == 0) {

			if (!has_poll_action(change))
				continue;
			if (!poll_match(new ? new : old))
				continue;
			count++;
			rc = !add_tabdiff_line(table, new, old, change);
			if (rc)
				goto done;
			if (flags & FL_FIRSTONLY)
				break;
		}

		if (count) {
			rc = scols_table_print_range(table, NULL, NULL);
			if (rc == 0)
				fputc('\n', scols_table_get_stream(table));
			fflush(stdout);
			if (rc)
				goto done;
		}

		 
		tmp = tb;
		tb = tb_new;
		tb_new = tmp;

		 
		scols_table_remove_lines(table);
		mnt_reset_table(tb_new);

		if (count && (flags & FL_FIRSTONLY))
			break;
	}

	rc = 0;
done:
	mnt_unref_table(tb_new);
	mnt_free_tabdiff(diff);
	mnt_free_iter(itr);
	if (f)
		fclose(f);
	return rc;
}