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

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

Re: diff 2.8 large file read fails for Tru64 5.1


From: Paul Eggert
Subject: Re: diff 2.8 large file read fails for Tru64 5.1
Date: Mon, 1 Apr 2002 16:13:30 -0800 (PST)

> From: Mike Coleman <address@hidden>
> Date: Mon, 1 Apr 2002 16:05:29 -0600 (CST)
> 
> Under Tru64 5.1 (gcc 3.0.3), it looks like read(2) won't accept a size
> argument greater than 2^31-1 (although the man page implies that this
> should work).

Thanks for the bug report, Mike.  Yes, POSIX requires that this must
work, so it is clearly a Tru64 bug.

> Perhaps diff could use smaller reads in this case or (ugh) retry on an
> initial read failure.

I'd rather not use smaller reads unless we detect the bug, so let's
try the 'ugh' approach instead.  Can you please try this patch on your
Tru64 host?  Thanks.

===================================================================
RCS file: lib/RCS/cmpbuf.c,v
retrieving revision 1.5
diff -pu -r1.5 lib/cmpbuf.c
--- lib/cmpbuf.c        2002/02/28 04:28:07     1.5
+++ lib/cmpbuf.c        2002/04/02 00:05:13
@@ -22,9 +22,7 @@
 #endif
 
 #include <errno.h>
-#if !STDC_HEADERS
- extern int errno;
-#endif
+#include <limits.h>
 
 #include <signal.h>
 #ifndef SA_RESTART
@@ -45,6 +43,9 @@
 #ifndef PTRDIFF_MAX
 # define PTRDIFF_MAX TYPE_MAXIMUM (ptrdiff_t)
 #endif
+#ifndef SIZE_MAX
+# define SIZE_MAX TYPE_MAXIMUM (size_t)
+#endif
 
 #include <sys/types.h>
 #include "cmpbuf.h"
@@ -66,6 +67,9 @@
 # define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
 #endif
 
+#undef MIN
+#define MIN(a, b) ((a) <= (b) ? (a) : (b))
+
 /* Read NBYTES bytes from descriptor FD into BUF.
    Return the number of characters successfully read.
    On error, return SIZE_MAX.
@@ -76,22 +80,32 @@ block_read (int fd, char *buf, size_t nb
 {
   char *bp = buf;
   char const *buflim = buf + nbytes;
+  size_t readlim = SIZE_MAX;
 
   do
     {
-      ssize_t nread = read (fd, bp, buflim - bp);
+      size_t bytes_to_read = MIN (buflim - bp, readlim);
+      ssize_t nread = read (fd, bp, bytes_to_read);
       if (nread <= 0)
        {
          if (nread == 0)
            break;
 
+         /* Accommodate Tru64 5.1, which can't read more than INT_MAX
+            bytes at a time.  */
+         if (errno == EINVAL && INT_MAX < bytes_to_read)
+           {
+             readlim = INT_MAX;
+             continue;
+           }
+
          /* Accommodate ancient AIX hosts that set errno to EINTR
             after uncaught SIGCONT.  See
             <news:address@hidden> (1993-04-22).  */
          if (! SA_RESTART && errno == EINTR)
            continue;
 
-         return -1;
+         return SIZE_MAX;
        }
       bp += nread;
     }
===================================================================
RCS file: src/RCS/cmp.c,v
retrieving revision 1.33
diff -pu -r1.33 src/cmp.c
--- src/cmp.c   2002/03/12 13:08:22     1.33
+++ src/cmp.c   2002/04/01 23:53:03
@@ -402,19 +402,13 @@ cmp (void)
          /* lseek failed; read and discard the ignored initial prefix.  */
          do
            {
-             ssize_t r = read (file_desc[f], buf0, MIN (ig, buf_size));
-             if (r <= 0)
+             size_t bytes_to_read = MIN (ig, buf_size);
+             ssize_t r = block_read (file_desc[f], buf0, bytes_to_read);
+             if (r != bytes_to_read)
                {
-                 if (r == 0)
-                   break;
-
-                 /* Accommodate ancient AIX hosts that set errno to
-                    EINTR after uncaught SIGCONT.  See
-                    <news:address@hidden> (1993-04-22).  */
-                 if (! SA_RESTART && errno == EINTR)
-                   continue;
-
-                 error (EXIT_TROUBLE, errno, "%s", file[f]);
+                 if (r == SIZE_MAX)
+                   error (EXIT_TROUBLE, errno, "%s", file[f]);
+                 break;
                }
              ig -= r;
            }
===================================================================
RCS file: src/RCS/diff3.c,v
retrieving revision 1.37
diff -pu -r1.37 src/diff3.c
--- src/diff3.c 2002/03/11 08:00:47     1.37
+++ src/diff3.c 2002/04/02 00:06:56
@@ -26,6 +26,7 @@ static char const copyright_string[] =
 static char const authorship_msgid[] = N_("Written by Randy Smith.");
 
 #include <c-stack.h>
+#include <cmpbuf.h>
 #include <error.h>
 #include <exitfail.h>
 #include <freesoft.h>
@@ -1221,27 +1222,18 @@ read_diff (char const *filea,
   diff_result = xmalloc (current_chunk_size);
   total = 0;
 
-  while ((bytes = read (fd, diff_result + total, current_chunk_size - total)))
+  while ((bytes = block_read (fd, diff_result + total,
+                             current_chunk_size - total)))
     {
-      if (bytes < 0)
-       {
-         /* Accommodate ancient AIX hosts that set errno to EINTR
-            after uncaught SIGCONT.  See
-            <news:address@hidden> (1993-04-22).  */
-         if (! SA_RESTART && errno == EINTR)
-           continue;
-
-         perror_with_exit (_("read failed"));
-       }
-
+      if (bytes == SIZE_MAX)
+       perror_with_exit (_("read failed"));
       total += bytes;
-      if (total == current_chunk_size)
-       {
-         if (PTRDIFF_MAX / 2 <= current_chunk_size)
-           xalloc_die ();
-         current_chunk_size *= 2;
-         diff_result = xrealloc (diff_result, current_chunk_size);
-       }
+      if (total < current_chunk_size)
+       break;
+      if (PTRDIFF_MAX / 2 <= current_chunk_size)
+       xalloc_die ();
+      current_chunk_size *= 2;
+      diff_result = xrealloc (diff_result, current_chunk_size);
     }
 
   if (total != 0 && diff_result[total-1] != '\n')



reply via email to

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