X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gzip.c;h=d9cdfaa5ac51df572db2d3c06e261355fde66e39;hb=e6516c537071ac28b3e8e12439fbaf54bfe4fbd0;hp=6cfc561c3f1fb04562fb132867dc394d7579464b;hpb=8e951439dd320eb8cb5d543d6904ce55d9b6b32d;p=debian%2Fgzip diff --git a/gzip.c b/gzip.c index 6cfc561..d9cdfaa 100644 --- a/gzip.c +++ b/gzip.c @@ -159,6 +159,14 @@ DECLARE(uch, window, 2L*WSIZE); is deliberately not documented, and only for testing. */ static bool presume_input_tty; +/* If true, transfer output data to the output file's storage device + when supported. Otherwise, if the system crashes around the time + gzip is run, the user might lose both input and output data. See: + Pillai TS et al. All file systems are not created equal: on the + complexity of crafting crash-consistent applications. OSDI'14. 2014:433-48. + https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai */ +static bool synchronous; + static int ascii = 0; /* convert end-of-lines to local OS conventions */ int to_stdout = 0; /* output to stdout (-c) */ static int decompress = 0; /* decompress (-d) */ @@ -240,6 +248,7 @@ static int handled_sig[] = enum { PRESUME_INPUT_TTY_OPTION = CHAR_MAX + 1, + SYNCHRONOUS_OPTION, /* A value greater than all valid long options, used as a flag to distinguish options derived from the GZIP environment variable. */ @@ -268,6 +277,7 @@ static const struct option longopts[] = {"-presume-input-tty", no_argument, NULL, PRESUME_INPUT_TTY_OPTION}, {"quiet", 0, 0, 'q'}, /* quiet mode */ {"silent", 0, 0, 'q'}, /* quiet mode */ + {"synchronous",0, 0, SYNCHRONOUS_OPTION}, {"recursive", 0, 0, 'r'}, /* recurse through directories */ {"suffix", 1, 0, 'S'}, /* use given suffix instead of .gz */ {"test", 0, 0, 't'}, /* test compressed file integrity */ @@ -353,6 +363,7 @@ local void help() " -r, --recursive operate recursively on directories", #endif " -S, --suffix=SUF use suffix SUF on compressed files", + " --synchronous synchronous output (safer if system crashes, but slower)", " -t, --test test compressed file integrity", " -v, --verbose verbose mode", " -V, --version display version number", @@ -551,6 +562,9 @@ int main (int argc, char **argv) z_len = strlen(optarg); z_suffix = optarg; break; + case SYNCHRONOUS_OPTION: + synchronous = true; + break; case 't': test = decompress = to_stdout = 1; break; @@ -645,6 +659,12 @@ int main (int argc, char **argv) if (list && !quiet && file_count > 1) { do_list(-1, -1); /* print totals */ } + if (to_stdout + && ((synchronous + && (fdatasync (STDOUT_FILENO) != 0 && errno != EINVAL)) + || close (STDOUT_FILENO) != 0) + && errno != EBADF) + write_error (); do_exit(exit_code); return exit_code; /* just to avoid lint warning */ } @@ -972,13 +992,7 @@ local void treat_file(iname) { copy_stat (&istat); - /* If KEEP, transfer output data to the output file's storage device. - Otherwise, if the system crashed now the user might lose - both input and output data. See: Pillai TS et al. All - file systems are not created equal: on the complexity of - crafting crash-consistent applications. OSDI'14. 2014:433-48. - https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai */ - if ((!keep + if ((synchronous && ((0 <= dfd && fdatasync (dfd) != 0 && errno != EINVAL) || (fsync (ofd) != 0 && errno != EINVAL))) || close (ofd) != 0)