policycoreutils: setfiles: estimate percent progress

This patch started with work from John Reiser patch to estimate the
percent progress for restorecon/setfiles.

It has a lot of changes since then, to make it only happen on full
relabel, overwrite itself, shows 10ths of %, and does a lot better and
more useful job of estimation.  We get all of the inodes on all mounted
FS.  Since the number of inodes is not fixed and only an estimate I added
5% to the inode number, and forced the number to never go over 100.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Dan Walsh <dwalsh@redhat.com>
This commit is contained in:
John Reiser 2012-02-03 11:56:39 -05:00 committed by Eric Paris
parent fec715a6f2
commit 960d6ee879
7 changed files with 66 additions and 26 deletions

View File

@ -114,6 +114,7 @@ exclude_dirs() {
# Set global Variables
#
fullFlag=0
VERBOSE="-p"
FORCEFLAG=""
DIRS=""
RPMILES=""
@ -176,7 +177,7 @@ if [ -f ${PREFC} -a -x /usr/bin/diff ]; then
esac; \
fi; \
done | \
${RESTORECON} -i -f - -R -p `exclude_dirs`; \
${RESTORECON} ${VERBOSE} -i -f - -R `exclude_dirs`; \
rm -f ${TEMPFILE} ${PREFCTEMPFILE}
fi
}
@ -206,12 +207,12 @@ if [ ! -z "$PREFC" ]; then
fi
if [ ! -z "$RPMFILES" ]; then
for i in `echo "$RPMFILES" | sed 's/,/ /g'`; do
rpmlist $i | ${RESTORECON} ${FORCEFLAG} $* -R -i -f - 2>&1 | cat >> $LOGFILE
rpmlist $i | ${RESTORECON} ${FORCEFLAG} ${VERBOSE} $* -R -i -f - 2>&1 | cat >> $LOGFILE
done
exit $?
fi
if [ ! -z "$FILEPATH" ]; then
${RESTORECON} ${FORCEFLAG} -R $* $FILEPATH 2>&1 | cat >> $LOGFILE
${RESTORECON} ${FORCEFLAG} ${VERBOSE} -R $* $FILEPATH 2>&1 | cat >> $LOGFILE
return
fi
[ -x /usr/sbin/genhomedircon ] && /usr/sbin/genhomedircon
@ -286,7 +287,7 @@ process() {
# Make sure they specified one of the three valid commands
#
case "$1" in
restore) restore -p ;;
restore) restore;;
check) restore -n -v;;
verify) restore -n -o -;;
relabel) relabel;;
@ -317,11 +318,14 @@ if [ $# = 0 ]; then
fi
# See how we were called.
while getopts "C:FfR:l:" i; do
while getopts "C:FfR:l:v" i; do
case "$i" in
f)
fullFlag=1
;;
v)
VERBOSE="-v"
;;
R)
RPMFILES=$OPTARG
;;

View File

@ -5,13 +5,13 @@ fixfiles \- fix file SELinux security contexts.
.SH "SYNOPSIS"
.B fixfiles
.I [-F] [-l logfile ] { check | restore|[-f] relabel | verify } [[dir/file] ... ]
.I [-v] [-F] [-l logfile ] { check | restore|[-f] relabel | verify } [[dir/file] ... ]
.B fixfiles
.I [-F] [ -R rpmpackagename[,rpmpackagename...] ] [-l logfile ] { check | restore | verify }
.I [-v] [-F] [ -R rpmpackagename[,rpmpackagename...] ] [-l logfile ] { check | restore | verify }
.B fixfiles
.I [ -C PREVIOUS_FILECONTEXT ] [-l logfile ] { check | restore | verify }
.I [-v] [ -C PREVIOUS_FILECONTEXT ] [-l logfile ] { check | restore | verify }
.B fixfiles
.I onboot
@ -54,6 +54,10 @@ Use the rpm database to discover all files within the specified packages and res
.B -C PREVIOUS_FILECONTEXT
Run a diff on the PREVIOUS_FILECONTEXT file to the currently installed one, and restore the context of all affected files.
.TP
.B -v
Modify verbosity from progess to verbose. (Run restorecon with -v instead of -p)
.SH "ARGUMENTS"
One of:
.TP

View File

