Mercurial > gnulib
changeset 39718:9068bde9c37d
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.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Mon, 25 Jun 2018 04:18:30 +0200 |
parents | d4d7547d5731 |
children | 82f14d8df980 |
files | ChangeLog lib/af_alg.c |
diffstat | 2 files changed, 25 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Jun 25 00:41:03 2018 +0200 +++ b/ChangeLog Mon Jun 25 04:18:30 2018 +0200 @@ -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.
--- a/lib/af_alg.c Mon Jun 25 00:41:03 2018 +0200 +++ b/lib/af_alg.c Mon Jun 25 04:18:30 2018 +0200 @@ -157,7 +157,10 @@ 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 @@ 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 @@ 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;