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