@ -105,6 +105,7 @@ static int restore(FTSENT *ftsent)
char *my_file = strdupa(ftsent->fts_path);
int ret = -1;
security_context_t curcon = NULL, newcon = NULL;
float progress;
if (match(my_file, ftsent->fts_statp, &newcon) < 0)
/* Check for no matching specification. */
@ -113,7 +114,14 @@ static int restore(FTSENT *ftsent)
if (r_opts->progress) {
r_opts->count++;
if (r_opts->count % STAR_COUNT == 0) {
fprintf(stdout, "*");
if (r_opts->progress == 1) {
fprintf(stdout, "*");
} else {
if (r_opts->nfile > 0) {
progress = (r_opts->count < r_opts->nfile) ? (100.0 * r_opts->count / r_opts->nfile) : 100;
fprintf(stdout, "\r%-.1f%%", progress);
}
}
fflush(stdout);
}
}
@ -283,6 +291,8 @@ static int apply_spec(FTSENT *ftsent)
return rc;
}
#include <sys/statvfs.h>
static int process_one(char *name, int recurse_this_path)
{
int rc = 0;
@ -332,6 +342,7 @@ static int process_one(char *name, int recurse_this_path)
continue;
}
}
rc = apply_spec(ftsent);
if (rc == SKIP)
fts_set(fts_handle, ftsent, FTS_SKIP);
@ -611,12 +622,22 @@ static int filespec_add(ino_t ino, const security_context_t con, const char *fil
}
#include <sys/utsname.h>
int file_system_count(char *name) {
struct statvfs statvfs_buf;
int nfile = 0;
memset(&statvfs_buf, 0, sizeof(statvfs_buf));
if (!statvfs(name, &statvfs_buf)) {
nfile = statvfs_buf.f_files - statvfs_buf.f_ffree;
}
return nfile;
}
/*
Search /proc/mounts for all file systems that do not support extended
attributes and add them to the exclude directory table. File systems
that support security labels have the seclabel option.
that support security labels have the seclabel option, return total file count
*/
void exclude_non_seclabel_mounts()
int exclude_non_seclabel_mounts()
{
struct utsname uts;
FILE *fp;
@ -625,16 +646,16 @@ void exclude_non_seclabel_mounts()
int index = 0, found = 0;
char *mount_info[4];
char *buf = NULL, *item;
int nfile = 0;
/* Check to see if the kernel supports seclabel */
if (uname(&uts) == 0 && strverscmp(uts.release, "2.6.30") < 0)
return;
return 0;
if (is_selinux_enabled() <= 0)
return;
return 0;
fp = fopen("/proc/mounts", "r");
if (!fp)
return;
return 0;
while ((num = getline(&buf, &len, fp)) != -1) {
found = 0;
@ -661,6 +682,7 @@ void exclude_non_seclabel_mounts()
while (item != NULL) {
if (strcmp(item, "seclabel") == 0) {
found = 1;
nfile += file_system_count(mount_info[1]);
break;
}
item = strtok(NULL, ",");
@ -673,5 +695,7 @@ void exclude_non_seclabel_mounts()
free(buf);
fclose(fp);
/* return estimated #Files + 5% for directories and hard links */
return nfile * 1.05;
}

View File

@ -14,6 +14,7 @@
#include <selinux/label.h>
#include <stdlib.h>
#include <limits.h>
#include <stdint.h>
#define STAR_COUNT 1000
@ -21,7 +22,8 @@
struct restore_opts {
int add_assoc; /* Track inode associations for conflict detection. */
int progress;
unsigned long long count;
uint64_t count; /* Number of files processed so far */
uint64_t nfile; /* Estimated total number of files */
int debug;
int change;
int hard_links;
@ -49,6 +51,6 @@ int exclude(const char *path);
void remove_exclude(const char *directory);
int process_one_realpath(char *name, int recurse);
int process_glob(char *name, int recurse);
void exclude_non_seclabel_mounts();
int exclude_non_seclabel_mounts();
#endif

View File

@ -55,7 +55,8 @@ don't change any file labels (passive check).
save list of files with incorrect context in outfilename.
.TP
.B \-p
show progress by printing * every STAR_COUNT files.
show progress by printing * every STAR_COUNT files. (If you relabel the entire OS, this will show you the percentage complete.)
.TP
.B \-R, \-r
change files and directories file labels recursively (descend directories).

View File

@ -60,7 +60,7 @@ don't change any file labels (passive check).
save list of files with incorrect context in filename.
.TP
.B \-p
show progress by printing * every STAR_COUNT files.
show progress by printing * every STAR_COUNT files. (If you relabel the entire OS, this will show you the percentage complete.)
.TP
.B \-q
suppress non-error output.

View File

@ -159,6 +159,7 @@ int main(int argc, char **argv)
/* Initialize variables */
r_opts.progress = 0;
r_opts.count = 0;
r_opts.nfile = 0;
r_opts.debug = 0;
r_opts.change = 1;
r_opts.verbose = 0;
@ -222,7 +223,7 @@ int main(int argc, char **argv)
}
/* This must happen before getopt. */
exclude_non_seclabel_mounts();
r_opts.nfile = exclude_non_seclabel_mounts();
/* Process any options. */
while ((opt = getopt(argc, argv, "c:de:f:hilno:pqrsvFRW0")) > 0) {
@ -346,7 +347,7 @@ int main(int argc, char **argv)
"Progress and Verbose mutually exclusive\n");
usage(argv[0]);
}
r_opts.progress = 1;
r_opts.progress++;
break;
case 'W':
warn_no_match = 1;
@ -360,6 +361,14 @@ int main(int argc, char **argv)
}
}
for (i = optind; i < argc; i++) {
if (!strcmp(argv[i], "/")) {
mass_relabel = 1;
if (r_opts.progress)
r_opts.progress++;
}
}
if (!iamrestorecon) {
if (policyfile) {
if (optind != (argc - 1))
@ -426,12 +435,8 @@ int main(int argc, char **argv)
if (strcmp(input_filename, "-") != 0)
fclose(f);
} else {
for (i = optind; i < argc; i++) {
if (!strcmp(argv[i], "/"))
mass_relabel = 1;
for (i = optind; i < argc; i++)
errors |= process_glob(argv[i], recurse) < 0;
}
}
maybe_audit_mass_relabel(mass_relabel, errors);