bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Patches for GNU tar 1.13.25


From: Paul Eggert
Subject: Re: Patches for GNU tar 1.13.25
Date: Sun, 14 Jul 2002 01:59:37 -0700 (PDT)

> From: Bruce Lilly <address@hidden>
> Date: Sat, 13 Jul 2002 10:51:44 -0400
> 
> The attached patch addresses most of the issues
> when compiling GNU tar 1.13.25 on UWIN

Thanks for doing the port.  Which version of UWIN, and which compiler
and library?

> Several issues noted remain unresolved, some others
> (e.g. application of unary minus to unsigned quantities) have not
> even been addressed

I don't understand this point, as unary minus has well-defined
behavior on unsigned quantities in C.

> most of those issues could be avoided by using double throughout for
> large quantities (double has a 64-bit mantissa) rather than
> non-portable and implementation-dependent constructs].

Sorry, I don't understand this point either.  We do need to avoid
unportable constructs.  But portable code cannot assume that double
has a 64-bit mantissa.  On my SPARC host, for example, double has only
a 53-bit fraction.  On x86, double expressions sometimes have a 64-bit
fraction, and sometimes a 53-bit fraction, depending on the vagaries
of one's compiler and runtime system.

> 1. no supplied conversion between uintmax_t and
>    double. Portable and efficient conversion
>    code supplied.

I take it that your compiler does not support conversion from
uintmax_t to double?  If so, we should fix "configure" so that it
detects that problem, and defines uintmax_t to be 'long'.

Can you supply a little test program that illustrates the compiler
problem?  For example what happens if you compile and run the
following little program?  It should output "(double)
9223372036854775808 == 9223372036854775808" on any machine with a
radix that is a power of 2.

  #include <inttypes.h>

  #define verify(name, assertion) struct name { char a[(assertion) ? 1 : -1]; }
  verify (convert_uintmax_t_to_double,
          (double) (uintmax_t) 9223372036854775808 == 9223372036854775808.0);
  verify (convert_double_to_uintmax_t,
          (uintmax_t) 9223372036854775808.0 == 9223372036854775808);

  #include <stdio.h>

  uintmax_t u = 9223372036854775808;

  int main (void)
  {
    double d = u;
    printf ("(double) 9223372036854775808 == %.20g\n", d);
    return 0;
  }

> 2. getdate.[cy] needs to declare mktime if the
>    replacement function is used.  extern
>    declaration should be harmless even if the
>    system mktime is used.

I worry that some hosts do funky things with mktime defines in <time.h>.
How about this patch instead of the one you supplied?

--- getdate.y   2002/01/16 22:43:41     1.28
+++ getdate.y   2002/07/14 03:25:09
@@ -27,9 +27,14 @@
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
-# ifdef HAVE_ALLOCA_H
-#  include <alloca.h>
-# endif
+#endif
+
+#ifdef mktime
+# define MKTIME_IS_REPLACED 1
+#endif
+
+#if HAVE_ALLOCA_H
+# include <alloca.h>
 #endif
 
 /* Since the code of getdate.y is not included in the Emacs executable
@@ -455,7 +460,7 @@ struct tm *gmtime ();
 #ifndef localtime
 struct tm *localtime ();
 #endif
-#ifndef mktime
+#if ! defined mktime || MKTIME_IS_REPLACED
 time_t mktime ();
 #endif


> 3. do-nothing code in human.c #ifdef'ed out.

But it's not do-nothing code.  Here are some details:

> +    b) does nothing useful (see comments below)
> + */
>     if (inexact_style != human_round_to_even && value < (uintmax_t) -1)
>       {
> !       uintmax_t u = value;  /* N.B. u == value (unconditionally) */

u might not equal value.  value is of type double, so it might not be
an integer, and it might be out of range for uintmax_t.  So it is
possible that (u != value) == 1.  (It is also possible that u does not
equal value, but (u != value) == 0, due to the vagaries of C
arithmetic; but that is a different story.)

> +    Most of the code in this file needs substantial revision.

The revision for GiB etc. has already been done; see
<http://savannah.gnu.org/cgi-bin/viewcvs/gnulib/gnulib/lib/human.c>.
This should appear in the next version of tar.


> 4. inconsistent placement of const qualifiers
>    made more consistent.

This sort of patch shouldn't be needed.  For example, 'char const' is
equivalent to 'const char' on all Standard C compilers.  If you have a
compiler that doesn't support 'const' properly, then 'configure'
should arrange for '#define const /**/' to appear in config.h.  If
config.h is incorrect, let's fix that bug rather than munge the code.


> 5. non-portable tests which assume that size_t
>    is signed replaced by portable tests.

I don't understand this point.  size_t is guaranteed to be unsigned,
and the code assumes this.  Is size_t signed on your host?


> 6. another case of the iconv "bug" accounted for.
> *** lib/unicodeio.c.orig      Tue Sep 25 18:52:20 2001
> --- lib/unicodeio.c   Tue Jul 02 21:14:16 2002
> ***************
> *** 209,215 ****
>   
>         /* Avoid glibc-2.1 bug and Solaris 2.7 bug.  */
>   # if defined _LIBICONV_VERSION \
> !     || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun)
>   
>         /* Get back to the initial shift state.  */
>         res = iconv (utf8_to_local, NULL, NULL, &outptr, &outbytesleft);
> --- 209,215 ----
>   
>         /* Avoid glibc-2.1 bug and Solaris 2.7 bug.  */
>   # if defined _LIBICONV_VERSION \
> !     || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun 
> || defined _UWIN)
>   
>         /* Get back to the initial shift state.  */
>         res = iconv (utf8_to_local, NULL, NULL, &outptr, &outbytesleft);

