]> Savannah Git Hosting - gnulib.git/commitdiff
af_alg: Fail in continuable manner on Linux/powerpc64le.
authorBruno Haible <bruno@clisp.org>
Mon, 25 Jun 2018 02:18:30 +0000 (04:18 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 25 Jun 2018 02:18:30 +0000 (04:18 +0200)
Reported by Assaf Gordon <assafgordon@gmail.com>
in <https://lists.gnu.org/archive/html/coreutils/2018-06/msg00034.html>.

* lib/af_alg.c (afalg_stream): On non-seekable streams, try a single-
byte send() as the first round.

ChangeLog
lib/af_alg.c

index 33da642c3b4bac8a51aec774d159c0f4bddb920f..d2f212874f4dd94e84a3a6b7066845a3f5676cec 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2018-06-24  Bruno Haible  <bruno@clisp.org>
+
+       af_alg: Fail in continuable manner on Linux/powerpc64le.
+       Reported by Assaf Gordon <assafgordon@gmail.com>
+       in <https://lists.gnu.org/archive/html/coreutils/2018-06/msg00034.html>.
+       * lib/af_alg.c (afalg_stream): On non-seekable streams, try a single-
+       byte send() as the first round.
+
 2018-06-24  Bruno Haible  <bruno@clisp.org>
 
        af_alg: Fix state of stream after sendfile() succeeds.
index 2753ab9a420e0a9f78f6a87c52fec127943b009f..549cdcfddeb637fe64ea8f738bcead858f868cf4 100644 (file)
@@ -157,7 +157,10 @@ afalg_stream (FILE *stream, const char *alg,
       for (;;)
         {
           char buf[BLOCKSIZE];
-          ssize_t size = fread (buf, 1, sizeof buf, stream);
+          /* When the stream is not seekable, start with a single-byte block,
+             so that we can use ungetc() in the case that send() fails.  */
+          size_t blocksize = (nseek == 0 && off < 0 ? 1 : BLOCKSIZE);
+          ssize_t size = fread (buf, 1, blocksize, stream);
           if (size == 0)
             {
               /* On Linux < 4.9, the value for an empty stream is wrong (all 0).
@@ -170,8 +173,18 @@ afalg_stream (FILE *stream, const char *alg,
           nseek -= size;
           if (send (ofd, buf, size, MSG_MORE) != size)
             {
-              result = (fseeko (stream, nseek, SEEK_CUR) == 0
-                        ? -EAFNOSUPPORT : -EIO);
+              if (nseek == -1)
+                {
+                  /* 1 byte of pushback buffer is guaranteed on stream, even
+                     if stream is not seekable.  */
+                  ungetc ((unsigned char) buf[0], stream);
+                  result = -EAFNOSUPPORT;
+                }
+              else if (fseeko (stream, nseek, SEEK_CUR) == 0)
+                /* The position of stream has been restored.  */
+                result = -EAFNOSUPPORT;
+              else
+                result = -EIO;
               break;
             }
 
@@ -187,6 +200,7 @@ afalg_stream (FILE *stream, const char *alg,
       if (result == 0 && read (ofd, resblock, hashlen) != hashlen)
         {
           if (nseek == 0 || fseeko (stream, nseek, SEEK_CUR) == 0)
+            /* The position of stream has been restored.  */
             result = -EAFNOSUPPORT;
           else
             result = -EIO;