Browse Source

Merge recent gnulib changes, and remove some lint.

Paul Eggert 21 years ago
parent
commit
2bda83b48d
26 changed files with 880 additions and 703 deletions
  1. 186 32
      ChangeLog
  2. 9 7
      bootstrap
  3. 3 1
      configure.ac
  4. 6 2
      lib/.cvsignore
  5. 8 2
      lib/Makefile.am
  6. 6 3
      m4/.cvsignore
  7. 21 21
      src/buffer.c
  8. 36 20
      src/common.h
  9. 14 13
      src/compare.c
  10. 152 151
      src/create.c
  11. 23 23
      src/extract.c
  12. 22 20
      src/incremen.c
  13. 19 14
      src/list.c
  14. 12 16
      src/misc.c
  15. 16 16
      src/names.c
  16. 20 18
      src/rmt.c
  17. 4 4
      src/rmt.h
  18. 39 24
      src/rtapelib.c
  19. 71 70
      src/sparse.c
  20. 42 78
      src/system.c
  21. 34 28
      src/tar.c
  22. 6 6
      src/update.c
  23. 23 33
      src/utf8.c
  24. 84 80
      src/xheader.c
  25. 3 2
      tests/genfile.c
  26. 21 19
      tests/mksparse.c

+ 186 - 32
ChangeLog

@@ -1,3 +1,157 @@
+2004-04-04  Paul Eggert  <[email protected]>
+
+	Merge recent gnulib changes, and remove some lint.
+
+	Improve support for nanosecond-resolution time stamps.
+	* bootstrap: Add gettime, timespec modules.
+	* configure.ac (gl_GETTIME, gl_TIMESPEC): Add.
+	* lib/.cvsignore (getopt_int.h, gettime.c, gettimeofday.c,
+	timespec.h): Add.
+	* lib/Makefile.am (libtar_a_SOURCES): Add gettime.c, timespec.h.
+	* m4/.cvsignore: Add clock_time.m4, gettime.m4, gettimeofday.m4,
+	st_mtim.m4, timespec.m4.  Remove malloc.m4, realloc.m4.
+	* src/common.h (newer_mtime_option): Now a struct timespec, not
+	time_t.  All uses changed.
+	(NEWER_OPTION_INITIALIZED, OLDER_STAT_MTIME): New macros.
+	* src/create.c (dump_file0): Use OLDER_STAT_TIME to compare times.
+	* src/incremen.c (scan_path): Likewise.
+	* src/list.c (read_and): Likewise.
+	* src/list.c (read_and): Use NEWER_OPTION_INITIALIZED to decide
+	whether newer_mtime_option is initialized.
+	* src/tar.c (decode_options): Likewise.
+	* src/tar.c (decode_options): Adjust to new signature for get_date.
+
+	* src/buffer.c (short_read, flush_read): Use size_t, not ssize_t, for
+	result of safe_read, full_write, and similar functions.
+	Detect safe_read error by comparing to SAFE_READ_ERROR;
+	detect full_write error by comparing to 0.
+	All uses changed.
+	* src/common.h (write_error_details, sys_write_archive_buffer):
+	Likewise.
+	* src/misc.c (write_error_details): Likewise.
+	* src/rmt.c (main): Likewise.
+	* src/rmt.h (rmt_read__, rmt_write__): Likewise.
+	* src/rtapelib.c (rmt_read__, rmt_write__, rmt_ioctl__): Likewise.
+	* src/sparse.c (sparse_scan_file, sparse_dump_region,
+	check_sparse_region, check_data_region): Likewise.
+	* src/system.c (sys_write_archive_buffer, sys_drain_input_pipe,
+	sys_child_open_for_compress, sys_child_open_for_uncompress): Likewise.
+	* src/update.c (append_file): Likewise.
+
+	* src/buffer.c (clear_read_error_count): Use explicit (void)
+	to indicate a function with no arguments.
+	* src/create.c (check_links): Likewise.
+	* src/system.c (sys_get_archive_stat, sys_save_archive_dev_ino,
+	sys_detect_dev_null_output, sys_drain_input_pipe, sys_spawn_shell,
+	sys_reset_uid_gid, sys_get_archive_stat, sys_save_archive_dev_ino,
+	sys_detect_dev_null_output, sys_drain_input_pipe, sys_spawn_shell):
+	Likewise.
+	* src/utf8.c (get_input_charset): Likewise.
+	* src/xheader.c (xheader_ghdr_name, xheader_write_global,
+	xheader_decode_global, extended_header_init): Likewise.
+	* tests/mksparse.c (usage): Likewise.
+
+	* src/buffer.c (new_volume): Rename local variables to avoid
+	shadowing warnings.
+	* src/common.h (file_dumpable_p, sys_stat_nanoseconds,
+	sparse_file_p, sparse_member_p, sparse_fixup_header,
+	sparse_dump_file, sparce_extract_file, sparse_skip_file,
+	sparse_diff_file): Likewise.
+	* src/compare.c (diff_archive): Likewise.
+	* src/create.c (file_dumpable_p, dump_regular_file, dump_dir0,
+	dump_dir, dump_hard_link, file_count_links, dump_file0, dump_file):
+	Likewise.
+	* src/extract.c (repair_delayed_set_stat): Likewise.
+	* src/misc.c (maybe_backup_file, add_hierarchy_to_namelist):
+	Likewise.
+	* src/sparse.c (struct tar_sparse_optab, tar_sparse_dump_region,
+	tar_sparse_extract_region, sparse_dump_region, sparse_extract_region,
+	sparse_dump_file, sparse_file_p, sparse_member_p,
+	sparse_fixup_header, sparse_extract_file, sparse_skip_file,
+	check_data_region, sparse_diff_file): Likewise.
+	* src/system.c (sys_stat_nanoseconds): Likewise.
+	* src/xheader.c (xheader_format_name): Likewise.
+
+	* src/common.h (enum old_files): Remove comma before }; not portable.
+
+	* src/common.h (read_fatal_details): Add __attribute__ ((noreturn)).
+	* src/rmt.c (usage): Likewise.
+	* src/xheader.c (xheader_set_single_keyword): Likewise.
+	* tests/genfile.c (usage): Likewise.
+	* tests/mksparse.c (die, usage): Likewise.  Also add printf attribute
+	to die.
+
+	* src/common.h (gname_to_gid, uname_to_uid): Add const to avoid
+	some gcc warnings.
+	* src/names.c (uname_to_uid, gname_to_gid): Likewise.
+	* src/utf8.c (struct langtab.lang, struct langtab.terr, struct
+	langtab.charset, charset_lookup): Likewise.
+
+	* src/common.h (name_init): Remove unused args.  All callers changed.
+	* src/names.c (name_init): Likewise.
+
+	* src/common.h (usage, xheader_write, xheader_write_global,
+	sys_reset_uid_gid): New decls.
+
+	* src/compare.c (report_difference, process_noop): Add
+	__attribute__ ((unused)) for unused attributes.
+	* src/sparse.c (oldgnu_sparse_member_p, star_sparse_member_p):
+	Likewise.
+	* src/xheader.c (dummy_coder, dummy_decoder, atime_coder,
+	gid_coder, gname_coder, linkpath_coder, ctime_coder, mtime_coder,
+	path_coder, size_coder, uid_coder, uname_coder,
+	sparse_numblocks_coder): Likewise.
+
+	* src/create.c (dump_regular_finish, dump_dir0, dump_dir,
+	dump_file0): Now static.
+	* src/utf8.c (charset_lookup): Likewise.
+	* src/xheader.c (xheader_protected_pattern_p,
+	xheader_protected_keyword_p, xheader_set_single_keyword,
+	xheader_keyword_deleted_p, xheader_keyword_override_p,
+	xheader_list_append, xheader_list_destroy, xheader_set_keyword_equal):
+	Likewise.
+	* tests/genfile.c (usage): Likewise.
+	* tests/mksparse.c (die, mkhole, mksparse, usage, xlat_suffix):
+	Likewise.
+
+	* src/create.c (hash_link): Rewrite to avoid cast.
+
+	* src/extract.c (file_newer_p): Use parameter, not global var.
+	* src/misc.c (write_error_details): Likewise.
+
+	* src/extract.c (prepare_to_extract): Remove directory arg; not
+	used.  All callers changed.
+
+	* src/misc.c (close_fatal): Remove; not used.
+	* src/system.c (sys_utimes): Likewise.
+
+	* src/rmt.c (get_string): Avoid buffer overrun (off by 1 error).
+
+	* src/rmt.c (main): Update copyright date to 2004.
+	* src/tar.c (decode_options): Likewise.
+
+	* src/rtapelib.c (get_status_string): Don't lose errno when
+	skipping the error messages.
+	(get_status): Report an error if atol returns a negative number.
+
+	* src/utf8.c (struct langtab, langtab, charset_lookup,
+	get_input_charset) [!defined HAVE_LIBCONV]: Omit unused
+	definitions.
+	(iconv_open, iconv, iconv_close) [!defined HAVE_LIBCONV]:
+	Use macros, not definitions, to avoid type clashes with system
+	headers.
+	(charset_lookup): Local var is now auto, not static.
+	(utf8_convert): Use ICONV_CONST instead of const, to avoid
+	type clashes.
+
+	* src/utf8.c (langtab): Initialize all elements of struct, to
+	avoid gcc warning.
+	* src/xheader.c (xhdr_tab): Likewise.
+
+	* src/xheader.c: Include fnmatch.h, since we use fnmatch.
+
+	* tests/mksparse.c (mkhole): Fix typo: bool was assigned to off_t.
+
 2004-04-04  Sergey Poznyakoff  <[email protected]>
 
 	* NEWS: Updated
@@ -11,7 +165,7 @@
 	* tests/multiv02.sh: New file
 	* tests/Makefile.am: Add sparse01.sh and multiv02.sh
 	* tests/longv7.sh: Added missing call to 'after'
-	
+
 	* src/common.h: Added missing prototypes
 	* src/compare.c (diff_archive): Use is_sparse member
 	instead of GNUTYPE_SPARSE.
@@ -49,7 +203,7 @@
 	(sparse_numbytes_decoder): Removed unused variable
 	* src/.cvsignore: Added .gdbinit
 	* THANKS: Added Mads Martin Joergensen
-	
+
 2004-03-26  Sergey Poznyakoff  <[email protected]>
 
 	* src/create.c (write_long_name): Do not allow more than
@@ -100,13 +254,13 @@
 
 	which is grossly wrong, since even if new_volume() below succeeds,
 	the subsequent call to rmtread will overwrite the chunk of data
-        already read in the buffer and thus spoil everything.
+	already read in the buffer and thus spoil everything.
 	* src/system.c (sys_child_open_for_uncompress): Minor stylistic
 	fix.
 	* tests/star/multi-fail.sh: New test.
 	* tests/Makefile.am: Added multi-fail.sh
 	* tests/star/README: Updated
-	
+
 2004-02-29  Sergey Poznyakoff  <[email protected]>
 
 	* NEWS: Updated
@@ -116,7 +270,7 @@
 	* src/extract.c: Handle --keep-newer-files option
 	* src/list.c (tartime): Print UTC if --utc was given.
 	* src/tar.c: New options: --utc and keep-newer-files
-	
+
 	* tests/Makefile.am: Added new tests
 	* tests/after: Rewritten
 	* tests/before: Rewritten
@@ -130,7 +284,7 @@
 	* tests/options.sh: Likewise
 	* tests/version.sh: Likewise
 	* tests/volume.sh: Likewise
-	
+
 	* tests/star: New directory
 	* tests/star/README: New file
 	* tests/star/gtarfail.sh: New file
@@ -171,7 +325,7 @@
 
 	Added UTF-8 support. Finished global extended header
 	support.
-	
+
 	* NEWS: Minor fix
 	* configure.ac: Detect libiconv
 	* src/utf8.c: New file. Conversions to and from utf-8.
@@ -188,7 +342,7 @@
 	missing gettext markers
 	(decode_record): Rewritten using caller-provided handler and
 	data closure.
-	* tests/listed01.sh: Give credit to Andreas Schuldei.	
+	* tests/listed01.sh: Give credit to Andreas Schuldei.
 
 2004-02-21  Sergey Poznyakoff  <[email protected]>
 
@@ -198,8 +352,8 @@
 	<[email protected]>.
 
 	This is due to the condition
-     
-          (0 < top_level || !incremental_option) 
+
+	  (0 < top_level || !incremental_option)
 
 	Removing it makes incremental backups work for individual
 	files as well as for directories. On the other hand, it does
@@ -217,7 +371,7 @@
 
 	      (!incremental_option)
 
-        Now, let's consider the effect of its removal. There are two cases:
+	Now, let's consider the effect of its removal. There are two cases:
 
 	1) when incremental_option==1
 	This means incremental backup in progress. In this case dump_file
@@ -234,8 +388,8 @@
 	irrelevant, and its removal won't alter the behavior of tar,
 	*except* that it will enable incremental backups on individual
 	files, which is the wanted effect.
-     
-        2) when incremental_option==0
+
+	2) when incremental_option==0
 	In this case the condition yields true and its removal does not
 	affect the functionality.
 
@@ -245,7 +399,7 @@
 	* tests/listed01.sh: New test. Check listed incremental
 	backups on individual files.
 	* tests/Makefile.am: Added listed01.sh
-	
+
 2004-02-20  Sergey Poznyakoff  <[email protected]>
 
 	* src/common.h (simple_finish_header,start_private_header): New
@@ -269,7 +423,7 @@
 
 	* src/update.c (update_archive): Write global extended header if
 	constructed.
-	* src/xheader.c (xheader_format_name): Bugfix. 
+	* src/xheader.c (xheader_format_name): Bugfix.
 	(xheader_xhdr_name): Changed the default extended header name
 	to '%d/PaxHeaders.%p/%f', as POSIX requires.
 	(xheader_ghdr_name): Removed unused argument.
@@ -281,25 +435,25 @@
 	unconditionally.
 	* src/list.c (decode_header): Likewise.
 	* src/incremen.c (sort_obstack): Fixed typo in the comment
-	
+
 	* doc/tar.texi: Document new default for extended
 	header names.
-	
+
 	* tests/before: Accept an optional list of allowed archive
 	formats. Exit with the status 77 if the current archive
 	format does not match any of them.
 	* tests/delete03.sh: Require gnu, oldgnu or posix format
 	* tests/incremen.sh: Require gnu or oldgnu format
 	* tests/multiv01.sh: Likewise
-	
+
 2004-02-20  Sergey Poznyakoff  <[email protected]>
-	
+
 	* doc/tar.texi (Option Summary): Documented --pax-option
 	* src/tar.c: Likewise.
 	* NEWS: Likewise.
 	* src/create.c (to_chars): Added a comment.
 	* src/tar.h: Comment to GNU_FORMAT
-	
+
 2004-02-18  Sergey Poznyakoff  <[email protected]>
 
 	* README: Updated
@@ -313,17 +467,17 @@
 	* src/tar.c: New option --pax-option (equivalent to -o option
 	of pax).
 	* src/xheader.c: Implement pax -o option. Fixed misleading
-	heading comment (introduced 2003-09-02). 
+	heading comment (introduced 2003-09-02).
 	* src/incremen.c: Minor fixes
 	* m4/.cvsignore: Updated
-	
+
 2004-02-17  Sergey Poznyakoff  <[email protected]>
 
 	* src/incremen.c: Removed accumulator stuff in favor of obstack.
 	(get_directory_contents): Split into two functions
 	* src/update.c: Minor changes
 	* doc/tar.texi: Fixed typo
-	
+
 2004-02-15  Paul Eggert  <[email protected]>
 
 	Fix Debian bug 230872, originally reported by Jeff King in
@@ -863,15 +1017,15 @@
 
 2003-09-03  Sergey Poznyakoff  <[email protected]>
 
-        * src/create.c (start_header): Store long file names
-        in "path" keyword of an extended header if in POSIX
-        mode.
-        (finish_header): print header before calling write_extended().
-        * src/list.c (list_archive): Always decode the header. This
-        is necessary so the extended header is processed and the correct
-        filename is printed no matter what the state of verbose_option.
-        * src/xheader.c (xhdr_tab): Reserved GNU keywords (commented out
-        for the time being).
+	* src/create.c (start_header): Store long file names
+	in "path" keyword of an extended header if in POSIX
+	mode.
+	(finish_header): print header before calling write_extended().
+	* src/list.c (list_archive): Always decode the header. This
+	is necessary so the extended header is processed and the correct
+	filename is printed no matter what the state of verbose_option.
+	* src/xheader.c (xhdr_tab): Reserved GNU keywords (commented out
+	for the time being).
 
 2003-09-01  Paul Eggert  <[email protected]>
 

+ 9 - 7
bootstrap

@@ -2,7 +2,7 @@
 
 # Bootstrap 'tar' from CVS.
 
-# Copyright (C) 2003 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -42,10 +42,10 @@ usage() {
  --no-po                      Do not download po files.
 
 Running without arguments will suffice in most cases. It is equivalent
-to 
+to
 
     ./bootstrap --cvs-auth=ext --cvs-user=anoncvs
-    
+
 EOF
 }
 
@@ -84,7 +84,7 @@ build_cvs_prefix() {
        CVS_RSH=ssh
        export CVS_RSH
     fi
-  fi 
+  fi
 }
 
 # Get gnulib files.
@@ -96,15 +96,15 @@ case ${GNULIB_SRCDIR--} in
 
     trap exit 1 2 13 15
     trap 'rm -fr gnulib; exit 1' 0
-    
+
     case "${CVS_AUTH--}" in
     -)       build_cvs_prefix ext anoncvs;;
     pserver) build_cvs_prefix $CVS_AUTH ${CVS_USER:-anoncvs};;
     gserver|server)
-             build_cvs_prefix $CVS_AUTH ${CVS_USER--};;
+	     build_cvs_prefix $CVS_AUTH ${CVS_USER--};;
     ext)     build_cvs_prefix $CVS_AUTH ${CVS_USER--};;
     *)       echo "$0: Unknown CVS access method" >&2
-             exit 1;;
+	     exit 1;;
     esac
     if [ "${CVS_AUTH--}" = "pserver" ]; then
       cvs -d ${CVS_PREFIX}subversions.gnu.org:/cvsroot/gnulib login || exit
@@ -133,6 +133,7 @@ getdate
 getline
 getopt
 gettext
+gettime
 hash
 human
 lchown
@@ -149,6 +150,7 @@ stdbool
 stpcpy
 strtol
 strtoul
+timespec
 unlocked-io
 utime
 xalloc

+ 3 - 1
configure.ac