Doesn't UWIN use glibc?  If not, which library and version does UWIN
use?  If UWIN uses a particular C library, I'd rather have the ifdef
depend on that rather than on the more-generic _UWIN symbol.
(Presumably the bug will be fixed at some point.)


> 7. test for O_ECL vs. O_TRUNC for file creation
>    during extraction corrected.
> *** src/extract.c.orig        Mon Sep 24 14:55:17 2001
> --- src/extract.c     Sat Jul 13 08:13:17 2002
> ***************
> *** 766,772 ****
>   
>       again_file:
>         openflag = (O_WRONLY | O_BINARY | O_CREAT
> !               | (old_files_option == OVERWRITE_OLD_FILES
>                    ? O_TRUNC
>                    : O_EXCL));
>         mode = current_stat.st_mode & MODE_RWX & ~ current_umask;
> --- 766,772 ----
>   
>       again_file:
>         openflag = (O_WRONLY | O_BINARY | O_CREAT
> !               | (old_files_option != KEEP_OLD_FILES
>                    ? O_TRUNC
>                    : O_EXCL));
>         mode = current_stat.st_mode & MODE_RWX & ~ current_umask;

I don't see the bug here.  For example, if old_files_option ==
DEFAULT_OLD_FILES, the code should use O_EXCL, because tar does not
want to overwrite existing files in that case.


> *** lib/exclude.h.orig        Sun Aug 26 19:07:15 2001
> --- lib/exclude.h     Tue Jul 02 14:13:28 2002
> ***************
> *** 30,43 ****
>   
>   /* Patterns must match the start of file names, instead of matching
>      anywhere after a '/'.  */
> ! #define EXCLUDE_ANCHORED (1 << 5)
>   
>   /* Include instead of exclude.  */
> ! #define EXCLUDE_INCLUDE (1 << 6)
>   
>   /* '?', '*', '[', and '\\' are special in patterns.  Without this
>      option, these characters are ordinary and fnmatch is not used.  */
> ! #define EXCLUDE_WILDCARDS (1 << 7)
>   
>   struct exclude;
>   
> --- 30,43 ----
>   
>   /* Patterns must match the start of file names, instead of matching
>      anywhere after a '/'.  */
> ! #define EXCLUDE_ANCHORED (1 << 7)
>   
>   /* Include instead of exclude.  */
> ! #define EXCLUDE_INCLUDE (1 << 8)
>   
>   /* '?', '*', '[', and '\\' are special in patterns.  Without this
>      option, these characters are ordinary and fnmatch is not used.  */
> ! #define EXCLUDE_WILDCARDS (1 << 9)
>   
>   struct exclude;
>   

Why was the above patch needed?  It doesn't seem to match any of your
comments.


> *** src/create.c.orig Wed Aug 29 17:21:02 2001
> --- src/create.c      Tue Jul 02 20:25:17 2002
> ***************
> *** 1108,1114 ****
>          (entrylen = strlen (entry)) != 0;
>          entry += entrylen + 1)
>       {
> !       if (buflen <= len + entrylen)
>           {
>             buflen = len + entrylen;
>             namebuf = xrealloc (namebuf, buflen + 1);
> --- 1108,1114 ----
>          (entrylen = strlen (entry)) != 0;
>          entry += entrylen + 1)
>       {
> !       if (buflen < len + entrylen)
>           {
>             buflen = len + entrylen;
>             namebuf = xrealloc (namebuf, buflen + 1);

This patch seems incorrect to me.  Surely it can cause a buffer
overflow if buflen == len + entrylen, because the buffer needs to be
enlarged in that case.



> From: Bruce Lilly <address@hidden>
> Date: Sat, 13 Jul 2002 12:05:09 -0400
> 
> The following supplementary patch may be required on some systems:
> *** lib/savedir.c.orig    Wed Jul  3 01:34:55 2002
> --- lib/savedir.c       Sat Jul 13 11:56:14 2002
> ***************
> *** 60,65 ****
> --- 60,69 ----
>    # define NULL 0
>    #endif
> 
> + #if HAVE_LIMITS_H || _LIBC
> + # include <limits.h>
> + #endif
> +
>    #include "savedir.h"
>    #include "xalloc.h"
> 

Hmm, why?  savedir.c doesn't use anything that limits.h provides.
The "|| _LIBC" shouldn't be needed in any case, as the file
isn't an internal glibc file.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]