summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--disk-utils/fsck.813
-rw-r--r--disk-utils/fsck.c64
2 files changed, 63 insertions, 14 deletions
diff --git a/disk-utils/fsck.8 b/disk-utils/fsck.8
index c2bb7bfd5..df7d0959c 100644
--- a/disk-utils/fsck.8
+++ b/disk-utils/fsck.8
@@ -6,7 +6,9 @@
fsck \- check and repair a Linux filesystem
.SH SYNOPSIS
.B fsck
-.RB [ \-lrsAVRTMNP ]
+.RB [ \-lsAVRTMNP ]
+.RB [ \-r
+.RI [ fd ]]
.RB [ \-C
.RI [ fd ]]
.RB [ \-t
@@ -100,13 +102,20 @@ multiple devices or for non-rotating disks. \fBfsck\fR does not lock underlying
devices when executed to check stacked devices (e.g.\& MD or DM) \(en this feature is
not implemented yet.
.TP
-.B \-r
+.BR \-r \ [ \fIfd\fR ]
Report certain statistics for each fsck when it completes. These statistics
include the exit status, the maximum run set size (in kilobytes), the elapsed
all-clock time and the user and system CPU time used by the fsck run. For
example:
/dev/sda1: status 0, rss 92828, real 4.002804, user 2.677592, sys 0.86186
+
+GUI front-ends may specify a file descriptor
+.IR fd ,
+in which case the progress bar information will be sent to that file descriptor
+in a machine parseable format. For example:
+
+/dev/sda1 0 92828 4.002804 2.677592 0.86186
.TP
.B \-s
Serialize
diff --git a/disk-utils/fsck.c b/disk-utils/fsck.c
index 299a77525..6ef8ad198 100644
--- a/disk-utils/fsck.c
+++ b/disk-utils/fsck.c
@@ -141,6 +141,7 @@ static int progress;
static int progress_fd;
static int force_all_parallel;
static int report_stats;
+static FILE *report_stats_file;
static int num_running;
static int max_running;
@@ -586,16 +587,28 @@ static void print_stats(struct fsck_instance *inst)
timersub(&inst->end_time, &inst->start_time, &delta);
- fprintf(stdout, "%s: status %d, rss %ld, "
- "real %ld.%06ld, user %d.%06d, sys %d.%06d\n",
- fs_get_device(inst->fs),
- inst->exit_status,
- inst->rusage.ru_maxrss,
- delta.tv_sec, delta.tv_usec,
- (int)inst->rusage.ru_utime.tv_sec,
- (int)inst->rusage.ru_utime.tv_usec,
- (int)inst->rusage.ru_stime.tv_sec,
- (int)inst->rusage.ru_stime.tv_usec);
+ if (report_stats_file)
+ fprintf(report_stats_file, "%s %d %ld "
+ "%ld.%06ld %d.%06d %d.%06d\n",
+ fs_get_device(inst->fs),
+ inst->exit_status,
+ inst->rusage.ru_maxrss,
+ delta.tv_sec, delta.tv_usec,
+ (int)inst->rusage.ru_utime.tv_sec,
+ (int)inst->rusage.ru_utime.tv_usec,
+ (int)inst->rusage.ru_stime.tv_sec,
+ (int)inst->rusage.ru_stime.tv_usec);
+ else
+ fprintf(stdout, "%s: status %d, rss %ld, "
+ "real %ld.%06ld, user %d.%06d, sys %d.%06d\n",
+ fs_get_device(inst->fs),
+ inst->exit_status,
+ inst->rusage.ru_maxrss,
+ delta.tv_sec, delta.tv_usec,
+ (int)inst->rusage.ru_utime.tv_sec,
+ (int)inst->rusage.ru_utime.tv_usec,
+ (int)inst->rusage.ru_stime.tv_sec,
+ (int)inst->rusage.ru_stime.tv_usec);
}
/*
@@ -1371,11 +1384,12 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
fputs(_(" -N do not execute, just show what would be done\n"), out);
fputs(_(" -P check filesystems in parallel, including root\n"), out);
fputs(_(" -R skip root filesystem; useful only with '-A'\n"), out);
- fputs(_(" -r report statistics for each device checked\n"), out);
+ fputs(_(" -r [<fd>] report statistics for each device checked;\n"
+ " file descriptor is for GUIs\n"), out);
fputs(_(" -s serialize the checking operations\n"), out);
fputs(_(" -T do not show the title on startup\n"), out);
fputs(_(" -t <type> specify filesystem types to be checked;\n"
- " <type> is allowed to be a comma-separated list\n"), out);
+ " <type> is allowed to be a comma-separated list\n"), out);
fputs(_(" -V explain what is being done\n"), out);
fputs(_(" -? display this help and exit\n"), out);
@@ -1399,6 +1413,7 @@ static void parse_argv(int argc, char *argv[])
int opt = 0;
int opts_for_fsck = 0;
struct sigaction sa;
+ int report_stats_fd = 0;
/*
* Set up signal action
@@ -1504,6 +1519,21 @@ static void parse_argv(int argc, char *argv[])
break;
case 'r':
report_stats = 1;
+ if (arg[j+1]) { /* -r<fd> */
+ report_stats_fd = string_to_int(arg+j+1);
+ if (report_stats_fd < 0)
+ report_stats_fd = 0;
+ else
+ goto next_arg;
+ } else if (i+1 < argc && *argv[i+1] != '-') { /* -r <fd> */
+ report_stats_fd = string_to_int(argv[i+1]);
+ if (report_stats_fd < 0)
+ report_stats_fd = 0;
+ else {
+ ++i;
+ goto next_arg;
+ }
+ }
break;
case 's':
serialize = 1;
@@ -1542,6 +1572,16 @@ static void parse_argv(int argc, char *argv[])
opt = 0;
}
}
+
+ /* Validate the report stats file descriptor to avoid disasters */
+ if (report_stats_fd) {
+ report_stats_file = fdopen(report_stats_fd, "w");
+ if (!report_stats_file)
+ err(FSCK_EX_ERROR,
+ _("invalid argument -r %d"),
+ report_stats_fd);
+ }
+
if (getenv("FSCK_FORCE_ALL_PARALLEL"))
force_all_parallel++;
if ((tmp = getenv("FSCK_MAX_INST")))