--- tar-1.23/src/buffer.c.bak 2010-03-09 14:52:41.000000000 +0200 +++ tar-1.23/src/buffer.c 2010-03-14 07:42:11.176656974 +0200 @@ -890,6 +890,8 @@ seek_archive (off_t size) void close_archive (void) { + int ret; + if (time_to_start_writing || access_mode == ACCESS_WRITE) { flush_archive (); @@ -901,6 +903,11 @@ close_archive (void) if (verify_option) verify_volume (); + ret = sys_fsync_archive(); + if (ret != 0) { + archive_write_error (errno); + } + if (rmtclose (archive) != 0) close_error (*archive_name_cursor); --- tar-1.23/src/system.c.bak 2010-03-14 07:40:46.104657738 +0200 +++ tar-1.23/src/system.c 2010-03-14 07:42:11.233657442 +0200 @@ -96,6 +96,12 @@ sys_write_archive_buffer (void) return full_write (archive, record_start->buffer, record_size); } +int +sys_fsync_archive (void) +{ + return 0; +} + /* Set ARCHIVE for writing, then compressing an archive. */ void sys_child_open_for_compress (void) @@ -269,6 +275,20 @@ sys_write_archive_buffer (void) return rmtwrite (archive, record_start->buffer, record_size); } +int +sys_fsync_archive (void) +{ + int ret; + + if (do_fsync && !use_compress_program_option /* can't fsync pipe */ ) { + ret = fsync (archive); + if ((ret == -1) && (errno == EINVAL)) return 0; + return ret; + } else { + return 0; + } +} + #define PREAD 0 /* read file descriptor from pipe() */ #define PWRITE 1 /* write file descriptor from pipe() */ --- tar-1.23/src/tar.c.bak 2010-03-14 07:40:48.344655641 +0200 +++ tar-1.23/src/tar.c 2010-03-14 07:44:39.726657796 +0200 @@ -746,6 +746,8 @@ static struct argp_option options[] = { N_("wildcards do not match `/'"), GRID+1 }, {"wildcards-match-slash", WILDCARDS_MATCH_SLASH_OPTION, 0, 0, N_("wildcards match `/' (default for exclusion)"), GRID+1 }, + {"fsync", 'q', 0, 0, + N_("when creating archive, fsync it prior to closing"), GRID+1}, #undef GRID #define GRID 130 @@ -1593,6 +1595,11 @@ parse_opt (int key, char *arg, struct ar absolute_names_option = true; break; + case 'q': + do_fsync = true; + setenv("TAR_WANTS_FSYNC", "", 1); + break; + case 'r': set_subcommand_option (APPEND_SUBCOMMAND); break; @@ -2642,6 +2649,9 @@ main (int argc, char **argv) /* System V fork+wait does not work if SIGCHLD is ignored. */ signal (SIGCHLD, SIG_DFL); + if (getenv("TAR_WANTS_FSYNC")) + do_fsync = true; + /* Try to disable the ability to unlink a directory. */ priv_set_remove_linkdir (); --- tar-1.23/src/common.h.bak 2010-03-14 07:40:46.373654580 +0200 +++ tar-1.23/src/common.h 2010-03-14 07:42:11.216660001 +0200 @@ -106,6 +106,9 @@ GLOBAL bool absolute_names_option; /* Display file times in UTC */ GLOBAL bool utc_option; +/* fsync() written archives prior to close() */ +GLOBAL bool do_fsync; + /* This variable tells how to interpret newer_mtime_option, below. If zero, files get archived if their mtime is not less than newer_mtime_option. If nonzero, files get archived if *either* their ctime or mtime is not less @@ -786,6 +789,7 @@ int sys_truncate (int fd); pid_t sys_child_open_for_compress (void); pid_t sys_child_open_for_uncompress (void); size_t sys_write_archive_buffer (void); +int sys_fsync_archive (void); bool sys_get_archive_stat (void); int sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st); void sys_wait_command (void);