12a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu#include "restore.h"
217c577ace7fcaae08401233cc9debde2d574b756Eric Paris#include <glob.h>
396cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh#include <selinux/context.h>
42a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
52a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu#define SKIP -2
62a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu#define ERR -1
72a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu#define MAX_EXCLUDES 1000
82a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
92a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu/*
102a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * The hash table of associations, hashed by inode number.
112a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * Chaining is used for collisions, with elements ordered
122a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * by inode number in each bucket.  Each hash bucket has a dummy
132a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * header.
142a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu */
152a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu#define HASH_BITS 16
162a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu#define HASH_BUCKETS (1 << HASH_BITS)
172a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu#define HASH_MASK (HASH_BUCKETS-1)
182a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
192a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu/*
202a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * An association between an inode and a context.
212a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu */
222a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liutypedef struct file_spec {
232a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	ino_t ino;		/* inode number */
242a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	char *con;		/* matched context */
252a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	char *file;		/* full pathname */
262a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	struct file_spec *next;	/* next association in hash bucket chain */
272a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu} file_spec_t;
282a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
292a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustruct edir {
302a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	char *directory;
312a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	size_t size;
322a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu};
332a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
342a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
352a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic file_spec_t *fl_head;
362a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic int filespec_add(ino_t ino, const security_context_t con, const char *file);
372a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustruct restore_opts *r_opts = NULL;
382a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic void filespec_destroy(void);
392a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic void filespec_eval(void);
402a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic int excludeCtr = 0;
412a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic struct edir excludeArray[MAX_EXCLUDES];
422a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
432a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuvoid remove_exclude(const char *directory)
442a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
452a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	int i = 0;
462a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	for (i = 0; i < excludeCtr; i++) {
472a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (strcmp(directory, excludeArray[i].directory) == 0) {
482a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			free(excludeArray[i].directory);
492a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (i != excludeCtr-1)
502a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				excludeArray[i] = excludeArray[excludeCtr-1];
512a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			excludeCtr--;
522a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			return;
532a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
542a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
552a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return;
562a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
572a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
582a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuvoid restore_init(struct restore_opts *opts)
592a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
602a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	r_opts = opts;
612a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	struct selinux_opt selinux_opts[] = {
622a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		{ SELABEL_OPT_VALIDATE, r_opts->selabel_opt_validate },
632a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		{ SELABEL_OPT_PATH, r_opts->selabel_opt_path }
642a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	};
652a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	r_opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 2);
662a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!r_opts->hnd) {
672a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		perror(r_opts->selabel_opt_path);
682a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		exit(1);
692a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
702a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
712a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
722a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuvoid restore_finish()
732a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
742a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	int i;
752a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	for (i = 0; i < excludeCtr; i++) {
762a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		free(excludeArray[i].directory);
772a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
782a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
792a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
802a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic int match(const char *name, struct stat *sb, char **con)
812a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
822a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!(r_opts->hard_links) && !S_ISDIR(sb->st_mode) && (sb->st_nlink > 1)) {
832a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(stderr, "Warning! %s refers to a file with more than one hard link, not fixing hard links.\n",
842a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu					name);
852a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return -1;
862a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
872a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
882a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (NULL != r_opts->rootpath) {
892a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (0 != strncmp(r_opts->rootpath, name, r_opts->rootpathlen)) {
902a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fprintf(stderr, "%s:  %s is not located in %s\n",
912a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				r_opts->progname, name, r_opts->rootpath);
922a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			return -1;
932a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
942a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		name += r_opts->rootpathlen;
952a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
962a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
972a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (r_opts->rootpath != NULL && name[0] == '\0')
982a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		/* this is actually the root dir of the alt root */
992a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return selabel_lookup_raw(r_opts->hnd, con, "/", sb->st_mode);
1002a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	else
1012a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return selabel_lookup_raw(r_opts->hnd, con, name, sb->st_mode);
1022a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
10336f1ccbb5743749c404ad8f960867923544b90d9Dan Walshstatic int restore(FTSENT *ftsent, int recurse)
1042a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
1052a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	char *my_file = strdupa(ftsent->fts_path);
106b9b7bddb28c85a7cc2340c753f37b21bd7a14dbdDan Walsh	int ret = -1;
10796cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	security_context_t curcon = NULL, newcon = NULL;
108960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	float progress;
10936f1ccbb5743749c404ad8f960867923544b90d9Dan Walsh	if (match(my_file, ftsent->fts_statp, &newcon) < 0) {
11036f1ccbb5743749c404ad8f960867923544b90d9Dan Walsh		if ((errno == ENOENT) && ((!recurse) || (r_opts->verbose)))
11136f1ccbb5743749c404ad8f960867923544b90d9Dan Walsh			fprintf(stderr, "%s:  Warning no default label for %s\n", r_opts->progname, my_file);
1122a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
1132a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		/* Check for no matching specification. */
1142a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return (errno == ENOENT) ? 0 : -1;
11536f1ccbb5743749c404ad8f960867923544b90d9Dan Walsh	}
1162a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
1172a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (r_opts->progress) {
1182a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		r_opts->count++;
1192a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (r_opts->count % STAR_COUNT == 0) {
120960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser			if (r_opts->progress == 1) {
1216020fb0b1ec698f354e425051a69f9a38d7151f4Dan Walsh				fprintf(stdout, "\r%luk", (size_t) r_opts->count / STAR_COUNT );
122960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser			} else {
123960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser				if (r_opts->nfile > 0) {
124960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser					progress = (r_opts->count < r_opts->nfile) ? (100.0 * r_opts->count / r_opts->nfile) : 100;
125960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser					fprintf(stdout, "\r%-.1f%%", progress);
126960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser				}
127960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser			}
1282a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fflush(stdout);
1292a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
1302a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
1312a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
1322a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	/*
1332a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 * Try to add an association between this inode and
1342a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 * this specification.  If there is already an association
1352a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 * for this inode and it conflicts with this specification,
1362a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 * then use the last matching specification.
1372a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 */
1382a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (r_opts->add_assoc) {
1392a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		ret = filespec_add(ftsent->fts_statp->st_ino, newcon, my_file);
1402a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (ret < 0)
1412a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			goto err;
1422a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
1432a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (ret > 0)
1442a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			/* There was already an association and it took precedence. */
1452a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			goto out;
1462a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
1472a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
1482a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (r_opts->debug) {
1492a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		printf("%s:  %s matched by %s\n", r_opts->progname, my_file, newcon);
1502a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
1512a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
15296cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	/*
15396cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	 * Do not relabel if their is no default specification for this file
15496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	 */
15596cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh
15696cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	if (strcmp(newcon, "<<none>>") == 0) {
15796cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		goto out;
15896cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	}
15996cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh
1602a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	/* Get the current context of the file. */
16196cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	ret = lgetfilecon_raw(ftsent->fts_accpath, &curcon);
1622a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (ret < 0) {
1632a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (errno == ENODATA) {
16496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			curcon = NULL;
1652a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		} else {
1662a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fprintf(stderr, "%s get context on %s failed: '%s'\n",
1672a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				r_opts->progname, my_file, strerror(errno));
1682a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			goto err;
1692a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
17096cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	}
17196cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh
1722a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	/* lgetfilecon returns number of characters and ret needs to be reset
1732a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 * to 0.
1742a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 */
1752a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	ret = 0;
1762a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
1772a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	/*
17896cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	 * Do not relabel the file if the file is already labeled according to
17996cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	 * the specification.
1802a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 */
18196cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	if (curcon && (strcmp(curcon, newcon) == 0)) {
1822a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		goto out;
1832a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
1842a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
18596cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	if (!r_opts->force && curcon && (is_context_customizable(curcon) > 0)) {
1862a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (r_opts->verbose > 1) {
1872a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fprintf(stderr,
1882a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				"%s: %s not reset customized by admin to %s\n",
18996cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh				r_opts->progname, my_file, curcon);
1902a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
1912a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		goto out;
1922a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
1932a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
19496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	/*
19596cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	 *  Do not change label unless this is a force or the type is different
19696cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	 */
19796cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	if (!r_opts->force && curcon) {
19896cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		int types_differ = 0;
19996cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		context_t cona;
20096cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		context_t conb;
20196cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		int err = 0;
20296cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		cona = context_new(curcon);
20396cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		if (! cona) {
20496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			goto out;
20596cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		}
20696cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		conb = context_new(newcon);
20796cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		if (! conb) {
20896cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			context_free(cona);
20996cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			goto out;
21096cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		}
21196cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh
21296cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		types_differ = strcmp(context_type_get(cona), context_type_get(conb));
21396cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		if (types_differ) {
21496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			err |= context_user_set(conb, context_user_get(cona));
21596cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			err |= context_role_set(conb, context_role_get(cona));
21696cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			err |= context_range_set(conb, context_range_get(cona));
21796cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			if (!err) {
21896cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh				freecon(newcon);
21996cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh				newcon = strdup(context_str(conb));
22096cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			}
22196cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		}
22296cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		context_free(cona);
22396cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		context_free(conb);
22496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh
22596cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		if (!types_differ || err) {
22696cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			goto out;
2272a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
2282a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
2292a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
23096cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	if (r_opts->verbose) {
23196cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		printf("%s reset %s context %s->%s\n",
23296cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		       r_opts->progname, my_file, curcon ?: "", newcon);
23396cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	}
23496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh
235687ff489e62aecda2d165be87cdb927799dbe16dDan Walsh	if (r_opts->logging && r_opts->change) {
23696cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh		if (curcon)
2372a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			syslog(LOG_INFO, "relabeling %s from %s to %s\n",
23896cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh			       my_file, curcon, newcon);
2392a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		else
2402a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			syslog(LOG_INFO, "labeling %s to %s\n",
2412a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			       my_file, newcon);
2422a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
2432a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
24496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	if (r_opts->outfile)
2452a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(r_opts->outfile, "%s\n", my_file);
2462a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
2472a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	/*
2482a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 * Do not relabel the file if -n was used.
2492a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 */
25096cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	if (!r_opts->change)
2512a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		goto out;
2522a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
2532a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	/*
2542a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 * Relabel the file to the specified context.
2552a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	 */
2562a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	ret = lsetfilecon(ftsent->fts_accpath, newcon);
2572a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (ret) {
2582a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(stderr, "%s set context %s->%s failed:'%s'\n",
2592a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			r_opts->progname, my_file, newcon, strerror(errno));
2602a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		goto skip;
2612a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
26230ef7451bc2d160f4749764dd092ab50b6a74becRussell Coker	ret = 0;
2632a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuout:
26496cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	freecon(curcon);
2652a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	freecon(newcon);
2662a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return ret;
2672a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuskip:
26896cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	freecon(curcon);
2692a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	freecon(newcon);
2702a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return SKIP;
2712a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuerr:
27296cedba3e59aa474f0f040da5108a17bba45ce6cDan Walsh	freecon(curcon);
2732a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	freecon(newcon);
2742a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return ERR;
2752a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
2762a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu/*
2772a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * Apply the last matching specification to a file.
2782a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * This function is called by fts on each file during
2792a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * the directory traversal.
2802a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu */
28136f1ccbb5743749c404ad8f960867923544b90d9Dan Walshstatic int apply_spec(FTSENT *ftsent, int recurse)
2822a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
2832a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (ftsent->fts_info == FTS_DNR) {
2842a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(stderr, "%s:  unable to read directory %s\n",
2852a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			r_opts->progname, ftsent->fts_path);
2862a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return SKIP;
2872a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
2882a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
28936f1ccbb5743749c404ad8f960867923544b90d9Dan Walsh	int rc = restore(ftsent, recurse);
2902a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (rc == ERR) {
2912a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (!r_opts->abort_on_error)
2922a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			return SKIP;
2932a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
2942a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return rc;
2952a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
2962a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
297960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser#include <sys/statvfs.h>
298960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser
2992a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic int process_one(char *name, int recurse_this_path)
3002a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
3012a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	int rc = 0;
3022a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	const char *namelist[2] = {name, NULL};
3032a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	dev_t dev_num = 0;
3045763e720d88ff2dcc7066cd61ca0c2836566e93fEric Paris	FTS *fts_handle = NULL;
3055763e720d88ff2dcc7066cd61ca0c2836566e93fEric Paris	FTSENT *ftsent = NULL;
3065763e720d88ff2dcc7066cd61ca0c2836566e93fEric Paris
3075763e720d88ff2dcc7066cd61ca0c2836566e93fEric Paris	if (r_opts == NULL){
3085763e720d88ff2dcc7066cd61ca0c2836566e93fEric Paris		fprintf(stderr,
3095763e720d88ff2dcc7066cd61ca0c2836566e93fEric Paris			"Must call initialize first!");
3105763e720d88ff2dcc7066cd61ca0c2836566e93fEric Paris		goto err;
3115763e720d88ff2dcc7066cd61ca0c2836566e93fEric Paris	}
3122a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
3132a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	fts_handle = fts_open((char **)namelist, r_opts->fts_flags, NULL);
3142a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (fts_handle  == NULL) {
3152a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(stderr,
3162a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			"%s: error while labeling %s:  %s\n",
3172a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			r_opts->progname, namelist[0], strerror(errno));
3182a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		goto err;
3192a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
3202a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
3212a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
3222a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	ftsent = fts_read(fts_handle);
323f23e078018b5313dd6a320b401173cc834b9450dDan Walsh	if (ftsent == NULL) {
324f23e078018b5313dd6a320b401173cc834b9450dDan Walsh		fprintf(stderr,
325f23e078018b5313dd6a320b401173cc834b9450dDan Walsh			"%s: error while labeling %s:  %s\n",
326f23e078018b5313dd6a320b401173cc834b9450dDan Walsh			r_opts->progname, namelist[0], strerror(errno));
327f23e078018b5313dd6a320b401173cc834b9450dDan Walsh		goto err;
3282a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
3292a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
330f23e078018b5313dd6a320b401173cc834b9450dDan Walsh	/* Keep the inode of the first one. */
331f23e078018b5313dd6a320b401173cc834b9450dDan Walsh	dev_num = ftsent->fts_statp->st_dev;
332f23e078018b5313dd6a320b401173cc834b9450dDan Walsh
3332a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	do {
3342a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		rc = 0;
3352a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		/* Skip the post order nodes. */
3362a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (ftsent->fts_info == FTS_DP)
3372a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			continue;
3382a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		/* If the XDEV flag is set and the device is different */
3392a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (ftsent->fts_statp->st_dev != dev_num &&
3402a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		    FTS_XDEV == (r_opts->fts_flags & FTS_XDEV))
3412a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			continue;
3422a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (excludeCtr > 0) {
3432a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (exclude(ftsent->fts_path)) {
3442a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				fts_set(fts_handle, ftsent, FTS_SKIP);
3452a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				continue;
3462a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			}
3472a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
348960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser
34936f1ccbb5743749c404ad8f960867923544b90d9Dan Walsh		rc = apply_spec(ftsent, recurse_this_path);
3502a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (rc == SKIP)
3512a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fts_set(fts_handle, ftsent, FTS_SKIP);
3522a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (rc == ERR)
3532a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			goto err;
3542a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (!recurse_this_path)
3552a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			break;
3562a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	} while ((ftsent = fts_read(fts_handle)) != NULL);
3572a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
3582a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuout:
3592a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (r_opts->add_assoc) {
3602a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (!r_opts->quiet)
3612a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			filespec_eval();
3622a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		filespec_destroy();
3632a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
3642a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (fts_handle)
3652a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fts_close(fts_handle);
3662a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return rc;
3672a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
3682a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuerr:
3692a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	rc = -1;
3702a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	goto out;
3712a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
3722a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
37317c577ace7fcaae08401233cc9debde2d574b756Eric Parisint process_glob(char *name, int recurse) {
37417c577ace7fcaae08401233cc9debde2d574b756Eric Paris	glob_t globbuf;
37517c577ace7fcaae08401233cc9debde2d574b756Eric Paris	size_t i = 0;
37617c577ace7fcaae08401233cc9debde2d574b756Eric Paris	int errors;
37717c577ace7fcaae08401233cc9debde2d574b756Eric Paris	memset(&globbuf, 0, sizeof(globbuf));
378e3048525adc8ac667fb57739b046b3b81ef7a451Dan Walsh	errors = glob(name, GLOB_TILDE | GLOB_PERIOD | GLOB_NOCHECK | GLOB_BRACE, NULL, &globbuf);
379ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh	if (errors)
380ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh		return errors;
381ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh
382ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh	for (i = 0; i < globbuf.gl_pathc; i++) {
383ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh		int len = strlen(globbuf.gl_pathv[i]) -2;
384ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh		if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0)
385ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh			continue;
386ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh		if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0)
387ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh			continue;
388af1c9091e32acd11b047681b46eee132f7fb6aadMartin Orr		int rc = process_one_realpath(globbuf.gl_pathv[i], recurse);
389af1c9091e32acd11b047681b46eee132f7fb6aadMartin Orr		if (rc < 0)
390af1c9091e32acd11b047681b46eee132f7fb6aadMartin Orr			errors = rc;
39117c577ace7fcaae08401233cc9debde2d574b756Eric Paris	}
392ddc5063c167ea3c253262c79c177d72c6aab68f9Dan Walsh	globfree(&globbuf);
39317c577ace7fcaae08401233cc9debde2d574b756Eric Paris	return errors;
39417c577ace7fcaae08401233cc9debde2d574b756Eric Paris}
39517c577ace7fcaae08401233cc9debde2d574b756Eric Paris
3962a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuint process_one_realpath(char *name, int recurse)
3972a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
3982a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	int rc = 0;
3992a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	char *p;
400a2db3f2df850362a6f6f6ddf779bb20f0bba9cbeEric Paris	struct stat64 sb;
4012a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4022a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (r_opts == NULL){
4032a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(stderr,
4042a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			"Must call initialize first!");
4052a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return -1;
4062a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
4072a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4082a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!r_opts->expand_realpath) {
4092a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return process_one(name, recurse);
4102a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	} else {
411a2db3f2df850362a6f6f6ddf779bb20f0bba9cbeEric Paris		rc = lstat64(name, &sb);
4122a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (rc < 0) {
41330ad11feb9c2557db22d6a1eeedaa791a9b9f269Eric Paris			if (r_opts->ignore_enoent && errno == ENOENT)
41430ad11feb9c2557db22d6a1eeedaa791a9b9f269Eric Paris				return 0;
4152a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fprintf(stderr, "%s:  lstat(%s) failed:  %s\n",
4162a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				r_opts->progname, name,	strerror(errno));
4172a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			return -1;
4182a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
4192a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4202a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (S_ISLNK(sb.st_mode)) {
4212a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			char path[PATH_MAX + 1];
4222a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
423d5475a909a570d72c75bc86dbb4e449c0ba7bb57Eric Paris			rc = realpath_not_final(name, path);
4242a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (rc < 0)
4252a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				return rc;
4262a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			rc = process_one(path, 0);
4272a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (rc < 0)
4282a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				return rc;
4292a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4302a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			p = realpath(name, NULL);
4312a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (p) {
4322a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				rc = process_one(p, recurse);
4332a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				free(p);
4342a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			}
4352a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			return rc;
4362a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		} else {
4372a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			p = realpath(name, NULL);
4382a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (!p) {
4392a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				fprintf(stderr, "realpath(%s) failed %s\n", name,
4402a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu					strerror(errno));
4412a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				return -1;
4422a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			}
4432a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			rc = process_one(p, recurse);
4442a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			free(p);
4452a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			return rc;
4462a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
4472a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
4482a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
4492a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
45066564a67cf3fd8b282d1222aaec8b02ae97611fbEric Parisint exclude(const char *file)
4512a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
4522a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	int i = 0;
4532a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	for (i = 0; i < excludeCtr; i++) {
4542a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (strncmp
4552a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		    (file, excludeArray[i].directory,
4562a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		     excludeArray[i].size) == 0) {
4572a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (file[excludeArray[i].size] == 0
4582a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			    || file[excludeArray[i].size] == '/') {
4592a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				return 1;
4602a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			}
4612a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
4622a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
4632a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return 0;
4642a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
4652a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4662a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liuint add_exclude(const char *directory)
4672a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
4682a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	size_t len = 0;
4692a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4702a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (directory == NULL || directory[0] != '/') {
4712a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(stderr, "Full path required for exclude: %s.\n",
4722a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			directory);
4732a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return 1;
4742a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
4752a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (excludeCtr == MAX_EXCLUDES) {
4762a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(stderr, "Maximum excludes %d exceeded.\n",
4772a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			MAX_EXCLUDES);
4782a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return 1;
4792a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
4802a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4812a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	len = strlen(directory);
4822a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	while (len > 1 && directory[len - 1] == '/') {
4832a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		len--;
4842a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
4852a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	excludeArray[excludeCtr].directory = strndup(directory, len);
4862a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4872a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (excludeArray[excludeCtr].directory == NULL) {
4882a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fprintf(stderr, "Out of memory.\n");
4892a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return 1;
4902a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
4912a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	excludeArray[excludeCtr++].size = len;
4922a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4932a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return 0;
4942a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
4952a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
4962a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu/*
4972a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * Evaluate the association hash table distribution.
4982a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu */
4992a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic void filespec_eval(void)
5002a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
5012a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	file_spec_t *fl;
5022a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	int h, used, nel, len, longest;
5032a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5042a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!fl_head)
5052a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return;
5062a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5072a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	used = 0;
5082a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	longest = 0;
5092a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	nel = 0;
5102a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	for (h = 0; h < HASH_BUCKETS; h++) {
5112a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		len = 0;
5122a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		for (fl = fl_head[h].next; fl; fl = fl->next) {
5132a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			len++;
5142a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
5152a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (len)
5162a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			used++;
5172a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (len > longest)
5182a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			longest = len;
5192a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		nel += len;
5202a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
5212a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5222a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (r_opts->verbose > 1)
5232a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		printf
5242a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		    ("%s:  hash table stats: %d elements, %d/%d buckets used, longest chain length %d\n",
5252a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		     __FUNCTION__, nel, used, HASH_BUCKETS, longest);
5262a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
5272a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5282a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu/*
5292a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * Destroy the association hash table.
5302a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu */
5312a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic void filespec_destroy(void)
5322a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
5332a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	file_spec_t *fl, *tmp;
5342a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	int h;
5352a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5362a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!fl_head)
5372a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		return;
5382a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5392a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	for (h = 0; h < HASH_BUCKETS; h++) {
5402a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fl = fl_head[h].next;
5412a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		while (fl) {
5422a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			tmp = fl;
5432a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fl = fl->next;
5442a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			freecon(tmp->con);
5452a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			free(tmp->file);
5462a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			free(tmp);
5472a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
5482a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fl_head[h].next = NULL;
5492a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
5502a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	free(fl_head);
5512a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	fl_head = NULL;
5522a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
5532a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu/*
5542a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * Try to add an association between an inode and a context.
5552a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * If there is a different context that matched the inode,
5562a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu * then use the first context that matched.
5572a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu */
5582a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liustatic int filespec_add(ino_t ino, const security_context_t con, const char *file)
5592a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu{
5602a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	file_spec_t *prevfl, *fl;
5612a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	int h, ret;
562a2db3f2df850362a6f6f6ddf779bb20f0bba9cbeEric Paris	struct stat64 sb;
5632a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5642a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!fl_head) {
5652a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS);
5662a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (!fl_head)
5672a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			goto oom;
5682a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS);
5692a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
5702a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5712a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	h = (ino + (ino >> HASH_BITS)) & HASH_MASK;
5722a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	for (prevfl = &fl_head[h], fl = fl_head[h].next; fl;
5732a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	     prevfl = fl, fl = fl->next) {
5742a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (ino == fl->ino) {
575a2db3f2df850362a6f6f6ddf779bb20f0bba9cbeEric Paris			ret = lstat64(fl->file, &sb);
5762a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (ret < 0 || sb.st_ino != ino) {
5772a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				freecon(fl->con);
5782a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				free(fl->file);
5792a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				fl->file = strdup(file);
5802a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				if (!fl->file)
5812a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu					goto oom;
5822a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				fl->con = strdup(con);
5832a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				if (!fl->con)
5842a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu					goto oom;
5852a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				return 1;
5862a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			}
5872a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5882a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (strcmp(fl->con, con) == 0)
5892a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				return 1;
5902a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
5912a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fprintf(stderr,
5922a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				"%s:  conflicting specifications for %s and %s, using %s.\n",
5932a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				__FUNCTION__, file, fl->file, fl->con);
5942a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			free(fl->file);
5952a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			fl->file = strdup(file);
5962a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			if (!fl->file)
5972a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu				goto oom;
5982a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			return 1;
5992a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		}
6002a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
6012a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		if (ino > fl->ino)
6022a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu			break;
6032a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	}
6042a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
6052a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	fl = malloc(sizeof(file_spec_t));
6062a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!fl)
6072a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		goto oom;
6082a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	fl->ino = ino;
6092a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	fl->con = strdup(con);
6102a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!fl->con)
6112a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		goto oom_freefl;
6122a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	fl->file = strdup(file);
6132a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	if (!fl->file)
6142a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		goto oom_freefl;
6152a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	fl->next = prevfl->next;
6162a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	prevfl->next = fl;
6172a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return 0;
6182a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu      oom_freefl:
6192a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	free(fl);
6202a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu      oom:
6212a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	fprintf(stderr,
6222a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		"%s:  insufficient memory for file label entry for %s\n",
6232a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu		__FUNCTION__, file);
6242a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu	return -1;
6252a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu}
6262a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
6275ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris#include <sys/utsname.h>
628960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiserint file_system_count(char *name) {
629960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	struct statvfs statvfs_buf;
630960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	int nfile = 0;
631960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	memset(&statvfs_buf, 0, sizeof(statvfs_buf));
632960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	if (!statvfs(name, &statvfs_buf)) {
633960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser		nfile = statvfs_buf.f_files - statvfs_buf.f_ffree;
634960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	}
635960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	return nfile;
636960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser}
637960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser
6385ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris/*
6395ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris   Search /proc/mounts for all file systems that do not support extended
6405ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris   attributes and add them to the exclude directory table.  File systems
641960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser   that support security labels have the seclabel option, return total file count
6425ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris*/
643960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiserint exclude_non_seclabel_mounts()
6445ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris{
6455ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	struct utsname uts;
6465ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	FILE *fp;
6475ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	size_t len;
6485ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	ssize_t num;
6495ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	int index = 0, found = 0;
6505ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	char *mount_info[4];
6515ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	char *buf = NULL, *item;
652960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	int nfile = 0;
6535ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	/* Check to see if the kernel supports seclabel */
6545ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	if (uname(&uts) == 0 && strverscmp(uts.release, "2.6.30") < 0)
655960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser		return 0;
6565ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	if (is_selinux_enabled() <= 0)
657960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser		return 0;
6585ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris
6595ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	fp = fopen("/proc/mounts", "r");
6605ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	if (!fp)
661960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser		return 0;
6625ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris
6635ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	while ((num = getline(&buf, &len, fp)) != -1) {
6645ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		found = 0;
6655ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		index = 0;
6665ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		item = strtok(buf, " ");
6675ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		while (item != NULL) {
6685ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			mount_info[index] = item;
6695ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			if (index == 3)
6705ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris				break;
6715ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			index++;
6725ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			item = strtok(NULL, " ");
6735ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		}
6745ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		if (index < 3) {
6755ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			fprintf(stderr,
6765ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris				"/proc/mounts record \"%s\" has incorrect format.\n",
6775ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris				buf);
6785ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			continue;
6795ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		}
6805ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris
6815ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		/* remove pre-existing entry */
6825ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		remove_exclude(mount_info[1]);
6832a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
6845ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		item = strtok(mount_info[3], ",");
6855ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		while (item != NULL) {
6865ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			if (strcmp(item, "seclabel") == 0) {
6875ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris				found = 1;
688960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser				nfile += file_system_count(mount_info[1]);
6895ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris				break;
6905ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			}
6915ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			item = strtok(NULL, ",");
6925ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		}
6935ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris
6945ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		/* exclude mount points without the seclabel option */
6955ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris		if (!found)
6965ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris			add_exclude(mount_info[1]);
6975ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	}
6985ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris
6995ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris	free(buf);
700e018eec325264aa33dfb25094f3566cc5df5f401Eric Paris	fclose(fp);
701960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	/* return estimated #Files + 5% for directories and hard links */
702960d6ee879f34df84e90394c32a606d6d1be48aeJohn Reiser	return nfile * 1.05;
7035ffa296798f892c6ba4946bd8181036dfddf29c9Eric Paris}
7042a1933d830aae615001e05fd5ca11a6fe0159f9dThomas Liu
705