@@ -119,6 +119,7 @@ gl_FUNC_STRTOIMAX
 gl_FUNC_STRTOUMAX
 gl_GETDATE
 gl_GETOPT
+gl_GETTIME
 gl_HASH
 gl_HUMAN
 gl_MODECHANGE
@@ -132,6 +133,7 @@ gl_SAVE_CWD
 gl_SAVEDIR
 gl_STRCASE
 gl_TIME_R
+gl_TIMESPEC
 gl_XALLOC
 gl_XGETCWD
 gl_XSTRTOL
@@ -150,7 +152,7 @@ AC_CHECK_MEMBERS([struct stat.st_spare1, struct stat.st_atim.tv_nsec, struct sta
                  [
 #include <sys/types.h>
 #include <sys/stat.h>])
- 
+
 # Save and restore LIBS so e.g., -lrt, isn't added to it.  Otherwise, *all*
 # programs in the package would end up linked with that potentially-shared
 # library, inducing unnecessary run-time overhead.

+ 6 - 2
lib/.cvsignore

@@ -37,7 +37,10 @@ getndelim2.h
 getopt.c
 getopt.h
 getopt1.c
+getopt_int.h
 gettext.h
+gettime.c
+gettimeofday.c
 hash.c
 hash.h
 human.c
@@ -68,6 +71,8 @@ savedir.c
 savedir.h
 stdbool.h
 stdbool_.h
+stpcpy.c
+stpcpy.h
 strcase.h
 strcasecmp.c
 stripslash.c
@@ -78,10 +83,9 @@ strtoll.c
 strtoul.c
 strtoull.c
 strtoumax.c
-stpcpy.c
-stpcpy.h
 time_r.c
 time_r.h
+timespec.h
 unlocked-io.h
 utime.c
 xalloc.h

+ 8 - 2
lib/Makefile.am

@@ -1,7 +1,7 @@
 # Makefile for GNU tar library.
 
-# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free
-# Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004
+# Free Software Foundation, Inc.
 
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -103,6 +103,9 @@ libtar_a_SOURCES += getopt.h getopt.c getopt1.c
 # gettext
 libtar_a_SOURCES += gettext.h
 
+# gettime
+libtar_a_SOURCES += gettime.c
+
 # hash
 libtar_a_SOURCES += hash.h hash.c
 
@@ -121,6 +124,9 @@ libtar_a_SOURCES += pathmax.h
 # time_r
 EXTRA_DIST += time_r.h
 
+# timespec
+libtar_a_SOURCES += timespec.h
+
 # quote
 libtar_a_SOURCES += quote.h quote.c
 

+ 6 - 3
m4/.cvsignore

@@ -4,6 +4,7 @@ alloca.m4
 backupfile.m4
 bison.m4
 chown.m4
+clock_time.m4
 codeset.m4
 d-ino.m4
 dirname.m4
@@ -21,6 +22,8 @@ getline.m4
 getndelim2.m4
 getopt.m4
 gettext.m4
+gettime.m4
+gettimeofday.m4
 glibc21.m4
 hash.m4
 human.m4
@@ -39,7 +42,6 @@ lib-link.m4
 lib-prefix.m4
 longdouble.m4
 longlong.m4
-malloc.m4
 mbrtowc.m4
 mbstate_t.m4
 memset.m4
@@ -54,7 +56,6 @@ printf-posix.m4
 progtest.m4
 quote.m4
 quotearg.m4
-realloc.m4
 restrict.m4
 rmdir.m4
 safe-read.m4
@@ -64,8 +65,10 @@ savedir.m4
 signed.m4
 size_max.m4
 ssize_t.m4
+st_mtim.m4
 stdbool.m4
 stdint_h.m4
+stpcpy.m4
 strcase.m4
 strerror_r.m4
 strtoimax.m4
@@ -74,8 +77,8 @@ strtoll.m4
 strtoul.m4
 strtoull.m4
 strtoumax.m4
-stpcpy.m4
 time_r.m4
+timespec.m4
 tm_gmtoff.m4
 uintmax_t.m4
 ulonglong.m4

+ 21 - 21
src/buffer.c

@@ -75,7 +75,7 @@ static int checkpoint;
    Declared in update.c
 
    As least EXTERN like this one as possible. (?? --gray)
-   FIXME: Either eliminate it or move it to common.h. 
+   FIXME: Either eliminate it or move it to common.h.
 */
 extern bool time_to_start_writing;
 
@@ -109,7 +109,7 @@ static off_t real_s_sizeleft;
 /* Functions.  */
 
 void
-clear_read_error_count ()
+clear_read_error_count (void)
 {
   read_error_count = 0;
 }
@@ -600,7 +600,7 @@ archive_read_error (void)
 }
 
 static void
-short_read (ssize_t status)
+short_read (size_t status)
 {
   size_t left;			/* bytes left */
   char *more;			/* pointer to next byte to read */
@@ -612,23 +612,23 @@ short_read (ssize_t status)
 	 || (left && status && read_full_records_option))
     {
       if (status)
-	while ((status = rmtread (archive, more, left)) < 0)
+	while ((status = rmtread (archive, more, left)) == SAFE_READ_ERROR)
 	  archive_read_error ();
 
       if (status == 0)
 	{
 	  char buf[UINTMAX_STRSIZE_BOUND];
-	  
+
 	  WARN((0, 0, _("Read %s bytes from %s"),
 		STRINGIFY_BIGINT (record_size - left, buf),
 		*archive_name_cursor));
 	  break;
 	}
-  
+
       if (! read_full_records_option)
 	{
 	  unsigned long rest = record_size - left;
-	  
+
 	  FATAL_ERROR ((0, 0,
 			ngettext ("Unaligned block (%lu byte) in archive",
 				  "Unaligned block (%lu bytes) in archive",
@@ -646,7 +646,7 @@ short_read (ssize_t status)
      about the problem.  */
 
   if (!read_full_records_option && verbose_option > 1
-      && record_start_block == 0 && status > 0)
+      && record_start_block == 0 && status != 0)
     {
       unsigned long rsize = (record_size - left) / BLOCKSIZE;
       WARN ((0, 0,
@@ -664,7 +664,7 @@ short_read (ssize_t status)
 void
 flush_read (void)
 {
-  ssize_t status;		/* result from system call */
+  size_t status;		/* result from system call */
 
   if (checkpoint_option && !(++checkpoint % 10))
     WARN ((0, 0, _("Read checkpoint %d"), checkpoint));
@@ -711,9 +711,9 @@ flush_read (void)
      This is incorrect since even if new_volume() succeeds, the
      subsequent call to rmtread will overwrite the chunk of data
      already read in the buffer, so the processing will fail */
-        
+
   if ((status == 0
-       || (status < 0 && errno == ENOSPC))
+       || (status == SAFE_READ_ERROR && errno == ENOSPC))
       && multi_volume_option)
     {
       union block *cursor;
@@ -734,12 +734,12 @@ flush_read (void)
 	  break;
 	}
 
-      while ((status =
-	      rmtread (archive, record_start->buffer, record_size)) < 0)
+      while ((status = rmtread (archive, record_start->buffer, record_size))
+	     == SAFE_READ_ERROR)
 	archive_read_error ();
-      
+
       if (status != record_size)
-	short_read (status); 
+	short_read (status);
 
       cursor = record_start;
 
@@ -807,7 +807,7 @@ flush_read (void)
       records_read++;
       return;
     }
-  else if (status < 0)
+  else if (status == SAFE_READ_ERROR)
     {
       archive_read_error ();
       goto error_loop;		/* try again */
@@ -897,7 +897,7 @@ close_archive (void)
     flush_archive ();
 
   sys_drain_input_pipe ();
-  
+
   if (verify_option)
     verify_volume ();
 
@@ -905,7 +905,7 @@ close_archive (void)
     close_warn (*archive_name_cursor);
 
   sys_wait_for_child (child_pid);
-  
+
   tar_stat_destroy (&current_stat_info);
   if (save_name)
     free (save_name);
@@ -957,7 +957,7 @@ closeout_volume_number (void)
    Return nonzero on success.
 */
 static bool
-new_volume (enum access_mode access)
+new_volume (enum access_mode mode)
 {
   static FILE *read_file;
   static int looped;
@@ -1086,7 +1086,7 @@ new_volume (enum access_mode access)
     archive = rmtopen (*archive_name_cursor, O_RDWR | O_CREAT, MODE_RW,
 		       rsh_command_option);
   else
-    switch (access)
+    switch (mode)
       {
       case ACCESS_READ:
 	archive = rmtopen (*archive_name_cursor, O_RDONLY, MODE_RW,
@@ -1109,7 +1109,7 @@ new_volume (enum access_mode access)
   if (archive < 0)
     {
       open_warn (*archive_name_cursor);
-      if (!verify_option && access == ACCESS_WRITE && backup_option)
+      if (!verify_option && mode == ACCESS_WRITE && backup_option)
 	undo_last_backup ();
       goto tryagain;
     }

+ 36 - 20
src/common.h

@@ -1,7 +1,7 @@
 /* Common declarations for the tar program.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003 Free Software Foundation, Inc.
+   2003, 2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
@@ -85,6 +85,7 @@ GLOBAL int exit_status;
 #include <modechange.h>
 #include <quote.h>
 #include <safe-read.h>
+#include <timespec.h>
 
 /* Log base 2 of common values.  */
 #define LG_8 3
@@ -189,7 +190,7 @@ enum old_files
   OVERWRITE_OLD_FILES,        /* --overwrite */
   UNLINK_FIRST_OLD_FILES,     /* --unlink-first */
   KEEP_OLD_FILES,             /* --keep-old-files */
-  KEEP_NEWER_FILES,           /* --keep-newer-files */
+  KEEP_NEWER_FILES	      /* --keep-newer-files */
 };
 GLOBAL enum old_files old_files_option;
 
@@ -201,13 +202,23 @@ GLOBAL struct mode_change *mode_option;
 
 GLOBAL bool multi_volume_option;
 
-/* The same variable hold the time, whether mtime or ctime.  Just fake a
+/* The same variable holds the time, whether mtime or ctime.  Just fake a
    non-existing option, for making the code clearer, elsewhere.  */
 #define newer_ctime_option newer_mtime_option
 
 /* Specified threshold date and time.  Files having an older time stamp
    do not get archived (also see after_date_option above).  */
-GLOBAL time_t newer_mtime_option;
+GLOBAL struct timespec newer_mtime_option;
+
+/* Return true if newer_mtime_option is initialized.  */
+#define NEWER_OPTION_INITIALIZED(opt) (0 <= (opt).tv_nsec)
+
+/* Return true if the struct stat ST's M time is less than
+   newer_mtime_option.  */
+#define OLDER_STAT_TIME(st, m) \
+  ((st).st_##m##time < newer_mtime_option.tv_sec \
+   || ((st).st_##m##time == newer_mtime_option.tv_sec \
+       && TIMESPEC_NS ((st).st_##m##tim) < newer_mtime_option.tv_nsec))
 
 /* Zero if there is no recursion, otherwise FNM_LEADING_DIR.  */
 GLOBAL int recursion_option;
@@ -367,7 +378,7 @@ enum dump_status
     dump_status_not_implemented
   };
 
-bool file_dumpable_p (struct tar_stat_info *stat);
+bool file_dumpable_p (struct tar_stat_info *);
 void create_archive (void);
 void pad_archive (off_t size_left);
 void dump_file (char *, int, dev_t);
@@ -535,7 +546,7 @@ void open_diag (char const *name);
 void read_error (char const *);
 void read_error_details (char const *, off_t, size_t);
 void read_fatal (char const *) __attribute__ ((noreturn));
-void read_fatal_details (char const *, off_t, size_t);
+void read_fatal_details (char const *, off_t, size_t) __attribute__ ((noreturn));
 void read_warn_details (char const *, off_t, size_t);
 void read_diag_details (char const *name, off_t offset, size_t size);
 void readlink_error (char const *);
@@ -559,7 +570,7 @@ void unlink_error (char const *);
 void utime_error (char const *);
 void waitpid_error (char const *);
 void write_error (char const *);
-void write_error_details (char const *, ssize_t, size_t);
+void write_error_details (char const *, size_t, size_t);
 void write_fatal (char const *) __attribute__ ((noreturn));
 void write_fatal_details (char const *, ssize_t, size_t)
      __attribute__ ((noreturn));
@@ -572,13 +583,13 @@ void xpipe (int[2]);
 extern struct name *gnu_list_name;
 
 void gid_to_gname (gid_t, char **gname);
-int gname_to_gid (char *gname, gid_t *);
+int gname_to_gid (char const *, gid_t *);
 void uid_to_uname (uid_t, char **uname);
-int uname_to_uid (char *uname, uid_t *);
+int uname_to_uid (char const *, uid_t *);
 
 void init_names (void);
 void name_add (const char *);
-void name_init (int, char *const *);
+void name_init (void);
 void name_term (void);
 char *name_next (int);
 void name_close (void);
@@ -609,6 +620,8 @@ bool contains_dot_dot (char const *);
 
 /* Module tar.c.  */
 
+void usage (int);
+
 int confirm (const char *, const char *);
 void request_stdin (const char *);
 
@@ -634,11 +647,13 @@ void xheader_finish (struct xheader *);
 void xheader_destroy (struct xheader *);
 char *xheader_xhdr_name (struct tar_stat_info *st);
 char *xheader_ghdr_name (void);
+void xheader_write (char, char *, struct xheader *);
+void xheader_write_global (void);
 void xheader_set_option (char *string);
 
 /* Module system.c */
 
-void sys_stat_nanoseconds (struct tar_stat_info *stat);
+void sys_stat_nanoseconds (struct tar_stat_info *);
 void sys_detect_dev_null_output (void);
 void sys_save_archive_dev_ino (void);
 void sys_drain_input_pipe (void);
@@ -652,7 +667,8 @@ int sys_truncate (int fd);
 void sys_reset_uid_gid (void);
 pid_t sys_child_open_for_compress (void);
 pid_t sys_child_open_for_uncompress (void);
-ssize_t sys_write_archive_buffer (void);
+void sys_reset_uid_gid (void);
+size_t sys_write_archive_buffer (void);
 bool sys_get_archive_stat (void);
 void sys_reset_uid_gid (void);
 
@@ -660,14 +676,14 @@ void sys_reset_uid_gid (void);
 void report_difference (struct tar_stat_info *st, const char *message, ...);
 
 /* Module sparse.c */
-bool sparse_file_p (struct tar_stat_info *stat);
-bool sparse_member_p (struct tar_stat_info *stat);
-bool sparse_fixup_header (struct tar_stat_info *stat);
-enum dump_status sparse_dump_file (int fd, struct tar_stat_info *stat);
-enum dump_status sparse_extract_file (int fd, struct tar_stat_info *stat, off_t *size);
-enum dump_status sparse_skip_file (struct tar_stat_info *stat);
-bool sparse_diff_file (int fd, struct tar_stat_info *stat);
+bool sparse_file_p (struct tar_stat_info *);
+bool sparse_member_p (struct tar_stat_info *);
+bool sparse_fixup_header (struct tar_stat_info *);
+enum dump_status sparse_dump_file (int, struct tar_stat_info *);
+enum dump_status sparse_extract_file (int, struct tar_stat_info *, off_t *);
+enum dump_status sparse_skip_file (struct tar_stat_info *);
+bool sparse_diff_file (int, struct tar_stat_info *);
 
 /* Module utf8.c */
 bool string_ascii_p (const char *str);
-bool utf8_convert(bool to_utf, const char *input, char **output);
+bool utf8_convert (bool to_utf, char const *input, char **output);

+ 14 - 13
src/compare.c

@@ -1,7 +1,7 @@
 /* Diff files from a tar archive.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003 Free Software Foundation, Inc.
+   2003, 2004 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1987-04-30.
 
@@ -62,7 +62,8 @@ diff_init (void)
 /* Sigh about something that differs by writing a MESSAGE to stdlis,
    given MESSAGE is nonzero.  Also set the exit status if not already.  */
 void
-report_difference (struct tar_stat_info *st, const char *fmt, ...)
+report_difference (struct tar_stat_info *st __attribute__ ((unused)),
+		   const char *fmt, ...)
 {
   if (fmt)
     {
@@ -74,35 +75,34 @@ report_difference (struct tar_stat_info *st, const char *fmt, ...)
       va_end (ap);
       fprintf (stdlis, "\n");
     }
-  
+
   if (exit_status == TAREXIT_SUCCESS)
     exit_status = TAREXIT_DIFFERS;
 }
 
 /* Take a buffer returned by read_and_process and do nothing with it.  */
 static int
-process_noop (size_t size, char *data)
+process_noop (size_t size __attribute__ ((unused)),
+	      char *data __attribute__ ((unused)))
 {
-  /* Yes, I know.  SIZE and DATA are unused in this function.  Some
-     compilers may even report it.  That's OK, just relax!  */
   return 1;
 }
 
 static int
 process_rawdata (size_t bytes, char *buffer)
 {
-  ssize_t status = safe_read (diff_handle, diff_buffer, bytes);
+  size_t status = safe_read (diff_handle, diff_buffer, bytes);
 
   if (status != bytes)
     {
-      if (status < 0)
+      if (status == SAFE_READ_ERROR)
 	{
 	  read_error (current_stat_info.file_name);
 	  report_difference (&current_stat_info, NULL);
 	}
       else
 	{
-	  report_difference (&current_stat_info, 
+	  report_difference (&current_stat_info,
 			     ngettext ("Could only read %lu of %lu byte",
 				       "Could only read %lu of %lu bytes",
 				       bytes),
@@ -308,19 +308,20 @@ diff_archive (void)
 
     case LNKTYPE:
       {
-	struct stat link_data, stat_data;
+	struct stat file_data;
+	struct stat link_data;
 
-	if (!get_stat_data (current_stat_info.file_name, &stat_data))
+	if (!get_stat_data (current_stat_info.file_name, &file_data))
 	  break;
 	if (!get_stat_data (current_stat_info.link_name, &link_data))
 	  break;
-	if (!sys_compare_links (&stat_data, &link_data))
+	if (!sys_compare_links (&file_data, &link_data))
 	  report_difference (&current_stat_info,
 			     _("Not linked to %s"),
 			     quote (current_stat_info.link_name));
       }
       break;
-      
+
 #ifdef HAVE_READLINK
     case SYMTYPE:
       {

+ 152 - 151
src/create.c

@@ -337,11 +337,11 @@ string_to_chars (char *str, char *p, size_t s)
    b) current archive is /dev/null */
 
 bool
-file_dumpable_p (struct tar_stat_info *stat)
+file_dumpable_p (struct tar_stat_info *st)
 {
   return !(dev_null_output
-	   || (stat->archive_file_size == 0
-	       && (stat->stat.st_mode & MODE_R) == MODE_R));
+	   || (st->archive_file_size == 0
+	       && (st->stat.st_mode & MODE_R) == MODE_R));
 }
 
 
@@ -376,7 +376,7 @@ start_private_header (const char *name, size_t size)
 {
   time_t t;
   union block *header = find_next_block ();
-  
+
   memset (header->buffer, 0, sizeof (union block));
 
   tar_copy_str (header->header.name, name, NAME_FIELD_SIZE);
@@ -397,7 +397,7 @@ start_private_header (const char *name, size_t size)
 /* Create a new header and store there at most NAME_FIELD_SIZE bytes of
    the file name */
 
-static union block * 
+static union block *
 write_short_name (struct tar_stat_info *st)
 {
   union block *header = find_next_block ();
@@ -464,7 +464,7 @@ write_ustar_long_name (const char *name)
 	     PREFIX_FIELD_SIZE + NAME_FIELD_SIZE + 1));
       return NULL;
     }
-  
+
   i = split_long_name (name, length);
   if (i == 0 || length - i - 1 > NAME_FIELD_SIZE)
     {
@@ -478,7 +478,7 @@ write_ustar_long_name (const char *name)
   memset (header->buffer, 0, sizeof (header->buffer));
   memcpy (header->header.prefix, name, i);
   memcpy (header->header.name, name + i + 1, length - i - 1);
-  
+
   return header;
 }
 
@@ -499,7 +499,7 @@ write_long_link (struct tar_stat_info *st)
 	     _("%s: link name is too long; not dumped"),
 	     quotearg_colon (st->link_name)));
 	    break;
-      
+
     case OLDGNU_FORMAT:
     case GNU_FORMAT:
       write_gnu_long_link (st, st->link_name, GNUTYPE_LONGLINK);
@@ -528,11 +528,11 @@ write_long_name (struct tar_stat_info *st)
 	  return NULL;
 	}
       break;
-      
+
     case USTAR_FORMAT:
     case STAR_FORMAT:
       return write_ustar_long_name (st->file_name);
-      
+
     case OLDGNU_FORMAT:
     case GNU_FORMAT:
       write_gnu_long_link (st, st->file_name, GNUTYPE_LONGNAME);
@@ -543,7 +543,7 @@ write_long_name (struct tar_stat_info *st)
     }
   return write_short_name (st);
 }
-		       
+
 static union block *
 write_extended (struct tar_stat_info *st, union block *old_header)
 {
@@ -551,8 +551,8 @@ write_extended (struct tar_stat_info *st, union block *old_header)
   char *p;
 
   if (extended_header.buffer || extended_header.stk == NULL)
-    return old_header; 
-  
+    return old_header;
+
   xheader_finish (&extended_header);
   memcpy (hp.buffer, old_header, sizeof (hp));
   p = xheader_xhdr_name (st);
@@ -563,7 +563,7 @@ write_extended (struct tar_stat_info *st, union block *old_header)
   return header;
 }
 
-static union block * 
+static union block *
 write_header_name (struct tar_stat_info *st)
 {
   if (archive_format == POSIX_FORMAT && !string_ascii_p (st->file_name))
@@ -634,7 +634,7 @@ start_header (struct tar_stat_info *st)
     xheader_store ("uid", st, NULL);
   else
     UID_TO_CHARS (st->stat.st_uid, header->header.uid);
-  
+
   if (st->stat.st_gid > MAXOCTAL7 && archive_format == POSIX_FORMAT)
     xheader_store ("gid", st, NULL);
   else
@@ -669,7 +669,7 @@ start_header (struct tar_stat_info *st)
       MAJOR_TO_CHARS (0, header->header.devmajor);
       MINOR_TO_CHARS (0, header->header.devminor);
     }
-  
+
   if (archive_format == POSIX_FORMAT)
     {
       xheader_store ("atime", st, NULL);
@@ -713,7 +713,7 @@ start_header (struct tar_stat_info *st)
     {
       uid_to_uname (st->stat.st_uid, &st->uname);
       gid_to_gname (st->stat.st_gid, &st->gname);
-      
+
       if (archive_format == POSIX_FORMAT
 	  && (strlen (st->uname) > UNAME_FIELD_SIZE
 	      || !string_ascii_p (st->uname)))
@@ -802,40 +802,40 @@ pad_archive (off_t size_left)
       set_next_block_after (blk);
       size_left -= BLOCKSIZE;
     }
-}  
+}
 
 static enum dump_status
-dump_regular_file (int fd, struct tar_stat_info *stat)
+dump_regular_file (int fd, struct tar_stat_info *st)
 {
-  off_t size_left = stat->stat.st_size;
+  off_t size_left = st->stat.st_size;
   off_t block_ordinal;
   union block *blk;
-  
+
   block_ordinal = current_block_ordinal ();
-  blk = start_header (stat);
+  blk = start_header (st);
   if (!blk)
     return dump_status_fail;
 
   /* Mark contiguous files, if we support them.  */
-  if (archive_format != V7_FORMAT && S_ISCTG (stat->stat.st_mode))
+  if (archive_format != V7_FORMAT && S_ISCTG (st->stat.st_mode))
     blk->header.typeflag = CONTTYPE;
 
-  finish_header (stat, blk, block_ordinal);
+  finish_header (st, blk, block_ordinal);
 
   while (size_left > 0)
     {
       size_t bufsize, count;
-      
+
       if (multi_volume_option)
 	{
-	  assign_string (&save_name, stat->file_name);
+	  assign_string (&save_name, st->file_name);
 	  save_sizeleft = size_left;
-	  save_totsize = stat->stat.st_size;
+	  save_totsize = st->stat.st_size;
 	}
       blk = find_next_block ();
-      
+
       bufsize = available_space_after (blk);
-      
+
       if (size_left < bufsize)
 	{
 	  /* Last read -- zero out area beyond.  */
@@ -844,12 +844,12 @@ dump_regular_file (int fd, struct tar_stat_info *stat)
 	  if (count)
 	    memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
 	}
-      
+
       count = (fd < 0) ? bufsize : safe_read (fd, blk->buffer, bufsize);
-      if (count < 0)
+      if (count == SAFE_READ_ERROR)
 	{
-	  read_diag_details (stat->orig_file_name, 
-	                     stat->stat.st_size - size_left, bufsize);
+	  read_diag_details (st->orig_file_name,
+	                     st->stat.st_size - size_left, bufsize);
 	  pad_archive (size_left);
 	  return dump_status_short;
 	}
@@ -865,7 +865,7 @@ dump_regular_file (int fd, struct tar_stat_info *stat)
 		 ngettext ("%s: File shrank by %s byte; padding with zeros",
 			   "%s: File shrank by %s bytes; padding with zeros",
 			   size_left),
-		 quotearg_colon (stat->orig_file_name),
+		 quotearg_colon (st->orig_file_name),
 		 STRINGIFY_BIGINT (size_left, buf)));
 	  if (! ignore_failed_read_option)
 	    exit_status = TAREXIT_FAILURE;
@@ -876,7 +876,7 @@ dump_regular_file (int fd, struct tar_stat_info *stat)
   return dump_status_ok;
 }
 
-void
+static void
 dump_regular_finish (int fd, struct tar_stat_info *st, time_t original_ctime)
 {
   if (fd >= 0)
@@ -903,22 +903,22 @@ dump_regular_finish (int fd, struct tar_stat_info *st, time_t original_ctime)
     }
 }
 
-void
+static void
 dump_dir0 (char *directory,
-	   struct tar_stat_info *stat, int top_level, dev_t parent_device)
+	   struct tar_stat_info *st, int top_level, dev_t parent_device)
 {
-  dev_t our_device = stat->stat.st_dev;
-  
-  if (!is_avoided_name (stat->orig_file_name))
+  dev_t our_device = st->stat.st_dev;
+
+  if (!is_avoided_name (st->orig_file_name))
     {
       union block *blk = NULL;
       off_t block_ordinal = current_block_ordinal ();
-      stat->stat.st_size = 0;	/* force 0 size on dir */
+      st->stat.st_size = 0;	/* force 0 size on dir */
 
-      blk = start_header (stat);
+      blk = start_header (st);
       if (!blk)
 	return;
-	  
+
       if (incremental_option)
 	blk->header.typeflag = GNUTYPE_DUMPDIR;
       else /* if (standard_option) */
@@ -927,7 +927,7 @@ dump_dir0 (char *directory,
       /* If we're gnudumping, we aren't done yet so don't close it.  */
 
       if (!incremental_option)
-	finish_header (stat, blk, block_ordinal);
+	finish_header (st, blk, block_ordinal);
       else if (gnu_list_name->dir_contents)
 	{
 	  off_t size_left;
@@ -935,8 +935,8 @@ dump_dir0 (char *directory,
 	  size_t bufsize;
 	  ssize_t count;
 	  const char *buffer, *p_buffer;
-	  off_t block_ordinal = current_block_ordinal ();
-	  
+
+	  block_ordinal = current_block_ordinal ();
 	  buffer = gnu_list_name->dir_contents; /* FOO */
 	  totsize = 0;
 	  if (buffer)
@@ -948,14 +948,14 @@ dump_dir0 (char *directory,
 	      }
 	  totsize++;
 	  OFF_TO_CHARS (totsize, blk->header.size);
-	  finish_header (stat, blk, block_ordinal); 
+	  finish_header (st, blk, block_ordinal);
 	  p_buffer = buffer;
 	  size_left = totsize;
 	  while (size_left > 0)
 	    {
 	      if (multi_volume_option)
 		{
-		  assign_string (&save_name, stat->orig_file_name);
+		  assign_string (&save_name, st->orig_file_name);
 		  save_sizeleft = size_left;
 		  save_totsize = totsize;
 		}
@@ -984,25 +984,25 @@ dump_dir0 (char *directory,
 
   if (one_file_system_option
       && !top_level
-      && parent_device != stat->stat.st_dev)
+      && parent_device != st->stat.st_dev)
     {
       if (verbose_option)
 	WARN ((0, 0,
 	       _("%s: file is on a different filesystem; not dumped"),
-	       quotearg_colon (stat->orig_file_name)));
+	       quotearg_colon (st->orig_file_name)));
       return;
     }
 
   {
     char const *entry;
     size_t entry_len;
-    char *name_buf = strdup (stat->orig_file_name);
+    char *name_buf = strdup (st->orig_file_name);
     size_t name_size = strlen (name_buf);
     size_t name_len = name_size;
-    
+
     /* Now output all the files in the directory.  */
     /* FIXME: Should speed this up by cd-ing into the dir.  */
-    
+
     for (entry = directory; (entry_len = strlen (entry)) != 0;
 	 entry += entry_len + 1)
       {
@@ -1015,7 +1015,7 @@ dump_dir0 (char *directory,
 	if (!excluded_name (name_buf))
 	  dump_file (name_buf, 0, our_device);
       }
-    
+
     free (name_buf);
   }
 }
@@ -1033,22 +1033,22 @@ ensure_slash (char **pstr)
   (*pstr)[len] = '\0';
 }
 
-bool
-dump_dir (struct tar_stat_info *stat, int top_level, dev_t parent_device)
+static bool
+dump_dir (struct tar_stat_info *st, int top_level, dev_t parent_device)
 {
   char *directory;
 
-  directory = savedir (stat->orig_file_name);
+  directory = savedir (st->orig_file_name);
   if (!directory)
     {
-      savedir_diag (stat->orig_file_name);
+      savedir_diag (st->orig_file_name);
       return false;
     }
 
-  ensure_slash (&stat->orig_file_name);
-  ensure_slash (&stat->file_name);
+  ensure_slash (&st->orig_file_name);
+  ensure_slash (&st->file_name);
 
-  dump_dir0 (directory, stat, top_level, parent_device);
+  dump_dir0 (directory, st, top_level, parent_device);
 
   free (directory);
   return true;
@@ -1064,7 +1064,7 @@ create_archive (void)
 
   open_archive (ACCESS_WRITE);
   xheader_write_global ();
-  
+
   if (incremental_option)
     {
       size_t buffer_size = 1000;
@@ -1131,8 +1131,9 @@ create_archive (void)
 static unsigned
 hash_link (void const *entry, unsigned n_buckets)
 {
-  struct link const *link = entry;
-  return (uintmax_t) (link->dev ^ link->ino) % n_buckets;
+  struct link const *l = entry;
+  uintmax_t num = l->dev ^ l->ino;
+  return num % n_buckets;
 }
 
 /* Compare two links for equality.  */
@@ -1164,41 +1165,41 @@ static Hash_table *link_table;
 /* Try to dump stat as a hard link to another file in the archive. If
    succeeded returns true */
 static bool
-dump_hard_link (struct tar_stat_info *stat)
+dump_hard_link (struct tar_stat_info *st)
 {
-  if (link_table && stat->stat.st_nlink > 1)
+  if (link_table && st->stat.st_nlink > 1)
     {
       struct link lp;
-      struct link *dup;
+      struct link *duplicate;
       off_t block_ordinal;
       union block *blk;
-      
-      lp.ino = stat->stat.st_ino;
-      lp.dev = stat->stat.st_dev;
 
-      if ((dup = hash_lookup (link_table, &lp)))
+      lp.ino = st->stat.st_ino;
+      lp.dev = st->stat.st_dev;
+
+      if ((duplicate = hash_lookup (link_table, &lp)))
 	{
 	  /* We found a link.  */
-	  char const *link_name = safer_name_suffix (dup->name, true);
+	  char const *link_name = safer_name_suffix (duplicate->name, true);
+
+	  duplicate->nlink--;
 
-	  dup->nlink--;
-	      
 	  block_ordinal = current_block_ordinal ();
-	  assign_string (&stat->link_name, link_name);
+	  assign_string (&st->link_name, link_name);
 	  if (NAME_FIELD_SIZE < strlen (link_name))
-	    write_long_link (stat);
-	  
-	  stat->stat.st_size = 0;
-	  blk = start_header (stat);
+	    write_long_link (st);
+
+	  st->stat.st_size = 0;
+	  blk = start_header (st);
 	  if (!blk)
 	    return true;
 	  tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
 
 	  blk->header.typeflag = LNKTYPE;
-	  finish_header (stat, blk, block_ordinal);
+	  finish_header (st, blk, block_ordinal);
 
-	  if (remove_files_option && unlink (stat->orig_file_name) != 0)
-	    unlink_error (stat->orig_file_name);
+	  if (remove_files_option && unlink (st->orig_file_name) != 0)
+	    unlink_error (st->orig_file_name);
 
 	  return true;
 	}
@@ -1207,25 +1208,25 @@ dump_hard_link (struct tar_stat_info *stat)
 }
 
 static void
-file_count_links (struct tar_stat_info *stat)
+file_count_links (struct tar_stat_info *st)
 {
-  if (stat->stat.st_nlink > 1)
+  if (st->stat.st_nlink > 1)
     {
-      struct link *dup;
+      struct link *duplicate;
       struct link *lp = xmalloc (offsetof (struct link, name)
-				 + strlen (stat->orig_file_name) + 1);
-      lp->ino = stat->stat.st_ino;
-      lp->dev = stat->stat.st_dev;
-      lp->nlink = stat->stat.st_nlink;
-      strcpy (lp->name, stat->orig_file_name);
+				 + strlen (st->orig_file_name) + 1);
+      lp->ino = st->stat.st_ino;
+      lp->dev = st->stat.st_dev;
+      lp->nlink = st->stat.st_nlink;
+      strcpy (lp->name, st->orig_file_name);
 
       if (! ((link_table
 	      || (link_table = hash_initialize (0, 0, hash_link,
 						compare_links, 0)))
-	     && (dup = hash_insert (link_table, lp))))
+	     && (duplicate = hash_insert (link_table, lp))))
 	xalloc_die ();
 
-      if (dup != lp)
+      if (duplicate != lp)
 	abort ();
       lp->nlink--;
     }
@@ -1234,7 +1235,7 @@ file_count_links (struct tar_stat_info *stat)
 /* For each dumped file, check if all its links were dumped. Emit
    warnings if it is not so. */
 void
-check_links ()
+check_links (void)
 {
   struct link *lp;
 
@@ -1261,8 +1262,8 @@ check_links ()
 /* FIXME: One should make sure that for *every* path leading to setting
    exit_status to failure, a clear diagnostic has been issued.  */
 
-void
-dump_file0 (struct tar_stat_info *stat, char *p,
+static void
+dump_file0 (struct tar_stat_info *st, char *p,
 	    int top_level, dev_t parent_device)
 {
   union block *header;
@@ -1270,26 +1271,26 @@ dump_file0 (struct tar_stat_info *stat, char *p,
   time_t original_ctime;
   struct utimbuf restore_times;
   off_t block_ordinal = -1;
-  
+
   if (interactive_option && !confirm ("add", p))
     return;
 
-  assign_string (&stat->orig_file_name, p);
-  assign_string (&stat->file_name, safer_name_suffix (p, false));
+  assign_string (&st->orig_file_name, p);
+  assign_string (&st->file_name, safer_name_suffix (p, false));
 
-  if (deref_stat (dereference_option, p, &stat->stat) != 0)
+  if (deref_stat (dereference_option, p, &st->stat) != 0)
     {
       stat_diag (p);
       return;
     }
-  stat->archive_file_size = stat->stat.st_size;
-  sys_stat_nanoseconds(stat);
-  original_ctime = stat->stat.st_ctime;
-  restore_times.actime = stat->stat.st_atime;
-  restore_times.modtime = stat->stat.st_mtime;
+  st->archive_file_size = st->stat.st_size;
+  sys_stat_nanoseconds (st);
+  original_ctime = st->stat.st_ctime;
+  restore_times.actime = st->stat.st_atime;
+  restore_times.modtime = st->stat.st_mtime;
 
 #ifdef S_ISHIDDEN
-  if (S_ISHIDDEN (stat->stat.st_mode))
+  if (S_ISHIDDEN (st->stat.st_mode))
     {
       char *new = (char *) alloca (strlen (p) + 2);
       if (new)
@@ -1304,9 +1305,9 @@ dump_file0 (struct tar_stat_info *stat, char *p,
   /* See if we want only new files, and check if this one is too old to
      put in the archive.  */
 
-  if (!S_ISDIR (stat->stat.st_mode)
-      && stat->stat.st_mtime < newer_mtime_option
-      && (!after_date_option || stat->stat.st_ctime < newer_ctime_option))
+  if (!S_ISDIR (st->stat.st_mode)
+      && OLDER_STAT_TIME (st->stat, m)
+      && (!after_date_option || OLDER_STAT_TIME (st->stat, c)))
     {
       if (0 < top_level) /* equivalent to !incremental_option */
 	WARN ((0, 0, _("%s: file is unchanged; not dumped"),
@@ -1316,16 +1317,16 @@ dump_file0 (struct tar_stat_info *stat, char *p,
     }
 
   /* See if we are trying to dump the archive.  */
-  if (sys_file_is_archive (stat))
+  if (sys_file_is_archive (st))
     {
       WARN ((0, 0, _("%s: file is the archive; not dumped"),
 	     quotearg_colon (p)));
       return;
     }
 
-  if (S_ISDIR (stat->stat.st_mode))
+  if (S_ISDIR (st->stat.st_mode))
     {
-      dump_dir (stat, top_level, parent_device);
+      dump_dir (st, top_level, parent_device);
       if (atime_preserve_option)
 	utime (p, &restore_times);
       return;
@@ -1335,49 +1336,49 @@ dump_file0 (struct tar_stat_info *stat, char *p,
   else
     {
       /* Check for multiple links.  */
-      if (dump_hard_link (stat))
+      if (dump_hard_link (st))
 	return;
-      
+
       /* This is not a link to a previously dumped file, so dump it.  */
 
-      if (S_ISREG (stat->stat.st_mode)
-	  || S_ISCTG (stat->stat.st_mode))
+      if (S_ISREG (st->stat.st_mode)
+	  || S_ISCTG (st->stat.st_mode))
 	{
 	  int fd;
 	  enum dump_status status;
 
-	  if (file_dumpable_p (stat))
+	  if (file_dumpable_p (st))
 	    {
-	      fd = open (stat->orig_file_name,
+	      fd = open (st->orig_file_name,
 			 O_RDONLY | O_BINARY);
 	      if (fd < 0)
 		{
 		  if (!top_level && errno == ENOENT)
 		    WARN ((0, 0, _("%s: File removed before we read it"),
-			   quotearg_colon (stat->orig_file_name)));
+			   quotearg_colon (st->orig_file_name)));
 		  else
-		    open_diag (stat->orig_file_name);
+		    open_diag (st->orig_file_name);
 		  return;
 		}
 	    }
 	  else
 	    fd = -1;
-	  
-	  if (sparse_option && sparse_file_p (stat))
+
+	  if (sparse_option && sparse_file_p (st))
 	    {
-	      status = sparse_dump_file (fd, stat); 
+	      status = sparse_dump_file (fd, st);
 	      if (status == dump_status_not_implemented)
-		status = dump_regular_file (fd, stat);
+		status = dump_regular_file (fd, st);
 	    }
 	  else
-	    status = dump_regular_file (fd, stat);
+	    status = dump_regular_file (fd, st);
 
 	  switch (status)
 	    {
 	    case dump_status_ok:
 	      if (multi_volume_option)
 		assign_string (&save_name, 0);
-	      dump_regular_finish (fd, stat, original_ctime);
+	      dump_regular_finish (fd, st, original_ctime);
 	      break;
 
 	    case dump_status_short:
@@ -1385,7 +1386,7 @@ dump_file0 (struct tar_stat_info *stat, char *p,
 		assign_string (&save_name, 0);
 	      close (fd);
 	      break;
-      
+
 	    case dump_status_fail:
 	      close (fd);
 	      return;
@@ -1395,17 +1396,17 @@ dump_file0 (struct tar_stat_info *stat, char *p,
 	    }
 
 	  if (atime_preserve_option)
-	    utime (stat->orig_file_name, &restore_times);
-	  file_count_links (stat);
+	    utime (st->orig_file_name, &restore_times);
+	  file_count_links (st);
 	  return;
 	}
 #ifdef HAVE_READLINK
-      else if (S_ISLNK (stat->stat.st_mode))
+      else if (S_ISLNK (st->stat.st_mode))
 	{
 	  char *buffer;
 	  int size;
-	  size_t linklen = stat->stat.st_size;
-	  if (linklen != stat->stat.st_size || linklen + 1 == 0)
+	  size_t linklen = st->stat.st_size;
+	  if (linklen != st->stat.st_size || linklen + 1 == 0)
 	    xalloc_die ();
 	  buffer = (char *) alloca (linklen + 1);
 	  size = readlink (p, buffer, linklen + 1);
@@ -1415,18 +1416,18 @@ dump_file0 (struct tar_stat_info *stat, char *p,
 	      return;
 	    }
 	  buffer[size] = '\0';
-	  assign_string (&stat->link_name, buffer);
+	  assign_string (&st->link_name, buffer);
 	  if (size > NAME_FIELD_SIZE)
-	    write_long_link (stat);
+	    write_long_link (st);
 
 	  block_ordinal = current_block_ordinal ();
-	  stat->stat.st_size = 0;	/* force 0 size on symlink */
-	  header = start_header (stat);
+	  st->stat.st_size = 0;	/* force 0 size on symlink */
+	  header = start_header (st);
 	  if (!header)
 	    return;
 	  tar_copy_str (header->header.linkname, buffer, NAME_FIELD_SIZE);
 	  header->header.typeflag = SYMTYPE;
-	  finish_header (stat, header, block_ordinal);
+	  finish_header (st, header, block_ordinal);
 	  /* nothing more to do to it */
 
 	  if (remove_files_option)
@@ -1434,22 +1435,22 @@ dump_file0 (struct tar_stat_info *stat, char *p,
 	      if (unlink (p) == -1)
 		unlink_error (p);
 	    }
-	  file_count_links (stat);
+	  file_count_links (st);
 	  return;
 	}
 #endif
-      else if (S_ISCHR (stat->stat.st_mode))
+      else if (S_ISCHR (st->stat.st_mode))
 	type = CHRTYPE;
-      else if (S_ISBLK (stat->stat.st_mode))
+      else if (S_ISBLK (st->stat.st_mode))
 	type = BLKTYPE;
-      else if (S_ISFIFO (stat->stat.st_mode))
+      else if (S_ISFIFO (st->stat.st_mode))
 	type = FIFOTYPE;
-      else if (S_ISSOCK (stat->stat.st_mode))
+      else if (S_ISSOCK (st->stat.st_mode))
 	{
 	  WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
 	  return;
 	}
-      else if (S_ISDOOR (stat->stat.st_mode))
+      else if (S_ISDOOR (st->stat.st_mode))
 	{
 	  WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
 	  return;
@@ -1468,21 +1469,21 @@ dump_file0 (struct tar_stat_info *stat, char *p,
     }
 
   block_ordinal = current_block_ordinal ();
-  stat->stat.st_size = 0;	/* force 0 size */
-  header = start_header (stat);
+  st->stat.st_size = 0;	/* force 0 size */
+  header = start_header (st);
   if (!header)
     return;
   header->header.typeflag = type;
 
   if (type != FIFOTYPE)
     {
-      MAJOR_TO_CHARS (major (stat->stat.st_rdev),
+      MAJOR_TO_CHARS (major (st->stat.st_rdev),
 		      header->header.devmajor);
-      MINOR_TO_CHARS (minor (stat->stat.st_rdev),
+      MINOR_TO_CHARS (minor (st->stat.st_rdev),
 		      header->header.devminor);
     }
 
-  finish_header (stat, header, block_ordinal);
+  finish_header (st, header, block_ordinal);
   if (remove_files_option)
     {
       if (unlink (p) == -1)
@@ -1493,8 +1494,8 @@ dump_file0 (struct tar_stat_info *stat, char *p,
 void
 dump_file (char *p, int top_level, dev_t parent_device)
 {
-  struct tar_stat_info stat;
-  tar_stat_init (&stat);
-  dump_file0 (&stat, p, top_level, parent_device);
-  tar_stat_destroy (&stat);
+  struct tar_stat_info st;
+  tar_stat_init (&st);
+  dump_file0 (&st, p, top_level, parent_device);
+  tar_stat_destroy (&st);
 }

+ 23 - 23
src/extract.c

@@ -1,7 +1,7 @@
 /* Extract files from a tar archive.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
-   2001, 2003 Free Software Foundation, Inc.
+   2001, 2003, 2004 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-11-19.
 
@@ -315,11 +315,11 @@ delay_set_stat (char const *file_name, struct stat const *stat_info,
 }
 
 /* Update the delayed_set_stat info for an intermediate directory
-   created on the path to DIR_NAME.  The intermediate directory turned
+   created on the path to DIR.  The intermediate directory turned
    out to be the same as this directory, e.g. due to ".." or symbolic
    links.  *DIR_STAT_INFO is the status of the directory.  */
 static void
-repair_delayed_set_stat (char const *dir_name,
+repair_delayed_set_stat (char const *dir,
 			 struct stat const *dir_stat_info)
 {
   struct delayed_set_stat *data;
@@ -344,7 +344,7 @@ repair_delayed_set_stat (char const *dir_name,
     }
 
   ERROR ((0, 0, _("%s: Unexpected inconsistency when making directory"),
-	  quotearg_colon (dir_name)));
+	  quotearg_colon (dir)));
 }
 
 /* After a file/link/symlink/directory creation has failed, see if
@@ -361,7 +361,7 @@ make_directories (char *file_name)
   int invert_permissions;
   int status;
 
-  
+
   for (cursor = cursor0; *cursor; cursor++)
     {
       if (! ISSLASH (*cursor))
@@ -423,25 +423,25 @@ static bool
 file_newer_p (const char *file_name, struct tar_stat_info *tar_stat)
 {
   struct stat st;
-	    
+
   if (stat (file_name, &st))
     {
       stat_warn (file_name);
       return true; /* Be on the safe side */
     }
   if (!S_ISDIR (st.st_mode)
-      && st.st_mtime >= current_stat_info.stat.st_mtime)
+      && st.st_mtime >= tar_stat->stat.st_mtime)
     {
       return true;
     }
   return false;
-}  
+}
 
 /* Prepare to extract a file.
    Return zero if extraction should not proceed.  */
 
 static int
-prepare_to_extract (char const *file_name, bool directory)
+prepare_to_extract (char const *file_name)
 {
   if (to_stdout_option)
     return 0;
@@ -460,7 +460,7 @@ prepare_to_extract (char const *file_name, bool directory)
     case KEEP_NEWER_FILES:
       if (file_newer_p (file_name, &current_stat_info))
 	{
-	  WARN ((0, 0, _("Current `%s' is newer"), file_name)); 
+	  WARN ((0, 0, _("Current `%s' is newer"), file_name));
 	  return 0;
 	}
       break;
@@ -480,7 +480,7 @@ static int
 maybe_recoverable (char *file_name, int *interdir_made)
 {
   int e = errno;
-  
+
   if (*interdir_made)
     return 0;
 
@@ -501,7 +501,7 @@ maybe_recoverable (char *file_name, int *interdir_made)
 	      return 0;
 	    }
 	  /* FALL THROUGH */
-	    
+
 	case DEFAULT_OLD_FILES:
 	case NO_OVERWRITE_DIR_OLD_FILES:
 	case OVERWRITE_OLD_FILES:
@@ -628,7 +628,7 @@ extract_archive (void)
 	}
       file_name += prefix_len;
     }
-  
+
   apply_nonancestor_delayed_set_stat (file_name, 0);
 
   /* Take a safety backup of a previously existing file.  */
@@ -648,7 +648,7 @@ extract_archive (void)
   /* KLUDGE */
   typeflag = sparse_member_p (&current_stat_info) ?
                   GNUTYPE_SPARSE : current_header->header.typeflag;
-  
+
   switch (typeflag)
     {
     case GNUTYPE_SPARSE:
@@ -679,7 +679,7 @@ extract_archive (void)
 	  goto extract_file;
 	}
 
-      if (! prepare_to_extract (file_name, 0))
+      if (! prepare_to_extract (file_name))
 	{
 	  skip_member ();
 	  if (backup_option)
@@ -794,7 +794,7 @@ extract_archive (void)
 
     case SYMTYPE:
 #ifdef HAVE_SYMLINK
-      if (! prepare_to_extract (file_name, 0))
+      if (! prepare_to_extract (file_name))
 	break;
 
       if (absolute_names_option
@@ -878,7 +878,7 @@ extract_archive (void)
 	      status = 0;
 	    }
 	}
-  
+
       if (status != 0 && backup_option)
 	undo_last_backup ();
       break;
@@ -899,7 +899,7 @@ extract_archive (void)
 #endif
 
     case LNKTYPE:
-      if (! prepare_to_extract (file_name, 0))
+      if (! prepare_to_extract (file_name))
 	break;
 
     again_link:
@@ -922,7 +922,7 @@ extract_archive (void)
 		    && ds->ino == st1.st_ino
 		    && ds->mtime == st1.st_mtime)
 		  {
-		    struct string_list *p = 
+		    struct string_list *p =
 		      xmalloc (offsetof (struct string_list, string)
 			       + strlen (file_name) + 1);
 		    strcpy (p->string, file_name);
@@ -963,7 +963,7 @@ extract_archive (void)
 
 #if S_IFCHR || S_IFBLK
     make_node:
-      if (! prepare_to_extract (file_name, 0))
+      if (! prepare_to_extract (file_name))
 	break;
 
       status = mknod (file_name, current_stat_info.stat.st_mode,
@@ -984,7 +984,7 @@ extract_archive (void)
 
 #if HAVE_MKFIFO || defined mkfifo
     case FIFOTYPE:
-      if (! prepare_to_extract (file_name, 0))
+      if (! prepare_to_extract (file_name))
 	break;
 
       while (status = mkfifo (file_name, current_stat_info.stat.st_mode),
@@ -1021,7 +1021,7 @@ extract_archive (void)
 	       | (we_are_root ? 0 : MODE_WXUSR))
 	      & MODE_RWX);
 
-      status = prepare_to_extract (file_name, 1);
+      status = prepare_to_extract (file_name);
       if (status == 0)
 	break;
       if (status < 0)
@@ -1053,7 +1053,7 @@ extract_archive (void)
 		}
 	      errno = EEXIST;
 	    }
-	
+
 	  if (maybe_recoverable (file_name, &interdir_made))
 	    goto again_dir;
 

+ 22 - 20
src/incremen.c

@@ -145,7 +145,7 @@ scan_path (struct obstack *stk, char *path, dev_t device)
 
   directory = find_directory (path);
   children = directory ? directory->children : CHANGED_CHILDREN;
-  
+
   if (dirp && children != NO_CHILDREN)
     for (entry = dirp;
 	 (entrylen = strlen (entry)) != 0;
@@ -159,23 +159,23 @@ scan_path (struct obstack *stk, char *path, dev_t device)
 	    name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
 	  }
 	strcpy (name_buffer + name_length, entry);
-	
+
 	if (excluded_name (name_buffer))
 	  obstack_1grow (stk, 'N');
 	else
 	  {
 	    struct stat stat_data;
-	    
+
 	    if (deref_stat (dereference_option, name_buffer, &stat_data))
 	      {
 		stat_diag (name_buffer);
 		continue;
 	      }
-	    
+
 	    if (S_ISDIR (stat_data.st_mode))
 	      {
 		bool nfs = NFS_FILE_STAT (stat_data);
-		
+
 		if ((directory = find_directory (name_buffer)) != NULL)
 		  {
 		    /* With NFS, the same file can have two different devices
@@ -184,7 +184,7 @@ scan_path (struct obstack *stk, char *path, dev_t device)
 		       To avoid spurious incremental redumping of
 		       directories, consider all NFS devices as equal,
 		       relying on the i-node to establish differences.  */
-		    
+
 		    if (! (((directory->nfs & nfs)
 			    || directory->device_number == stat_data.st_dev)
 			   && directory->inode_number == stat_data.st_ino))
@@ -209,13 +209,13 @@ scan_path (struct obstack *stk, char *path, dev_t device)
 						stat_data.st_ino, nfs, 1);
 		    directory->children =
 		      ((listed_incremental_option
-			|| newer_mtime_option <= stat_data.st_mtime
-			|| (after_date_option &&
-			    newer_ctime_option <= stat_data.st_ctime))
+			|| OLDER_STAT_TIME (stat_data, m)
+			|| (after_date_option
+			    && OLDER_STAT_TIME (stat_data, c)))
 		       ? ALL_CHILDREN
 		       : CHANGED_CHILDREN);
 		  }
-		
+
 		if (one_file_system_option && device != stat_data.st_dev)
 		  directory->children = NO_CHILDREN;
 		else if (children == ALL_CHILDREN)
@@ -239,19 +239,18 @@ scan_path (struct obstack *stk, char *path, dev_t device)
 
 	    else
 	      if (children == CHANGED_CHILDREN
-		  && stat_data.st_mtime < newer_mtime_option
-		  && (!after_date_option
-		      || stat_data.st_ctime < newer_ctime_option))
+		  && OLDER_STAT_TIME (stat_data, m)
+		  && (!after_date_option || OLDER_STAT_TIME (stat_data, c)))
 		obstack_1grow (stk, 'N');
 	      else
 		obstack_1grow (stk, 'Y');
 	  }
-	
+
 	obstack_grow (stk, entry, entrylen + 1);
       }
 
   obstack_grow (stk, "\000\000", 2);
-  
+
   free (name_buffer);
   if (dirp)
     free (dirp);
@@ -267,16 +266,16 @@ sort_obstack (struct obstack *stk)
   char *buffer;
   char **array;
   char **array_cursor;
-  
+
   counter = 0;
   for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1)
     counter++;
-  
+
   if (!counter)
     return NULL;
 
   array = obstack_alloc (stk, sizeof (char *) * (counter + 1));
-  
+
   array_cursor = array;
   for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1)
     *array_cursor++ = cursor;
@@ -290,7 +289,7 @@ sort_obstack (struct obstack *stk)
   for (array_cursor = array; *array_cursor; array_cursor++)
     {
       char *string = *array_cursor;
-      
+
       while ((*cursor++ = *string++))
 	continue;
     }
@@ -357,7 +356,10 @@ read_directory_file (void)
 	ERROR ((0, 0, "%s:1: %s", quotearg_colon (listed_incremental_option),
 		_("Time stamp out of range")));
       else
-	newer_mtime_option = t;
+	{
+	  newer_mtime_option.tv_sec = t;
+	  newer_mtime_option.tv_nsec = 0;
+	}
 
       while (0 < (n = getline (&buf, &bufsize, fp)))
 	{

+ 19 - 14
src/list.c

@@ -1,7 +1,7 @@
 /* List a tar archive, with support routines for reading a tar archive.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
-   2001, 2003 Free Software Foundation, Inc.
+   2001, 2003, 2004 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-08-26.
 
@@ -20,7 +20,7 @@
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* Define to non-zero for forcing old ctime format instead of ISO format.  */
-#undef USE_OLD_CTIME 
+#undef USE_OLD_CTIME
 
 #include "system.h"
 #include <quotearg.h>
@@ -78,7 +78,7 @@ read_and (void (*do_something) (void))
       prev_status = status;
       tar_stat_destroy (&current_stat_info);
       xheader_destroy (&extended_header);
-      
+
       status = read_header (false);
       switch (status)
 	{
@@ -92,12 +92,17 @@ read_and (void (*do_something) (void))
 	     Ensure incoming names are null terminated.  */
 
 	  if (! name_match (current_stat_info.file_name)
-	      || (newer_mtime_option != TYPE_MINIMUM (time_t)
+	      || (NEWER_OPTION_INITIALIZED (newer_mtime_option)
 		  /* FIXME: We get mtime now, and again later; this causes
 		     duplicate diagnostics if header.mtime is bogus.  */
 		  && ((current_stat_info.stat.st_mtime
-		       = TIME_FROM_HEADER (current_header->header.mtime))
-		      < newer_mtime_option))
+		       = TIME_FROM_HEADER (current_header->header.mtime)),
+#ifdef ST_MTIM_NSEC
+		      /* FIXME: Grab fractional time stamps from
+			 extended header.  */
+		      current_stat_info.stat.st_mtim.ST_MTIM_NSEC = 0,
+#endif
+		      OLDER_STAT_TIME (current_stat_info.stat, m)))
 	      || excluded_name (current_stat_info.file_name))
 	    {
 	      switch (current_header->header.typeflag)
@@ -356,7 +361,7 @@ read_header (bool raw_extended_headers)
 		xalloc_die ();
 
 	      header_copy = xmalloc (size + 1);
-	      
+
 	      if (header->header.typeflag == GNUTYPE_LONGNAME)
 		{
 		  if (next_long_name)
@@ -371,7 +376,7 @@ read_header (bool raw_extended_headers)
 		  next_long_link = header_copy;
 		  next_long_link_blocks = size / BLOCKSIZE;
 		}
-	      
+
 	      set_next_block_after (header);
 	      *header_copy = *header;
 	      bp = header_copy->buffer + BLOCKSIZE;
@@ -387,7 +392,7 @@ read_header (bool raw_extended_headers)
 		  written = available_space_after (data_block);
 		  if (written > size)
 		    written = size;
-		  
+
 		  memcpy (bp, data_block->buffer, written);
 		  bp += written;
 		  set_next_block_after ((union block *)
@@ -403,7 +408,7 @@ read_header (bool raw_extended_headers)
 	      xheader_read (header, OFF_FROM_HEADER (header->header.size));
 	      xheader_decode_global ();
 	    }
-      
+
 	  /* Loop!  */
 
 	}
@@ -520,7 +525,7 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
   assign_string (&stat_info->gname, header->header.gname);
   stat_info->devmajor = MAJOR_FROM_HEADER (header->header.devmajor);
   stat_info->devminor = MINOR_FROM_HEADER (header->header.devminor);
-  
+
   stat_info->stat.st_atime = start_time;
   stat_info->stat.st_ctime = start_time;
 
@@ -559,7 +564,7 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
 	      || !gname_to_gid (header->header.gname, &stat_info->stat.st_gid))
 	    stat_info->stat.st_gid = GID_FROM_HEADER (header->header.gid);
 	}
-      
+
       switch (header->header.typeflag)
 	{
 	case BLKTYPE:
@@ -961,7 +966,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
   char modes[11];
   char const *time_stamp;
   char *temp_name = st->orig_file_name ? st->orig_file_name : st->file_name;
-  
+
   /* These hold formatted ints.  */
   char uform[UINTMAX_STRSIZE_BOUND], gform[UINTMAX_STRSIZE_BOUND];
   char *user, *group;
@@ -1108,7 +1113,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
 	  strcat (size,
 		  STRINGIFY_BIGINT (minor (st->stat.st_rdev), uintbuf));
 	  break;
-	  
+
 	default:
 	  /* st->stat.st_size keeps stored file size */
 	  strcpy (size, STRINGIFY_BIGINT (st->stat.st_size, uintbuf));

+ 12 - 16
src/misc.c

@@ -1,7 +1,7 @@
 /* Miscellaneous functions, not really specific to GNU tar.
 
    Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
-   2003 Free Software Foundation, Inc.
+   2003, 2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
@@ -331,16 +331,17 @@ remove_any_file (const char *path, enum remove_option option)
 /* Check if PATH already exists and make a backup of it right now.
    Return success (nonzero) only if the backup is either unneeded, or
    successful.  For now, directories are considered to never need
-   backup.  If ARCHIVE is nonzero, this is the archive and so, we do
-   not have to backup block or character devices, nor remote entities.  */
+   backup.  If THIS_IS_THE_ARCHIVE is nonzero, this is the archive and
+   so, we do not have to backup block or character devices, nor remote
+   entities.  */
 bool
-maybe_backup_file (const char *path, int archive)
+maybe_backup_file (const char *path, int this_is_the_archive)
 {
   struct stat file_stat;
 
   /* Check if we really need to backup the file.  */
 
-  if (archive && _remdev (path))
+  if (this_is_the_archive && _remdev (path))
     return true;
 
   if (stat (path, &file_stat))
@@ -355,7 +356,8 @@ maybe_backup_file (const char *path, int archive)
   if (S_ISDIR (file_stat.st_mode))
     return true;
 
-  if (archive && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
+  if (this_is_the_archive
+      && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
     return true;
 
   assign_string (&before_backup_name, path);
@@ -586,12 +588,6 @@ close_error (char const *name)
   call_arg_error ("close", name);
 }
 
-void
-close_fatal (char const *name)
-{
-  call_arg_fatal ("close", name);
-}
-
 void
 close_warn (char const *name)
 {
@@ -875,16 +871,16 @@ write_error (char const *name)
 }
 
 void
-write_error_details (char const *name, ssize_t status, size_t size)
+write_error_details (char const *name, size_t status, size_t size)
 {
-  if (status < 0)
+  if (status == 0)
     write_error (name);
   else
     ERROR ((0, 0,
 	    ngettext ("%s: Wrote only %lu of %lu byte",
 		      "%s: Wrote only %lu of %lu bytes",
-		      record_size),
-	    name, (unsigned long) status, (unsigned long) record_size));
+		      size),
+	    name, (unsigned long int) status, (unsigned long int) size));
 }
 
 void

+ 16 - 16
src/names.c

@@ -1,7 +1,7 @@
 /* Various processing of names.
 
    Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
-   2003 Free Software Foundation, Inc.
+   2003, 2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
@@ -118,7 +118,7 @@ gid_to_gname (gid_t gid, char **gname)
 
 /* Given UNAME, set the corresponding UID and return 1, or else, return 0.  */
 int
-uname_to_uid (char *uname, uid_t *uidp)
+uname_to_uid (char const *uname, uid_t *uidp)
 {
   struct passwd *passwd;
 
@@ -148,7 +148,7 @@ uname_to_uid (char *uname, uid_t *uidp)
 
 /* Given GNAME, set the corresponding GID and return 1, or else, return 0.  */
 int
-gname_to_gid (char *gname, gid_t *gidp)
+gname_to_gid (char const *gname, gid_t *gidp)
 {
   struct group *group;
 
@@ -227,7 +227,7 @@ is_pattern (const char *string)
 /* Set up to gather file names for tar.  They can either come from a
    file or were saved from decoding arguments.  */
 void
-name_init (int argc, char *const *argv)
+name_init (void)
 {
   name_buffer = xmalloc (NAME_FIELD_SIZE + 2);
   name_buffer_length = NAME_FIELD_SIZE;
@@ -639,7 +639,7 @@ names_notfound (void)
 	  ERROR ((0, 0, _("%s: Required occurrence not found in archive"),
 		  quotearg_colon (cursor->name)));
       }
-  
+
   /* Don't bother freeing the name list; we're about to exit.  */
   namelist = 0;
   nametail = &namelist;
@@ -759,18 +759,18 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
       size_t allocated_length = (name_length >= NAME_FIELD_SIZE
 				 ? name_length + NAME_FIELD_SIZE
 				 : NAME_FIELD_SIZE);
-      char *name_buffer = xmalloc (allocated_length + 1);
+      char *namebuf = xmalloc (allocated_length + 1);
 				/* FIXME: + 2 above?  */
       char *string;
       size_t string_length;
       int change_dir = name->change_dir;
 
       name->dir_contents = buffer;
-      strcpy (name_buffer, path);
-      if (! ISSLASH (name_buffer[name_length - 1]))
+      strcpy (namebuf, path);
+      if (! ISSLASH (namebuf[name_length - 1]))
 	{
-	  name_buffer[name_length++] = '/';
-	  name_buffer[name_length] = '\0';
+	  namebuf[name_length++] = '/';
+	  namebuf[name_length] = '\0';
 	}
 
       for (string = buffer; *string; string += string_length + 1)
@@ -788,15 +788,15 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
 		    }
 		  while (allocated_length <= name_length + string_length);
 
-		  name_buffer = xrealloc (name_buffer, allocated_length + 1);
+		  namebuf = xrealloc (namebuf, allocated_length + 1);
 		}
-	      strcpy (name_buffer + name_length, string + 1);
-	      add_hierarchy_to_namelist (addname (name_buffer, change_dir),
+	      strcpy (namebuf + name_length, string + 1);
+	      add_hierarchy_to_namelist (addname (namebuf, change_dir),
 					 device);
 	    }
 	}
 
-      free (name_buffer);
+      free (namebuf);
     }
 }
 
@@ -1023,7 +1023,7 @@ safer_name_suffix (char const *file_name, bool link_target)
 	{
           if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
 	    prefix_len = p + 2 - file_name;
-	  
+
 	  do
 	    {
 	      char c = *p++;
@@ -1067,7 +1067,7 @@ safer_name_suffix (char const *file_name, bool link_target)
 	  };
 	  WARN ((0, 0, _(diagnostic[link_target])));
 	}
-      
+
       p = ".";
     }
 

+ 20 - 18
src/rmt.c

@@ -1,7 +1,7 @@
 /* Remote connection server.
 
-   Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003 Free
-   Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2003, 2004
+   Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
@@ -117,12 +117,12 @@ get_string (char *string)
 {
   int counter;
 
-  for (counter = 0; counter < STRING_SIZE; counter++)
+  for (counter = 0; ; counter++)
     {
       if (safe_read (STDIN_FILENO, string + counter, 1) != 1)
 	exit (EXIT_SUCCESS);
 
-      if (string[counter] == '\n')
+      if (string[counter] == '\n' || counter == STRING_SIZE - 1)
 	break;
     }
   string[counter] = '\0';
@@ -179,11 +179,11 @@ decode_oflag (char const *oflag_string)
   char *oflag_num_end;
   int numeric_oflag = strtol (oflag_string, &oflag_num_end, 10);
   int symbolic_oflag = 0;
-  
+
   oflag_string = oflag_num_end;
   while (ISSPACE ((unsigned char) *oflag_string))
     oflag_string++;
-    
+
   do
     {
       struct name_value_pair { char const *name; int value; };
@@ -247,6 +247,8 @@ static struct option const long_opts[] =
   {0, 0, 0, 0}
 };
 
+static void usage (int) __attribute__ ((noreturn));
+
 static void
 usage (int status)
 {
@@ -272,7 +274,7 @@ int
 main (int argc, char *const *argv)
 {
   char command;
-  ssize_t status;
+  size_t status;
 
   /* FIXME: Localization is meaningless, unless --help and --version are
      locally used.  Localization would be best accomplished by the calling
@@ -287,14 +289,14 @@ main (int argc, char *const *argv)
     {
     default:
       usage (EXIT_FAILURE);
-      
+
     case 'h':
       usage (EXIT_SUCCESS);
-      
+
     case 'v':
       {
 	printf ("rmt (%s) %s\n%s\n", PACKAGE_NAME, PACKAGE_VERSION,
-		"Copyright (C) 2003 Free Software Foundation, Inc.");
+		"Copyright (C) 2004 Free Software Foundation, Inc.");
 	puts (_("\
 This program comes with NO WARRANTY, to the extent permitted by law.\n\
 You may redistribute it under the terms of the GNU General Public License;\n\
@@ -421,7 +423,7 @@ top:
 	do
 	  *--p = '0' + (int) (count % 10);
 	while ((count /= 10) != 0);
-	
+
 	DEBUG1 ("rmtd: A %s\n", p);
 
 	sprintf (reply_buffer, "A%s\n", p);
@@ -444,7 +446,7 @@ top:
 	  {
 	    status = safe_read (STDIN_FILENO, &record_buffer[counter],
 				size - counter);
-	    if (status <= 0)
+	    if (status == SAFE_READ_ERROR || status == 0)
 	      {
 		DEBUG (_("rmtd: Premature eof\n"));
 
@@ -453,7 +455,7 @@ top:
 	      }
 	  }
 	status = full_write (tape, record_buffer, size);
-	if (status < 0)
+	if (status != size)
 	  goto ioerror;
 	goto respond;
       }
@@ -469,9 +471,9 @@ top:
 	size = atol (count_string);
 	prepare_input_buffer (-1, size);
 	status = safe_read (tape, record_buffer, size);
-	if (status < 0)
+	if (status == SAFE_READ_ERROR)
 	  goto ioerror;
-	sprintf (reply_buffer, "A%ld\n", (long) status);
+	sprintf (reply_buffer, "A%lu\n", (unsigned long int) status);
 	full_write (STDOUT_FILENO, reply_buffer, strlen (reply_buffer));
 	full_write (STDOUT_FILENO, record_buffer, status);
 	goto top;
@@ -496,13 +498,13 @@ top:
 	  /* Parse count_string, taking care to check for overflow.
 	     We can't use standard functions,
 	     since off_t might be longer than long.  */
-	  
+
 	  for (p = count_string;  *p == ' ' || *p == '\t';  p++)
 	    continue;
-	  
+
 	  negative = *p == '-';
 	  p += negative || *p == '+';
-	  
+
 	  for (;;)
 	    {
 	      int digit = *p++ - '0';

+ 4 - 4
src/rmt.h

@@ -1,7 +1,7 @@
 /* Definitions for communicating with a remote tape drive.
 
-   Copyright (C) 1988, 1992, 1996, 1997, 2001, 2003 Free Software
-   Foundation, Inc.
+   Copyright (C) 1988, 1992, 1996, 1997, 2001, 2003, 2004 Free
+   Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,8 +21,8 @@ extern char *rmt_path__;
 
 int rmt_open__ (const char *, int, int, const char *);
 int rmt_close__ (int);
-ssize_t rmt_read__ (int, char *, size_t);
-ssize_t rmt_write__ (int, char *, size_t);
+size_t rmt_read__ (int, char *, size_t);
+size_t rmt_write__ (int, char *, size_t);
 off_t rmt_lseek__ (int, off_t, int);
 int rmt_ioctl__ (int, int, char *);
 

+ 39 - 24
src/rtapelib.c

@@ -1,7 +1,7 @@
 /* Functions for communicating with a remote tape drive.
 
-   Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001 Free Software
-   Foundation, Inc.
+   Copyright 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2004 Free
+   Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -163,8 +163,6 @@ get_status_string (int handle, char *command_buffer)
 
   if (*cursor == 'E' || *cursor == 'F')
     {
-      errno = atoi (cursor + 1);
-
       /* Skip the error message line.  */
 
       /* FIXME: there is better to do than merely ignoring error messages
@@ -178,6 +176,8 @@ get_status_string (int handle, char *command_buffer)
 	    break;
       }
 
+      errno = atoi (cursor + 1);
+
       if (*cursor == 'F')
 	_rmt_shutdown (handle, errno);
 
@@ -199,12 +199,19 @@ get_status_string (int handle, char *command_buffer)
 
 /* Read and return the status from remote tape connection HANDLE.  If
    an error occurred, return -1 and set errno.  */
-static long
+static long int
 get_status (int handle)
 {
   char command_buffer[COMMAND_BUFFER_SIZE];
   const char *status = get_status_string (handle, command_buffer);
-  return status ? atol (status) : -1L;
+  if (status)
+    {
+      long int result = atol (status);
+      if (0 <= result)
+	return result;
+      errno = EIO;
+    }
+  return -1;
 }
 
 static off_t
@@ -226,10 +233,10 @@ get_status_off (int handle)
 
       for (;  *status == ' ' || *status == '\t';  status++)
 	continue;
-      
+
       negative = *status == '-';
       status += negative || *status == '+';
-      
+
       for (;;)
 	{
 	  int digit = *status++ - '0';
@@ -533,7 +540,7 @@ rmt_open__ (const char *path, int open_mode, int bias, const char *remote_shell)
 int
 rmt_close__ (int handle)
 {
-  int status;
+  long int status;
 
   if (do_command (handle, "C\n") == -1)
     return -1;
@@ -544,26 +551,27 @@ rmt_close__ (int handle)
 }
 
 /* Read up to LENGTH bytes into BUFFER from remote tape connection HANDLE.
-   Return the number of bytes read on success, -1 on error.  */
-ssize_t
+   Return the number of bytes read on success, SAFE_READ_ERROR on error.  */
+size_t
 rmt_read__ (int handle, char *buffer, size_t length)
 {
   char command_buffer[COMMAND_BUFFER_SIZE];
-  ssize_t status, rlen;
+  size_t status;
+  size_t rlen;
   size_t counter;
 
   sprintf (command_buffer, "R%lu\n", (unsigned long) length);
   if (do_command (handle, command_buffer) == -1
-      || (status = get_status (handle)) == -1)
-    return -1;
+      || (status = get_status (handle)) == SAFE_READ_ERROR)
+    return SAFE_READ_ERROR;
 
   for (counter = 0; counter < status; counter += rlen, buffer += rlen)
     {
       rlen = safe_read (READ_SIDE (handle), buffer, status - counter);
-      if (rlen <= 0)
+      if (rlen == SAFE_READ_ERROR || rlen == 0)
 	{
 	  _rmt_shutdown (handle, EIO);
-	  return -1;
+	  return SAFE_READ_ERROR;
 	}
     }
 
@@ -571,8 +579,8 @@ rmt_read__ (int handle, char *buffer, size_t length)
 }
 
 /* Write LENGTH bytes from BUFFER to remote tape connection HANDLE.
-   Return the number of bytes written on success, -1 on error.  */
-ssize_t
+   Return the number of bytes written.  */
+size_t
 rmt_write__ (int handle, char *buffer, size_t length)
 {
   char command_buffer[COMMAND_BUFFER_SIZE];
@@ -581,18 +589,25 @@ rmt_write__ (int handle, char *buffer, size_t length)
 
   sprintf (command_buffer, "W%lu\n", (unsigned long) length);
   if (do_command (handle, command_buffer) == -1)
-    return -1;
+    return 0;
 
   pipe_handler = signal (SIGPIPE, SIG_IGN);
   written = full_write (WRITE_SIDE (handle), buffer, length);
   signal (SIGPIPE, pipe_handler);
   if (written == length)
-    return get_status (handle);
+    {
+      long int r = get_status (handle);
+      if (r < 0)
+	return 0;
+      if (r == length)
+	return length;
+      written = r;
+    }
 
   /* Write error.  */
 
   _rmt_shutdown (handle, EIO);
-  return -1;
+  return written;
 }
 
 /* Perform an imitation lseek operation on remote tape connection
@@ -648,7 +663,7 @@ rmt_ioctl__ (int handle, int operation, char *argument)
 		       ? - (uintmax_t) ((struct mtop *) argument)->mt_count
 		       : (uintmax_t) ((struct mtop *) argument)->mt_count);
 	char *p = operand_buffer + sizeof operand_buffer;
-	
+
         *--p = 0;
 	do
 	  *--p = '0' + (int) (u % 10);
@@ -671,7 +686,7 @@ rmt_ioctl__ (int handle, int operation, char *argument)
     case MTIOCGET:
       {
 	ssize_t status;
-	ssize_t counter;
+	size_t counter;
 
 	/* Grab the status and read it directly into the structure.  This
 	   assumes that the status buffer is not padded and that 2 shorts
@@ -686,7 +701,7 @@ rmt_ioctl__ (int handle, int operation, char *argument)
 	for (; status > 0; status -= counter, argument += counter)
 	  {
 	    counter = safe_read (READ_SIDE (handle), argument, status);
-	    if (counter <= 0)
+	    if (counter == SAFE_READ_ERROR || counter == 0)
 	      {
 		_rmt_shutdown (handle, EIO);
 		return -1;

+ 71 - 70
src/sparse.c

@@ -1,6 +1,6 @@
-/* Functions for dealing with sparse files 
+/* Functions for dealing with sparse files
 
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
@@ -39,8 +39,8 @@ struct tar_sparse_optab
   bool (*decode_header) (struct tar_sparse_file *);
   bool (*scan_block) (struct tar_sparse_file *, enum sparse_scan_state,
 		      void *);
-  bool (*dump_region) (struct tar_sparse_file *, size_t index);
-  bool (*extract_region) (struct tar_sparse_file *, size_t index);
+  bool (*dump_region) (struct tar_sparse_file *, size_t);
+  bool (*extract_region) (struct tar_sparse_file *, size_t);
 };
 
 struct tar_sparse_file
@@ -89,18 +89,18 @@ tar_sparse_scan (struct tar_sparse_file *file, enum sparse_scan_state state,
 }
 
 static bool
-tar_sparse_dump_region (struct tar_sparse_file *file, size_t index)
+tar_sparse_dump_region (struct tar_sparse_file *file, size_t i)
 {
   if (file->optab->dump_region)
-    return file->optab->dump_region (file, index);
+    return file->optab->dump_region (file, i);
   return false;
 }
 
 static bool
-tar_sparse_extract_region (struct tar_sparse_file *file, size_t index)
+tar_sparse_extract_region (struct tar_sparse_file *file, size_t i)
 {
   if (file->optab->extract_region)
-    return file->optab->extract_region (file, index);
+    return file->optab->extract_region (file, i);
   return false;
 }
 
@@ -191,11 +191,12 @@ sparse_scan_file (struct tar_sparse_file *file)
 
   file->stat_info->sparse_map_size = 0;
   file->stat_info->archive_file_size = 0;
-  
+
   if (!tar_sparse_scan (file, scan_begin, NULL))
     return false;
 
-  while ((count = safe_read (file->fd, buffer, sizeof buffer)) > 0)
+  while ((count = safe_read (file->fd, buffer, sizeof buffer)) != 0
+	 && count != SAFE_READ_ERROR)
     {
       /* Analize the block */
       if (zero_block_p (buffer, count))
@@ -217,11 +218,11 @@ sparse_scan_file (struct tar_sparse_file *file)
 	  if (!tar_sparse_scan (file, scan_block, buffer))
 	    return false;
 	}
-      
+
       offset += count;
       clear_block (buffer);
     }
-      
+
   if (sp.numbytes == 0)
     sp.offset = offset;
 
@@ -255,7 +256,7 @@ sparse_select_optab (struct tar_sparse_file *file)
     case STAR_FORMAT:
       file->optab = &star_optab;
       break;
-	
+
     default:
       return false;
     }
@@ -263,28 +264,28 @@ sparse_select_optab (struct tar_sparse_file *file)
 }
 
 static bool
-sparse_dump_region (struct tar_sparse_file *file, size_t index)
+sparse_dump_region (struct tar_sparse_file *file, size_t i)
 {
   union block *blk;
-  off_t bytes_left = file->stat_info->sparse_map[index].numbytes;
-  
-  if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
+  off_t bytes_left = file->stat_info->sparse_map[i].numbytes;
+
+  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
 		       SEEK_SET))
     return false;
 
   while (bytes_left > 0)
     {
       size_t bufsize = (bytes_left > BLOCKSIZE) ? BLOCKSIZE : bytes_left;
-      off_t bytes_read;
-      
+      size_t bytes_read;
+
       blk = find_next_block ();
       memset (blk->buffer, 0, BLOCKSIZE);
       bytes_read = safe_read (file->fd, blk->buffer, bufsize);
-      if (bytes_read < 0)
+      if (bytes_read == SAFE_READ_ERROR)
 	{
           read_diag_details (file->stat_info->orig_file_name,
-	                     file->stat_info->sparse_map[index].offset
-	                         + file->stat_info->sparse_map[index].numbytes
+	                     file->stat_info->sparse_map[i].offset
+	                         + file->stat_info->sparse_map[i].numbytes
 	                         - bytes_left,
 	             bufsize);
 	  return false;
@@ -299,15 +300,15 @@ sparse_dump_region (struct tar_sparse_file *file, size_t index)
 }
 
 static bool
-sparse_extract_region (struct tar_sparse_file *file, size_t index)
+sparse_extract_region (struct tar_sparse_file *file, size_t i)
 {
   size_t write_size;
-  
-  if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
+
+  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
 		       SEEK_SET))
     return false;
 
-  write_size = file->stat_info->sparse_map[index].numbytes;
+  write_size = file->stat_info->sparse_map[i].numbytes;
 
   if (write_size == 0)
     {
@@ -343,12 +344,12 @@ sparse_extract_region (struct tar_sparse_file *file, size_t index)
 
 /* Interface functions */
 enum dump_status
-sparse_dump_file (int fd, struct tar_stat_info *stat)
+sparse_dump_file (int fd, struct tar_stat_info *st)
 {
   bool rc;
   struct tar_sparse_file file;
 
-  file.stat_info = stat;
+  file.stat_info = st;
   file.fd = fd;
 
   if (!sparse_select_optab (&file)
@@ -375,43 +376,43 @@ sparse_dump_file (int fd, struct tar_stat_info *stat)
 
 /* Returns true if the file represented by stat is a sparse one */
 bool
-sparse_file_p (struct tar_stat_info *stat)
+sparse_file_p (struct tar_stat_info *st)
 {
-  return (ST_NBLOCKS (stat->stat)
-	  < (stat->stat.st_size / ST_NBLOCKSIZE
-	     + (stat->stat.st_size % ST_NBLOCKSIZE != 0)));
+  return (ST_NBLOCKS (st->stat)
+	  < (st->stat.st_size / ST_NBLOCKSIZE
+	     + (st->stat.st_size % ST_NBLOCKSIZE != 0)));
 }
 
 bool
-sparse_member_p (struct tar_stat_info *stat)
+sparse_member_p (struct tar_stat_info *st)
 {
   struct tar_sparse_file file;
-  
+
   if (!sparse_select_optab (&file))
     return false;
-  file.stat_info = stat;
+  file.stat_info = st;
   return tar_sparse_member_p (&file);
 }
 
 bool
-sparse_fixup_header (struct tar_stat_info *stat)
+sparse_fixup_header (struct tar_stat_info *st)
 {
   struct tar_sparse_file file;
-  
+
   if (!sparse_select_optab (&file))
     return false;
-  file.stat_info = stat;
+  file.stat_info = st;
   return tar_sparse_fixup_header (&file);
 }
 
 enum dump_status
-sparse_extract_file (int fd, struct tar_stat_info *stat, off_t *size)
+sparse_extract_file (int fd, struct tar_stat_info *st, off_t *size)
 {
   bool rc = true;
   struct tar_sparse_file file;
   size_t i;
-  
-  file.stat_info = stat;
+
+  file.stat_info = st;
   file.fd = fd;
 
   if (!sparse_select_optab (&file)
@@ -426,12 +427,12 @@ sparse_extract_file (int fd, struct tar_stat_info *stat, off_t *size)
 }
 
 enum dump_status
-sparse_skip_file (struct tar_stat_info *stat)
+sparse_skip_file (struct tar_stat_info *st)
 {
   bool rc = true;
   struct tar_sparse_file file;
-  
-  file.stat_info = stat;
+
+  file.stat_info = st;
   file.fd = -1;
 
   if (!sparse_select_optab (&file)
@@ -445,23 +446,23 @@ sparse_skip_file (struct tar_stat_info *stat)
 
 
 static char diff_buffer[BLOCKSIZE];
-		   
+
 static bool
 check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
 {
   if (!lseek_or_error (file, beg, SEEK_SET))
     return false;
-  
+
   while (beg < end)
     {
       size_t bytes_read;
       size_t rdsize = end - beg;
-      
+
       if (rdsize > BLOCKSIZE)
 	rdsize = BLOCKSIZE;
       clear_block (diff_buffer);
       bytes_read = safe_read (file->fd, diff_buffer, rdsize);
-      if (bytes_read < 0)
+      if (bytes_read == SAFE_READ_ERROR)
 	{
           read_diag_details (file->stat_info->orig_file_name,
 	                     beg,
@@ -481,19 +482,19 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
 }
 
 static bool
-check_data_region (struct tar_sparse_file *file, size_t index)
+check_data_region (struct tar_sparse_file *file, size_t i)
 {
   size_t size_left;
-  
-  if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
+
+  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
 		       SEEK_SET))
     return false;
-  size_left = file->stat_info->sparse_map[index].numbytes;
+  size_left = file->stat_info->sparse_map[i].numbytes;
   while (size_left > 0)
     {
       size_t bytes_read;
       size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;
-      
+
       union block *blk = find_next_block ();
       if (!blk)
 	{
@@ -502,11 +503,11 @@ check_data_region (struct tar_sparse_file *file, size_t index)
 	}
       set_next_block_after (blk);
       bytes_read = safe_read (file->fd, diff_buffer, rdsize);
-      if (bytes_read < 0)
+      if (bytes_read == SAFE_READ_ERROR)
 	{
           read_diag_details (file->stat_info->orig_file_name,
-			     file->stat_info->sparse_map[index].offset
-	                         + file->stat_info->sparse_map[index].numbytes
+			     file->stat_info->sparse_map[i].offset
+	                         + file->stat_info->sparse_map[i].numbytes
 			         - size_left,
 			     rdsize);
 	  return false;
@@ -523,14 +524,14 @@ check_data_region (struct tar_sparse_file *file, size_t index)
 }
 
 bool
-sparse_diff_file (int fd, struct tar_stat_info *stat)
+sparse_diff_file (int fd, struct tar_stat_info *st)
 {
   bool rc = true;
   struct tar_sparse_file file;
   size_t i;
   off_t offset = 0;
-  
-  file.stat_info = stat;
+
+  file.stat_info = st;
   file.fd = fd;
 
   if (!sparse_select_optab (&file)
@@ -554,14 +555,14 @@ sparse_diff_file (int fd, struct tar_stat_info *stat)
   return rc;
 }
 
-     
+
 /* Old GNU Format. The sparse file information is stored in the
    oldgnu_header in the following manner:
 
    The header is marked with type 'S'. Its `size' field contains
    the cumulative size of all non-empty blocks of the file. The
    actual file size is stored in `realsize' member of oldgnu_header.
-   
+
    The map of the file is stored in a list of `struct sparse'.
    Each struct contains offset to the block of data and its
    size (both as octal numbers). The first file header contains
@@ -581,13 +582,13 @@ enum oldgnu_add_status
   };
 
 static bool
-oldgnu_sparse_member_p (struct tar_sparse_file *file_unused)
+oldgnu_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
 {
   return current_header->header.typeflag == GNUTYPE_SPARSE;
 }
 
 /* Add a sparse item to the sparse file and its obstack */
-static enum oldgnu_add_status 
+static enum oldgnu_add_status
 oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
 {
   struct sp_array sp;
@@ -624,7 +625,7 @@ oldgnu_get_sparse_info (struct tar_sparse_file *file)
   union block *h = current_header;
   int ext_p;
   static enum oldgnu_add_status rc;
-  
+
   file->stat_info->sparse_map_size = 0;
   for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
     {
@@ -676,7 +677,7 @@ oldgnu_dump_header (struct tar_sparse_file *file)
   off_t block_ordinal = current_block_ordinal ();
   union block *blk;
   size_t i;
-    
+
   blk = start_header (file->stat_info);
   blk->header.typeflag = GNUTYPE_SPARSE;
   if (file->stat_info->sparse_map_avail > SPARSES_IN_OLDGNU_HEADER)
@@ -693,7 +694,7 @@ oldgnu_dump_header (struct tar_sparse_file *file)
 			    SPARSES_IN_OLDGNU_HEADER);
   blk->oldgnu_header.isextended = i < file->stat_info->sparse_map_avail;
   finish_header (file->stat_info, blk, block_ordinal);
-  
+
   while (i < file->stat_info->sparse_map_avail)
     {
       blk = find_next_block ();
@@ -726,7 +727,7 @@ static struct tar_sparse_optab oldgnu_optab = {
 /* Star */
 
 static bool
-star_sparse_member_p (struct tar_sparse_file *file_unused)
+star_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
 {
   return current_header->header.typeflag == GNUTYPE_SPARSE;
 }
@@ -750,7 +751,7 @@ star_get_sparse_info (struct tar_sparse_file *file)
   union block *h = current_header;
   int ext_p;
   static enum oldgnu_add_status rc;
-  
+
   file->stat_info->sparse_map_size = 0;
 
   if (h->star_in_header.prefix[0] == '\0'
@@ -799,7 +800,7 @@ static struct tar_sparse_optab star_optab = {
   star_fixup_header,
   star_get_sparse_info,
   NULL,  /* No scan_block function */
-  NULL, /* No dump region function */ 
+  NULL, /* No dump region function */
   sparse_extract_region,
 };
 
@@ -836,7 +837,7 @@ pax_dump_header (struct tar_sparse_file *file)
       xheader_store ("GNU.sparse.offset", file->stat_info, &i);
       xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
     }
-  
+
   blk = start_header (file->stat_info);
   /* Store the effective (shrunken) file size */
   OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);

+ 42 - 78
src/system.c

@@ -1,6 +1,6 @@
 /* System-dependent calls for tar.
 
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
@@ -23,46 +23,33 @@
 #include <signal.h>
 
 void
-sys_stat_nanoseconds(struct tar_stat_info *stat)
+sys_stat_nanoseconds (struct tar_stat_info *st)
 {
 #if defined(HAVE_STRUCT_STAT_ST_SPARE1)
-  stat->atime_nsec = stat->stat.st_spare1 * 1000;
-  stat->mtime_nsec = stat->stat.st_spare2 * 1000;
-  stat->ctime_nsec = stat->stat.st_spare3 * 1000;
+  st->atime_nsec = st->stat.st_spare1 * 1000;
+  st->mtime_nsec = st->stat.st_spare2 * 1000;
+  st->ctime_nsec = st->stat.st_spare3 * 1000;
 #elif defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
-  stat->atime_nsec = stat->stat.st_atim.tv_nsec;
-  stat->mtime_nsec = stat->stat.st_mtim.tv_nsec;
-  stat->ctime_nsec = stat->stat.st_ctim.tv_nsec;
+  st->atime_nsec = st->stat.st_atim.tv_nsec;
+  st->mtime_nsec = st->stat.st_mtim.tv_nsec;
+  st->ctime_nsec = st->stat.st_ctim.tv_nsec;
 #elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
-  stat->atime_nsec = stat->stat.st_atimespec.tv_nsec;
-  stat->mtime_nsec = stat->stat.st_mtimespec.tv_nsec;
-  stat->ctime_nsec = stat->stat.st_ctimespec.tv_nsec;
+  st->atime_nsec = st->stat.st_atimespec.tv_nsec;
+  st->mtime_nsec = st->stat.st_mtimespec.tv_nsec;
+  st->ctime_nsec = st->stat.st_ctimespec.tv_nsec;
 #elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
-  stat->atime_nsec = stat->stat.st_atimensec;
-  stat->mtime_nsec = stat->stat.st_mtimensec;
-  stat->ctime_nsec = stat->stat.st_ctimensec;
+  st->atime_nsec = st->stat.st_atimensec;
+  st->mtime_nsec = st->stat.st_mtimensec;
+  st->ctime_nsec = st->stat.st_ctimensec;
 #else
-  stat->atime_nsec  = stat->mtime_nsec = stat->ctime_nsec = 0;
-#endif
-}
-
-int
-sys_utimes(char *file_name, struct timeval tvp[3])
-{
-#ifdef HAVE_UTIMES
-  return utimes (file_name, tvp);
-#else
-  struct utimbuf utimbuf;
-  utimbuf.actime = tvp[0].tv_sec;
-  utimbuf.modtime = tvp[1].tv_sec;
-  return utime (file_name, &utimbuf);
+  st->atime_nsec  = st->mtime_nsec = st->ctime_nsec = 0;
 #endif
 }
 
 #if MSDOS
 
 bool
-sys_get_archive_stat ()
+sys_get_archive_stat (void)
 {
   return 0;
 }
@@ -74,12 +61,12 @@ sys_file_is_archive (struct tar_stat_info *p)
 }
 
 void
-sys_save_archive_dev_ino ()
+sys_save_archive_dev_ino (void)
 {
 }
 
 void
-sys_detect_dev_null_output ()
+sys_detect_dev_null_output (void)
 {
   static char const dev_null[] = "nul";
 
@@ -88,7 +75,7 @@ sys_detect_dev_null_output ()
 }
 
 void
-sys_drain_input_pipe ()
+sys_drain_input_pipe (void)
 {
 }
 
@@ -98,7 +85,7 @@ sys_wait_for_child (pid_t child_pid)
 }
 
 void
-sys_spawn_shell ()
+sys_spawn_shell (void)
 {
   spawnl (P_WAIT, getenv ("COMSPEC"), "-", 0);
 }
@@ -132,25 +119,14 @@ sys_truncate (int fd)
 }
 
 void
-sys_reset_uid_gid ()
+sys_reset_uid_gid (void)
 {
 }
 
-ssize_t
+size_t
 sys_write_archive_buffer (void)
 {
-  ssize_t status;
-  ssize_t written = 0;
-
-  while (0 <= (status = full_write (archive, record_start->buffer + written,
-				    record_size - written)))
-    {
-      written += status;
-      if (written == record_size)
-        break;
-    }
-
-  return written ? written : status;
+  return full_write (archive, record_start->buffer, record_size);
 }
 
 /* Set ARCHIVE for writing, then compressing an archive.  */
@@ -174,11 +150,11 @@ extern union block *record_start; /* FIXME */
 static struct stat archive_stat; /* stat block for archive file */
 
 bool
-sys_get_archive_stat ()
+sys_get_archive_stat (void)
 {
   return fstat (archive, &archive_stat) == 0;
 }
-    
+
 bool
 sys_file_is_archive (struct tar_stat_info *p)
 {
@@ -187,7 +163,7 @@ sys_file_is_archive (struct tar_stat_info *p)
 
 /* Save archive file inode and device numbers */
 void
-sys_save_archive_dev_ino ()
+sys_save_archive_dev_ino (void)
 {
   if (!_isrmt (archive) && S_ISREG (archive_stat.st_mode))
     {
@@ -200,7 +176,7 @@ sys_save_archive_dev_ino ()
 
 /* Detect if outputting to "/dev/null".  */
 void
-sys_detect_dev_null_output ()
+sys_detect_dev_null_output (void)
 {
   static char const dev_null[] = "/dev/null";
   struct stat dev_null_stat;
@@ -219,12 +195,15 @@ sys_detect_dev_null_output ()
    work to do, we might have to revise this area in such time.  */
 
 void
-sys_drain_input_pipe ()
+sys_drain_input_pipe (void)
 {
+  size_t r;
+
   if (access_mode == ACCESS_READ
       && ! _isrmt (archive)
       && (S_ISFIFO (archive_stat.st_mode) || S_ISSOCK (archive_stat.st_mode)))
-    while (rmtread (archive, record_start->buffer, record_size) > 0)
+    while ((r = rmtread (archive, record_start->buffer, record_size)) != 0
+	   && r != SAFE_READ_ERROR)
       continue;
 }
 
@@ -252,7 +231,7 @@ sys_wait_for_child (pid_t child_pid)
 }
 
 void
-sys_spawn_shell ()
+sys_spawn_shell (void)
 {
   pid_t child;
   const char *shell = getenv ("SHELL");
@@ -303,7 +282,7 @@ sys_truncate (int fd)
 }
 
 void
-sys_reset_uid_gid ()
+sys_reset_uid_gid (void)
 {
   setuid (getuid ());
   setgid (getgid ());
@@ -322,24 +301,10 @@ is_regular_file (const char *name)
     return errno == ENOENT;
 }
 
-ssize_t
+size_t
 sys_write_archive_buffer (void)
 {
-  ssize_t status;
-  ssize_t written = 0;
-
-  while (0 <= (status = rmtwrite (archive, record_start->buffer + written,
-				  record_size - written)))
-    {
-      written += status;
-      if (written == record_size
-	  || _isrmt (archive)
-	  || ! (S_ISFIFO (archive_stat.st_mode)
-		|| S_ISSOCK (archive_stat.st_mode)))
-	break;
-    }
-
-  return written ? written : status;
+  return rmtwrite (archive, record_start->buffer, record_size);
 }
 
 #define	PREAD 0			/* read file descriptor from pipe() */
@@ -471,7 +436,7 @@ sys_child_open_for_compress (void)
 
   while (1)
     {
-      ssize_t status = 0;
+      size_t status = 0;
       char *cursor;
       size_t length;
 
@@ -484,13 +449,12 @@ sys_child_open_for_compress (void)
 	  size_t size = record_size - length;
 
 	  status = safe_read (STDIN_FILENO, cursor, size);
-	  if (status <= 0)
+	  if (status == SAFE_READ_ERROR)
+	    read_fatal (use_compress_program_option);
+	  if (status == 0)
 	    break;
 	}
 
-      if (status < 0)
-	read_fatal (use_compress_program_option);
-
       /* Copy the record.  */
 
       if (status == 0)
@@ -628,13 +592,13 @@ sys_child_open_for_uncompress (void)
       char *cursor;
       size_t maximum;
       size_t count;
-      ssize_t status;
+      size_t status;
 
       clear_read_error_count ();
 
     error_loop:
       status = rmtread (archive, record_start->buffer, record_size);
-      if (status < 0)
+      if (status == SAFE_READ_ERROR)
 	{
 	  archive_read_error ();
 	  goto error_loop;

+ 34 - 28
src/tar.c

@@ -1,7 +1,7 @@
 /* A tar (tape archiver) program.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
-   2001, 2003 Free Software Foundation, Inc.
+   2001, 2003, 2004 Free Software Foundation, Inc.
 
    Written by John Gilmore, starting 1985-08-25.
 
@@ -335,7 +335,7 @@ static struct option long_options[] =
   {"volno-file", required_argument, 0, VOLNO_FILE_OPTION},
   {"wildcards", no_argument, 0, WILDCARDS_OPTION},
   {"wildcards-match-slash", no_argument, 0, WILDCARDS_MATCH_SLASH_OPTION},
-  
+
   {0, 0, 0, 0}
 };
 
@@ -519,7 +519,7 @@ Compatibility options:\n\
   -o                                 when creating, same as --old-archive\n\
                                      when extracting, same as --no-same-owner\n"),
              stdout);
-      
+
       fputs (_("\
 \n\
 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
@@ -595,7 +595,8 @@ decode_options (int argc, char **argv)
   blocking_factor = DEFAULT_BLOCKING;
   record_size = DEFAULT_BLOCKING * BLOCKSIZE;
   excluded = new_exclude ();
-  newer_mtime_option = TYPE_MINIMUM (time_t);
+  newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t);
+  newer_mtime_option.tv_nsec = -1;
   recursion_option = FNM_LEADING_DIR;
 
   owner_option = -1;
@@ -823,7 +824,7 @@ decode_options (int argc, char **argv)
 	/* Fall through.  */
 
       case NEWER_MTIME_OPTION:
-	if (newer_mtime_option != TYPE_MINIMUM (time_t))
+	if (NEWER_OPTION_INITIALIZED (newer_mtime_option))
 	  USAGE_ERROR ((0, 0, _("More than one threshold date")));
 
 	if (FILESYSTEM_PREFIX_LEN (optarg) != 0
@@ -836,14 +837,17 @@ decode_options (int argc, char **argv)
 		stat_error (optarg);
 		USAGE_ERROR ((0, 0, _("Date file not found")));
 	      }
-	    newer_mtime_option = st.st_mtime;
+	    newer_mtime_option.tv_sec = st.st_mtime;
+	    newer_mtime_option.tv_nsec = TIMESPEC_NS (st.st_mtim);
 	  }
 	else
 	  {
-	    newer_mtime_option = get_date (optarg, 0);
-	    if (newer_mtime_option == (time_t) -1)
-	      WARN ((0, 0, _("Substituting %s for unknown date format %s"),
-		     tartime (newer_mtime_option), quote (optarg)));
+	    if (! get_date (&newer_mtime_option, optarg, NULL))
+	      {
+		WARN ((0, 0, _("Substituting %s for unknown date format %s"),
+		       tartime (newer_mtime_option.tv_sec), quote (optarg)));
+		newer_mtime_option.tv_nsec = 0;
+	      }
 	    else
 	      textual_date_option = optarg;
 	  }
@@ -912,7 +916,7 @@ decode_options (int argc, char **argv)
       case UTC_OPTION:
 	utc_option = true;
 	break;
-	
+
       case 'v':
 	verbose_option++;
 	break;
@@ -990,7 +994,7 @@ decode_options (int argc, char **argv)
       case FORMAT_OPTION:
 	set_archive_format (optarg);
 	break;
-	
+
       case INDEX_FILE_OPTION:
 	index_file_name = optarg;
 	break;
@@ -1006,7 +1010,7 @@ decode_options (int argc, char **argv)
       case KEEP_NEWER_FILES_OPTION:
 	old_files_option = KEEP_NEWER_FILES;
 	break;
-	
+
       case GROUP_OPTION:
 	if (! (strlen (optarg) < GNAME_FIELD_SIZE
 	       && gname_to_gid (optarg, &group_option)))
@@ -1072,7 +1076,7 @@ decode_options (int argc, char **argv)
 			    _("Invalid number")));
 	  }
 	break;
-	
+
       case OVERWRITE_OPTION:
 	old_files_option = OVERWRITE_OLD_FILES;
 	break;
@@ -1095,7 +1099,7 @@ decode_options (int argc, char **argv)
 	pax_option++;
 	xheader_set_option (optarg);
 	break;
-			    
+
       case POSIX_OPTION:
 	set_archive_format ("posix");
 	break;
@@ -1148,7 +1152,7 @@ decode_options (int argc, char **argv)
 	  strip_path_elements = u;
 	}
 	break;
-	
+
       case SUFFIX_OPTION:
 	backup_option = true;
 	backup_suffix_string = optarg;
@@ -1157,7 +1161,7 @@ decode_options (int argc, char **argv)
       case TOTALS_OPTION:
 	totals_option = true;
 	break;
-	
+
       case USE_COMPRESS_PROGRAM_OPTION:
 	set_use_compress_program_option (optarg);
 	break;
@@ -1285,7 +1289,7 @@ decode_options (int argc, char **argv)
   if (show_version)
     {
       printf ("tar (%s) %s\n%s\n", PACKAGE_NAME, PACKAGE_VERSION,
-	      "Copyright (C) 2003 Free Software Foundation, Inc.");
+	      "Copyright (C) 2004 Free Software Foundation, Inc.");
       puts (_("\
 This program comes with NO WARRANTY, to the extent permitted by law.\n\
 You may redistribute it under the terms of the GNU General Public License;\n\
@@ -1308,7 +1312,7 @@ see the file named COPYING for details."));
       else
 	archive_format = DEFAULT_ARCHIVE_FORMAT;
     }
-  
+
   if (volume_label_option && subcommand_option == CREATE_SUBCOMMAND)
     assert_format (FORMAT_MASK (OLDGNU_FORMAT)
 		   | FORMAT_MASK (GNU_FORMAT));
@@ -1316,12 +1320,12 @@ see the file named COPYING for details."));
 
   if (incremental_option || multi_volume_option)
     assert_format (FORMAT_MASK (OLDGNU_FORMAT) | FORMAT_MASK (GNU_FORMAT));
-		   
+
   if (sparse_option)
     assert_format (FORMAT_MASK (OLDGNU_FORMAT)
 		   | FORMAT_MASK (GNU_FORMAT)
 		   | FORMAT_MASK (POSIX_FORMAT));
-  
+
   if (occurrence_option)
     {
       if (!input_files && !files_from_option)
@@ -1353,7 +1357,7 @@ see the file named COPYING for details."));
 		  _("Multiple archive files require `-M' option")));
 
   if (listed_incremental_option
-      && newer_mtime_option != TYPE_MINIMUM (time_t))
+      && NEWER_OPTION_INITIALIZED (newer_mtime_option))
     USAGE_ERROR ((0, 0,
 		  _("Cannot combine --listed-incremental with --newer")));
 
@@ -1403,7 +1407,7 @@ see the file named COPYING for details."));
 	  || subcommand_option != DIFF_SUBCOMMAND
 	  || subcommand_option != LIST_SUBCOMMAND))
     USAGE_ERROR ((0, 0, _("--pax-option can be used only on POSIX archives")));
-  
+
   /* If ready to unlink hierarchies, so we are for simpler files.  */
   if (recursive_unlink_option)
     old_files_option = UNLINK_FIRST_OLD_FILES;
@@ -1455,10 +1459,12 @@ see the file named COPYING for details."));
 
   if (verbose_option && textual_date_option)
     {
-      char const *treated_as = tartime (newer_mtime_option);
+      /* FIXME: tartime should support nanoseconds, too, so that this
+	 comparison doesn't complain about lost nanoseconds.  */
+      char const *treated_as = tartime (newer_mtime_option.tv_sec);
       if (strcmp (textual_date_option, treated_as) != 0)
-	WARN ((0, 0, _("Treating date `%s' as %s"),
-	       textual_date_option, treated_as));
+	WARN ((0, 0, _("Treating date `%s' as %s + %ld nanoseconds"),
+	       textual_date_option, treated_as, newer_mtime_option.tv_nsec));
     }
 }
 
@@ -1499,7 +1505,7 @@ main (int argc, char **argv)
   /* Decode options.  */
 
   decode_options (argc, argv);
-  name_init (argc, argv);
+  name_init ();
 
   /* Main command execution.  */
 
@@ -1575,7 +1581,7 @@ tar_stat_init (struct tar_stat_info *st)
 {
   memset (st, 0, sizeof (*st));
 }
-     
+
 void
 tar_stat_destroy (struct tar_stat_info *st)
 {

+ 6 - 6
src/update.c

@@ -1,7 +1,7 @@
 /* Update a tar archive.
 
-   Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
+   2004 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
@@ -33,7 +33,7 @@ extern union block *current_block;
 /* We've hit the end of the old stuff, and its time to start writing new
    stuff to the tape.  This involves seeking back one record and
    re-writing the current record (which has been changed).
-   FIXME: Either eliminate it or move it to common.h. 
+   FIXME: Either eliminate it or move it to common.h.
 */
 bool time_to_start_writing;
 
@@ -66,7 +66,7 @@ append_file (char *path)
 	{
 	  union block *start = find_next_block ();
 	  size_t buffer_size = available_space_after (start);
-	  ssize_t status;
+	  size_t status;
 	  char buf[UINTMAX_STRSIZE_BOUND];
 
 	  if (bytes_left < buffer_size)
@@ -78,7 +78,7 @@ append_file (char *path)
 	    }
 
 	  status = safe_read (handle, start->buffer, buffer_size);
-	  if (status < 0)
+	  if (status == SAFE_READ_ERROR)
 	    read_fatal_details (path, stat_data.st_size - bytes_left,
 				buffer_size);
 	  if (status == 0)
@@ -111,7 +111,7 @@ update_archive (void)
   name_gather ();
   open_archive (ACCESS_UPDATE);
   xheader_write_global ();
-  
+
   while (!found_end)
     {
       enum read_header status = read_header (false);

+ 23 - 33
src/utf8.c

@@ -23,11 +23,13 @@
 # include <iconv.h>
 #endif
 
+#ifdef HAVE_LIBICONV
+
 struct langtab
 {
-  char *lang;        /* Language code */
-  char *terr;        /* Territory code */
-  char *charset;     /* Corresponding charset */
+  char const *lang;        /* Language code */
+  char const *terr;        /* Territory code */
+  char const *charset;     /* Corresponding charset */
 };
 
 /* The list of language codes defined in ISO 639 with the corresponding
@@ -216,22 +218,22 @@ static struct langtab langtab[] = {
   { "zh",    "TW", "big5"},            /* Chinese */
   { "zh",    NULL, "gb2312"},          /* Chinese */
   { "zu",    NULL, NULL},              /* Zulu */
-  { NULL }
+  { NULL,    NULL, NULL}
 };
 
 /* Given the language and (optionally) territory code, return the
    default character set for that language. See notes above. */
 
-const char *
-charset_lookup (char *lang, char *terr)
+static char const *
+charset_lookup (char const *lang, char const *terr)
 {
-  static struct langtab *p;
+  struct langtab const *p;
 
   if (!lang)
     return NULL;
   for (p = langtab; p->lang; p++)
     if (strcasecmp (p->lang, lang) == 0
-	&& (terr == NULL 
+	&& (terr == NULL
 	    || p->terr == NULL
 	    || !strcasecmp (p->terr, terr) == 0))
       return p->charset;
@@ -239,7 +241,7 @@ charset_lookup (char *lang, char *terr)
 }
 
 static const char *
-get_input_charset ()
+get_input_charset (void)
 {
   const char *charset = NULL;
   char *tmp;
@@ -268,30 +270,18 @@ get_input_charset ()
   return charset;
 }
 
+#else /* !defined HAVE_LIBICONV */
 
-
-#ifndef HAVE_LIBICONV
-
-iconv_t
-iconv_open (const char *tocode, const char *fromcode)
-{
-  return (iconv_t)(-1);
-}
+# undef iconv_open
+# define iconv_open(tocode, fromcode) ((iconv_t) -1)
 
-size_t
-iconv (iconv_t cd, ICONV_CONST char **inbuf, size_t *inbytesleft,
-       char **outbuf, size_t *outbytesleft)
-{
-  return 0;
-}
+# undef iconv
+# define iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft) ((size_t) 0)
 
-int
-iconv_close (iconv_t cd)
-{
-  return 0;
-}
+# undef iconv_close
+# define iconv_close(cd) 0
 
-#endif /* !HAVE_LIBICONV */
+#endif /* !defined HAVE_LIBICONV */
 
 
 
@@ -310,11 +300,11 @@ utf8_init (bool to_utf)
     }
   return conv_desc[(int) to_utf];
 }
-		  
+
 bool
-utf8_convert(bool to_utf, const char *input, char **output)
+utf8_convert (bool to_utf, char const *input, char **output)
 {
-  const char *ib;
+  char ICONV_CONST *ib;
   char *ob;
   size_t inlen;
   size_t outlen;
@@ -332,7 +322,7 @@ utf8_convert(bool to_utf, const char *input, char **output)
   inlen = strlen (input) + 1;
   outlen = inlen * MB_LEN_MAX + 1;
   ob = *output = xmalloc (outlen);
-  ib = input;
+  ib = (char ICONV_CONST *) input;
   rc = iconv (cd, &ib, &inlen, &ob, &outlen);
   *ob = 0;
   return rc != -1;

+ 84 - 80
src/xheader.c

@@ -18,6 +18,7 @@
 
 #include "system.h"
 
+#include <fnmatch.h>
 #include <hash.h>
 #include <quotearg.h>
 #include <xstrtol.h>
@@ -30,13 +31,14 @@
 
 #include <fnmatch.h>
 
-bool xheader_protected_pattern_p (const char *pattern);
-bool xheader_protected_keyword_p (const char *keyword);
+static bool xheader_protected_pattern_p (char const *pattern);
+static bool xheader_protected_keyword_p (char const *keyword);
+static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
 
 /* Used by xheader_finish() */
 static void code_string (char const *string, char const *keyword,
 			 struct xheader *xhdr);
-static void extended_header_init ();
+static void extended_header_init (void);
 
 /* Number of global headers written so far. */
 static size_t global_header_count;
@@ -80,7 +82,7 @@ static char *exthdr_name;
 /* Template for the name field of a 'g' type header */
 static char *globexthdr_name;
 
-bool
+static bool
 xheader_keyword_deleted_p (const char *kw)
 {
   struct keyword_list *kp;
@@ -91,7 +93,7 @@ xheader_keyword_deleted_p (const char *kw)
   return false;
 }
 
-bool
+static bool
 xheader_keyword_override_p (const char *keyword)
 {
   struct keyword_list *kp;
@@ -102,7 +104,7 @@ xheader_keyword_override_p (const char *keyword)
   return false;
 }
 
-void
+static void
 xheader_list_append (struct keyword_list **root, char const *kw,
 		     char const *value)
 {
@@ -113,7 +115,7 @@ xheader_list_append (struct keyword_list **root, char const *kw,
   *root = kp;
 }
 
-void
+static void
 xheader_list_destroy (struct keyword_list **root)
 {
   if (root)
@@ -130,15 +132,14 @@ xheader_list_destroy (struct keyword_list **root)
       *root = NULL;
     }
 }
-	  
-  
-void
+
+static void
 xheader_set_single_keyword (char *kw)
 {
   USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet imlemented"), kw));
 }
 
-void
+static void
 xheader_set_keyword_equal (char *kw, char *eq)
 {
   bool global = true;
@@ -157,7 +158,7 @@ xheader_set_keyword_equal (char *kw, char *eq)
 
   for (p = eq + 1; *p && isspace (*p); p++)
     ;
-  
+
   if (strcmp (kw, "delete") == 0)
     {
       if (xheader_protected_pattern_p (p))
@@ -232,11 +233,11 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
   size_t len = strlen (fmt);
   char *q;
   const char *p;
-  char *dirname = NULL;
-  char *basename = NULL;
+  char *dir = NULL;
+  char *base = NULL;
   char pidbuf[64];
   char nbuf[64];
-  
+
   for (p = fmt; *p && (p = strchr (p, '%')); )
     {
       switch (p[1])
@@ -248,25 +249,24 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
 	case 'd':
 	  if (st)
 	    {
-	      dirname = safer_name_suffix (dir_name (st->orig_file_name),
-					   false);
-	      len += strlen (dirname) - 1;
+	      dir = safer_name_suffix (dir_name (st->orig_file_name), false);
+	      len += strlen (dir) - 1;
 	    }
 	  break;
-	      
+
 	case 'f':
 	  if (st)
 	    {
-	      basename = base_name (st->orig_file_name);
-	      len += strlen (basename) - 1;
+	      base = base_name (st->orig_file_name);
+	      len += strlen (base) - 1;
 	    }
 	  break;
-	      
+
 	case 'p':
 	  to_decimal (getpid (), pidbuf, sizeof pidbuf);
 	  len += strlen (pidbuf) - 1;
 	  break;
-	  
+
 	case 'n':
 	  if (allow_n)
 	    {
@@ -277,7 +277,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
 	}
       p++;
     }
-  
+
   buf = xmalloc (len + 1);
   for (q = buf, p = fmt; *p; )
     {
@@ -289,19 +289,19 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
 	      *q++ = *p++;
 	      p++;
 	      break;
-	      
+
 	    case 'd':
-	      if (dirname)
-		q = stpcpy (q, dirname);
+	      if (dir)
+		q = stpcpy (q, dir);
 	      p += 2;
 	      break;
-	      
+
 	    case 'f':
-	      if (basename)
-		q = stpcpy (q, basename);
+	      if (base)
+		q = stpcpy (q, base);
 	      p += 2;
 	      break;
-	      
+
 	    case 'p':
 	      q = stpcpy (q, pidbuf);
 	      p += 2;
@@ -314,7 +314,7 @@ xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
 		  p += 2;
 		}
 	      /* else fall through */
-	      
+
 	    default:
 	      *q++ = *p++;
 	      if (*p)
@@ -343,7 +343,7 @@ xheader_xhdr_name (struct tar_stat_info *st)
 #define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
 
 char *
-xheader_ghdr_name ()
+xheader_ghdr_name (void)
 {
   if (!globexthdr_name)
     {
@@ -366,7 +366,7 @@ xheader_write (char type, char *name, struct xheader *xhdr)
   union block *header;
   size_t size;
   char *p;
-  
+
   size = xhdr->size;
   header = start_private_header (name, size);
   header->header.typeflag = type;
@@ -374,11 +374,11 @@ xheader_write (char type, char *name, struct xheader *xhdr)
   simple_finish_header (header);
 
   p = xhdr->buffer;
-  
+
   do
     {
       size_t len;
-      
+
       header = find_next_block ();
       len = BLOCKSIZE;
       if (len > size)
@@ -392,17 +392,17 @@ xheader_write (char type, char *name, struct xheader *xhdr)
     }
   while (size > 0);
   xheader_destroy (xhdr);
-}  
+}
 
 void
-xheader_write_global ()
+xheader_write_global (void)
 {
   char *name;
   struct keyword_list *kp;
 
   if (!keyword_global_override_list)
     return;
-  
+
   extended_header_init ();
   for (kp = keyword_global_override_list; kp; kp = kp->next)
     code_string (kp->value, kp->pattern, &extended_header);
@@ -444,7 +444,7 @@ locate_handler (char const *keyword)
   return NULL;
 }
 
-bool
+static bool
 xheader_protected_pattern_p (const char *pattern)
 {
   struct xhdr_tab const *p;
@@ -455,7 +455,7 @@ xheader_protected_pattern_p (const char *pattern)
   return false;
 }
 
-bool
+static bool
 xheader_protected_keyword_p (const char *keyword)
 {
   struct xhdr_tab const *p;
@@ -534,7 +534,7 @@ decx (void *data, char const *keyword, char const *value)
   if (xheader_keyword_deleted_p (keyword)
       || xheader_keyword_override_p (keyword))
     return;
-  
+
   t = locate_handler (keyword);
   if (t)
     t->decoder (st, value);
@@ -545,12 +545,12 @@ xheader_decode (struct tar_stat_info *st)
 {
   run_override_list (keyword_global_override_list, st);
   run_override_list (global_header_override_list, st);
-  
+
   if (extended_header.size)
     {
       char *p = extended_header.buffer + BLOCKSIZE;
       char *endp = &extended_header.buffer[extended_header.size-1];
-      
+
       while (p < endp)
 	if (!decode_record (&p, decx, st))
 	  break;
@@ -566,7 +566,7 @@ decg (void *data, char const *keyword, char const *value)
 }
 
 void
-xheader_decode_global ()
+xheader_decode_global (void)
 {
   if (extended_header.size)
     {
@@ -581,7 +581,7 @@ xheader_decode_global ()
 }
 
 static void
-extended_header_init ()
+extended_header_init (void)
 {
   if (!extended_header.stk)
     {
@@ -594,7 +594,7 @@ void
 xheader_store (char const *keyword, struct tar_stat_info const *st, void *data)
 {
   struct xhdr_tab const *t;
-  
+
   if (extended_header.buffer)
     return;
   t = locate_handler (keyword);
@@ -625,7 +625,7 @@ xheader_read (union block *p, size_t size)
 
       if (len > BLOCKSIZE)
 	len = BLOCKSIZE;
-      
+
       memcpy (&extended_header.buffer[j], p->buffer, len);
       set_next_block_after (p);
 
@@ -783,19 +783,22 @@ code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
 }
 
 static void
-dummy_coder (struct tar_stat_info const *st, char const *keyword,
-	     struct xheader *xhdr, void *data)
+dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
+	     char const *keyword __attribute__ ((unused)),
+	     struct xheader *xhdr __attribute__ ((unused)),
+	     void *data __attribute__ ((unused)))
 {
 }
 
 static void
-dummy_decoder (struct tar_stat_info *st, char const *arg)
+dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
+	       char const *arg __attribute__ ((unused)))
 {
 }
 
 static void
 atime_coder (struct tar_stat_info const *st, char const *keyword,
-	     struct xheader *xhdr, void *data)
+	     struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_time (st->stat.st_atime, st->atime_nsec, keyword, xhdr);
 }
@@ -808,7 +811,7 @@ atime_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 gid_coder (struct tar_stat_info const *st, char const *keyword,
-	   struct xheader *xhdr, void *data)
+	   struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_num (st->stat.st_gid, keyword, xhdr);
 }
@@ -823,7 +826,7 @@ gid_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 gname_coder (struct tar_stat_info const *st, char const *keyword,
-	     struct xheader *xhdr, void *data)
+	     struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_string (st->gname, keyword, xhdr);
 }
@@ -836,7 +839,7 @@ gname_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 linkpath_coder (struct tar_stat_info const *st, char const *keyword,
-		struct xheader *xhdr, void *data)
+		struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_string (st->link_name, keyword, xhdr);
 }
@@ -849,7 +852,7 @@ linkpath_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 ctime_coder (struct tar_stat_info const *st, char const *keyword,
-	     struct xheader *xhdr, void *data)
+	     struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_time (st->stat.st_ctime, st->ctime_nsec, keyword, xhdr);
 }
@@ -862,7 +865,7 @@ ctime_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 mtime_coder (struct tar_stat_info const *st, char const *keyword,
-	     struct xheader *xhdr, void *data)
+	     struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_time (st->stat.st_mtime, st->mtime_nsec, keyword, xhdr);
 }
@@ -875,7 +878,7 @@ mtime_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 path_coder (struct tar_stat_info const *st, char const *keyword,
-	    struct xheader *xhdr, void *data)
+	    struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_string (st->file_name, keyword, xhdr);
 }
@@ -890,7 +893,7 @@ path_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 size_coder (struct tar_stat_info const *st, char const *keyword,
-	    struct xheader *xhdr, void *data)
+	    struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_num (st->stat.st_size, keyword, xhdr);
 }
@@ -905,7 +908,7 @@ size_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 uid_coder (struct tar_stat_info const *st, char const *keyword,
-	   struct xheader *xhdr, void *data)
+	   struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_num (st->stat.st_uid, keyword, xhdr);
 }
@@ -920,7 +923,7 @@ uid_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 uname_coder (struct tar_stat_info const *st, char const *keyword,
-	     struct xheader *xhdr, void *data)
+	     struct xheader *xhdr, void *data __attribute__ ((unused)))
 {
   code_string (st->uname, keyword, xhdr);
 }
@@ -948,7 +951,8 @@ sparse_size_decoder (struct tar_stat_info *st, char const *arg)
 
 static void
 sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
-			struct xheader *xhdr, void *data)
+			struct xheader *xhdr,
+			void *data __attribute__ ((unused)))
 {
   code_num (st->sparse_map_avail, keyword, xhdr);
 }
@@ -1007,18 +1011,18 @@ sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg)
 }
 
 struct xhdr_tab const xhdr_tab[] = {
-  { "atime",	atime_coder,	atime_decoder	},
-  { "comment",	dummy_coder,	dummy_decoder	},
-  { "charset",	dummy_coder,	dummy_decoder	},
-  { "ctime",	ctime_coder,	ctime_decoder	},
-  { "gid",	gid_coder,	gid_decoder	},
-  { "gname",	gname_coder,	gname_decoder	},
-  { "linkpath", linkpath_coder, linkpath_decoder},
-  { "mtime",	mtime_coder,	mtime_decoder	},
-  { "path",	path_coder,	path_decoder	},
-  { "size",	size_coder,	size_decoder	},
-  { "uid",	uid_coder,	uid_decoder	},
-  { "uname",	uname_coder,	uname_decoder	},
+  { "atime",	atime_coder,	atime_decoder,	  false },
+  { "comment",	dummy_coder,	dummy_decoder,	  false },
+  { "charset",	dummy_coder,	dummy_decoder,	  false },
+  { "ctime",	ctime_coder,	ctime_decoder,	  false },
+  { "gid",	gid_coder,	gid_decoder,	  false },
+  { "gname",	gname_coder,	gname_decoder,	  false },
+  { "linkpath", linkpath_coder, linkpath_decoder, false },
+  { "mtime",	mtime_coder,	mtime_decoder,	  false },
+  { "path",	path_coder,	path_decoder,	  false },
+  { "size",	size_coder,	size_decoder,	  false },
+  { "uid",	uid_coder,	uid_decoder,	  false },
+  { "uname",	uname_coder,	uname_decoder,	  false },
 
   /* Sparse file handling */
   { "GNU.sparse.size",       sparse_size_coder, sparse_size_decoder, true },
@@ -1034,12 +1038,12 @@ struct xhdr_tab const xhdr_tab[] = {
   /* The next directory entry actually contains the names of files
      that were in the directory at the time the dump was made.
      Supersedes GNUTYPE_DUMPDIR header type.  */
-  { "GNU.dump.name",  dump_name_coder, dump_name_decoder },
-  { "GNU.dump.status", dump_status_coder, dump_status_decoder },
+  { "GNU.dump.name",  dump_name_coder, dump_name_decoder, false },
+  { "GNU.dump.status", dump_status_coder, dump_status_decoder, false },
 
   /* Keeps the tape/volume header. May be present only in the global headers.
      Equivalent to GNUTYPE_VOLHDR.  */
-  { "GNU.volume.header", volume_header_coder, volume_header_decoder },
+  { "GNU.volume.header", volume_header_coder, volume_header_decoder, false },
 
   /* These may be present in a first global header of the archive.
      They provide the same functionality as GNUTYPE_MULTIVOL header.
@@ -1047,9 +1051,9 @@ struct xhdr_tab const xhdr_tab[] = {
      otherwise kept in the size field of a multivolume header.  The
      GNU.volume.offset keeps the offset of the start of this volume,
      otherwise kept in oldgnu_header.offset.  */
-  { "GNU.volume.size", volume_size_coder, volume_size_decoder },
-  { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder },
+  { "GNU.volume.size", volume_size_coder, volume_size_decoder, false },
+  { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, false },
 #endif
 
-  { NULL, NULL, NULL }
+  { NULL, NULL, NULL, false }
 };

+ 3 - 2
tests/genfile.c

@@ -1,6 +1,6 @@
 /* Generate a file containing some preset patterns.
 
-   Copyright (C) 1995, 1996, 1997, 2001, 2003 Free Software
+   Copyright (C) 1995, 1996, 1997, 2001, 2003, 2004 Free Software
    Foundation, Inc.
 
    François Pinard <[email protected]>, 1995.
@@ -54,7 +54,8 @@ static int file_length = 0;
 static enum pattern pattern = DEFAULT_PATTERN;
 
 /* Explain how to use the program, then get out.  */
-void
+static void usage (int) __attribute__ ((noreturn));
+static void
 usage (int status)
 {
   if (status != EXIT_SUCCESS)

+ 21 - 19
tests/mksparse.c

@@ -30,8 +30,10 @@ char *progname;
 char *buffer;
 size_t buffer_size;
 
-void
-die (char *fmt, ...)
+static void die (char const *, ...) __attribute__ ((noreturn,
+						    format (printf, 1, 2)));
+static void
+die (char const *fmt, ...)
 {
   va_list ap;
 
@@ -40,12 +42,13 @@ die (char *fmt, ...)
   vfprintf (stderr, fmt, ap);
   va_end (ap);
   fprintf (stderr, "\n");
+  exit (1);
 }
 
-void
+static void
 mkhole (int fd, off_t displ)
 {
-  if (displ = lseek (fd, displ, SEEK_CUR) == -1)
+  if (lseek (fd, displ, SEEK_CUR) == -1)
     {
       perror ("lseek");
       exit (1);
@@ -53,11 +56,9 @@ mkhole (int fd, off_t displ)
   ftruncate (fd, lseek (fd, 0, SEEK_CUR));
 }
 
-void
+static void
 mksparse (int fd, off_t displ, char *marks)
 {
-  int i;
-
   for (; *marks; marks++)
     {
       memset (buffer, *marks, buffer_size);
@@ -66,7 +67,7 @@ mksparse (int fd, off_t displ, char *marks)
 	  perror ("write");
 	  exit (1);
 	}
-      
+
       if (lseek (fd, displ, SEEK_CUR) == -1)
 	{
 	  perror ("lseek");
@@ -75,14 +76,15 @@ mksparse (int fd, off_t displ, char *marks)
     }
 }
 
-void
-usage ()
+static void usage (void) __attribute__ ((noreturn));
+static void
+usage (void)
 {
   printf ("Usage: mksparse filename blocksize disp letters [disp letters...] [disp]\n");
   exit (1);
 }
 
-int
+static int
 xlat_suffix (off_t *vp, char *p)
 {
   if (p[1])
@@ -92,7 +94,7 @@ xlat_suffix (off_t *vp, char *p)
     case 'g':
     case 'G':
       *vp *= 1024;
-      
+
     case 'm':
     case 'M':
       *vp *= 1024;
@@ -107,7 +109,7 @@ xlat_suffix (off_t *vp, char *p)
     }
   return 0;
 }
-    
+
 int
 main (int argc, char **argv)
 {
@@ -115,20 +117,20 @@ main (int argc, char **argv)
   int fd;
   char *p;
   off_t n;
-  
+
   progname = strrchr (argv[0], '/');
   if (progname)
     progname++;
   else
     progname = argv[0];
-  
+
   if (argc < 4)
     usage ();
 
   fd = open (argv[1], O_CREAT|O_TRUNC|O_RDWR, 0644);
   if (fd < 0)
     die ("cannot open %s", argv[1]);
-  
+
   n = strtoul (argv[2], &p, 0);
   if (n <= 0 || (*p && xlat_suffix (&n, p)))
     die ("Invalid buffer size: %s", argv[2]);
@@ -136,11 +138,11 @@ main (int argc, char **argv)
   buffer = malloc (buffer_size);
   if (!buffer)
     die ("Not enough memory");
-  
+
   for (i = 3; i < argc; i += 2)
     {
       off_t displ;
-      
+
       displ = strtoul (argv[i], &p, 0);
       if (displ < 0 || (*p && xlat_suffix (&displ, p)))
 	die ("Invalid displacement: %s", argv[i]);
@@ -153,7 +155,7 @@ main (int argc, char **argv)
       else
 	mksparse (fd, displ, argv[i+1]);
     }
-      
+
   close(fd);
   return 0;
 }