Mercurial > gnulib
annotate lib/af_alg.c @ 40203:30d91797009f
autoupdate
author | Karl Berry <karl@freefriends.org> |
---|---|
date | Fri, 01 Mar 2019 08:42:42 -0800 |
parents | b06060465f09 |
children |
rev | line source |
---|---|
19631
001bce13544f
af_alg: fix file descriptor leak
Paul Eggert <eggert@cs.ucla.edu>
parents:
19630
diff
changeset
|
1 /* af_alg.c - Compute message digests from file streams and buffers. |
40057
b06060465f09
maint: Run 'make update-copyright'
Paul Eggert <eggert@cs.ucla.edu>
parents:
39718
diff
changeset
|
2 Copyright (C) 2018-2019 Free Software Foundation, Inc. |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
3 |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
4 This program is free software; you can redistribute it and/or modify it |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
5 under the terms of the GNU General Public License as published by the |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
6 Free Software Foundation; either version 2, or (at your option) any |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
7 later version. |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
8 |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
9 This program is distributed in the hope that it will be useful, |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
12 GNU General Public License for more details. |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
13 |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
14 You should have received a copy of the GNU General Public License |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
15 along with this program; if not, see <https://www.gnu.org/licenses/>. */ |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
16 |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
17 /* Written by Matteo Croce <mcroce@redhat.com>, 2018. */ |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
18 |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
19 #include <config.h> |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
20 |
19621
3475ec8fca53
af_alg: Add configure option to enable/disable use of Linux crypto API.
Bruno Haible <bruno@clisp.org>
parents:
19617
diff
changeset
|
21 #if USE_LINUX_CRYPTO_API |
19616 | 22 |
23 #include "af_alg.h" | |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
24 |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
25 #include <unistd.h> |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
26 #include <string.h> |
19623
1acf7ebb5dab
af_alg: Fix bug with streams that are not at position 0.
Bruno Haible <bruno@clisp.org>
parents:
19621
diff
changeset
|
27 #include <stdio.h> |
1acf7ebb5dab
af_alg: Fix bug with streams that are not at position 0.
Bruno Haible <bruno@clisp.org>
parents:
19621
diff
changeset
|
28 #include <errno.h> |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
29 #include <linux/if_alg.h> |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
30 #include <sys/stat.h> |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
31 #include <sys/sendfile.h> |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
32 #include <sys/socket.h> |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
33 |
19611
970c998e00e3
sys-limits.h: new file for crypto and safe I/O
Paul Eggert <eggert@cs.ucla.edu>
parents:
19610
diff
changeset
|
34 #include "sys-limits.h" |
970c998e00e3
sys-limits.h: new file for crypto and safe I/O
Paul Eggert <eggert@cs.ucla.edu>
parents:
19610
diff
changeset
|
35 |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
36 #define BLOCKSIZE 32768 |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
37 |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
38 /* Return a newly created socket for ALG. |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
39 On error, return a negative error number. */ |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
40 static int |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
41 alg_socket (char const *alg) |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
42 { |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
43 struct sockaddr_alg salg = { |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
44 .salg_family = AF_ALG, |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
45 .salg_type = "hash", |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
46 }; |
39710
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
47 /* Copy alg into salg.salg_name, without calling strcpy nor strlen. */ |
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
48 for (size_t i = 0; (salg.salg_name[i] = alg[i]) != '\0'; i++) |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
49 if (i == sizeof salg.salg_name - 1) |
39710
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
50 /* alg is too long. */ |
19630
a67dfbeb0b3d
af_alg: Pacify --enable-gcc-warnings on GCC 8
Paul Eggert <eggert@cs.ucla.edu>
parents:
19629
diff
changeset
|
51 return -EINVAL; |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
52 |
19633
a5d8edeceecf
af_alg: don’t leak file descriptors into children
Paul Eggert <eggert@cs.ucla.edu>
parents:
19632
diff
changeset
|
53 int cfd = socket (AF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0); |
19630
a67dfbeb0b3d
af_alg: Pacify --enable-gcc-warnings on GCC 8
Paul Eggert <eggert@cs.ucla.edu>
parents:
19629
diff
changeset
|
54 if (cfd < 0) |
a67dfbeb0b3d
af_alg: Pacify --enable-gcc-warnings on GCC 8
Paul Eggert <eggert@cs.ucla.edu>
parents:
19629
diff
changeset
|
55 return -EAFNOSUPPORT; |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
56 int ofd = (bind (cfd, (struct sockaddr *) &salg, sizeof salg) == 0 |
19633
a5d8edeceecf
af_alg: don’t leak file descriptors into children
Paul Eggert <eggert@cs.ucla.edu>
parents:
19632
diff
changeset
|
57 ? accept4 (cfd, NULL, 0, SOCK_CLOEXEC) |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
58 : -1); |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
59 close (cfd); |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
60 return ofd < 0 ? -EAFNOSUPPORT : ofd; |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
61 } |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
62 |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
63 int |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
64 afalg_buffer (const char *buffer, size_t len, const char *alg, |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
65 void *resblock, ssize_t hashlen) |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
66 { |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
67 /* On Linux < 4.9, the value for an empty stream is wrong (all zeroes). |
39710
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
68 See <https://patchwork.kernel.org/patch/9308641/>. |
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
69 This was not fixed properly until November 2016, |
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
70 see <https://patchwork.kernel.org/patch/9434741/>. */ |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
71 if (len == 0) |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
72 return -EAFNOSUPPORT; |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
73 |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
74 int ofd = alg_socket (alg); |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
75 if (ofd < 0) |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
76 return ofd; |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
77 |
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
78 int result; |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
79 |
19634 | 80 for (;;) |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
81 { |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
82 ssize_t size = (len > BLOCKSIZE ? BLOCKSIZE : len); |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
83 if (send (ofd, buffer, size, MSG_MORE) != size) |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
84 { |
19635
e791e827a06f
af_alg: distiguish I/O errors better
Paul Eggert <eggert@cs.ucla.edu>
parents:
19634
diff
changeset
|
85 result = -EAFNOSUPPORT; |
19634 | 86 break; |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
87 } |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
88 buffer += size; |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
89 len -= size; |
19634 | 90 if (len == 0) |
91 { | |
19637
91ffcfdc9b64
af_alg: fix my typo in afalg_buffer
Paul Eggert <eggert@cs.ucla.edu>
parents:
19636
diff
changeset
|
92 result = read (ofd, resblock, hashlen) == hashlen ? 0 : -EAFNOSUPPORT; |
19634 | 93 break; |
94 } | |
19627
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
95 } |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
96 |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
97 close (ofd); |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
98 return result; |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
99 } |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
100 |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
101 int |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
102 afalg_stream (FILE *stream, const char *alg, |
25b7564e3876
af_alg: Add ability to use Linux kernel crypto API on data in memory.
Bruno Haible <bruno@clisp.org>
parents:
19624
diff
changeset
|
103 void *resblock, ssize_t hashlen) |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
104 { |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
105 int ofd = alg_socket (alg); |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
106 if (ofd < 0) |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
107 return ofd; |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
108 |
19636
b9a17c2eedf8
af_alg: recover better from crypto failures
Paul Eggert <eggert@cs.ucla.edu>
parents:
19635
diff
changeset
|
109 /* If STREAM's size is known and nonzero and not too large, attempt |
b9a17c2eedf8
af_alg: recover better from crypto failures
Paul Eggert <eggert@cs.ucla.edu>
parents:
19635
diff
changeset
|
110 sendfile to pipe the data. The nonzero restriction avoids issues |
b9a17c2eedf8
af_alg: recover better from crypto failures
Paul Eggert <eggert@cs.ucla.edu>
parents:
19635
diff
changeset
|
111 with /proc files that pretend to be empty, and lets the classic |
b9a17c2eedf8
af_alg: recover better from crypto failures
Paul Eggert <eggert@cs.ucla.edu>
parents:
19635
diff
changeset
|
112 read-write loop work around an empty-input bug noted below. */ |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
113 int fd = fileno (stream); |
19637
91ffcfdc9b64
af_alg: fix my typo in afalg_buffer
Paul Eggert <eggert@cs.ucla.edu>
parents:
19636
diff
changeset
|
114 int result; |
19632
dbfa4ac5dc40
af_alg: coalesce socket creation
Paul Eggert <eggert@cs.ucla.edu>
parents:
19631
diff
changeset
|
115 struct stat st; |
39710
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
116 off_t off = ftello (stream); |
19636
b9a17c2eedf8
af_alg: recover better from crypto failures
Paul Eggert <eggert@cs.ucla.edu>
parents:
19635
diff
changeset
|
117 if (0 <= off && fstat (fd, &st) == 0 |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
118 && (S_ISREG (st.st_mode) || S_TYPEISSHM (&st) || S_TYPEISTMO (&st)) |
19636
b9a17c2eedf8
af_alg: recover better from crypto failures
Paul Eggert <eggert@cs.ucla.edu>
parents:
19635
diff
changeset
|
119 && off < st.st_size && st.st_size - off < SYS_BUFSIZE_MAX) |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
120 { |
39717
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
121 /* Make sure the offset of fileno (stream) reflects how many bytes |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
122 have been read from stream before this function got invoked. |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
123 Note: fflush on an input stream after ungetc does not work as expected |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
124 on some platforms. Therefore this situation is not supported here. */ |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
125 if (fflush (stream)) |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
126 result = -EIO; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
127 else |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
128 { |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
129 off_t nbytes = st.st_size - off; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
130 if (sendfile (ofd, fd, &off, nbytes) == nbytes) |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
131 { |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
132 if (read (ofd, resblock, hashlen) == hashlen) |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
133 { |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
134 /* The input buffers of stream are no longer valid. */ |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
135 if (lseek (fd, off, SEEK_SET) != (off_t)-1) |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
136 result = 0; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
137 else |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
138 /* The file position of fd has not changed. */ |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
139 result = -EAFNOSUPPORT; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
140 } |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
141 else |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
142 /* The file position of fd has not changed. */ |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
143 result = -EAFNOSUPPORT; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
144 } |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
145 else |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
146 /* The file position of fd has not changed. */ |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
147 result = -EAFNOSUPPORT; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
148 } |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
149 } |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
150 else |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
151 { |
39710
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
152 /* sendfile not possible, do a classic read-write loop. */ |
39717
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
153 |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
154 /* Number of bytes to seek (backwards) in case of error. */ |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
155 off_t nseek = 0; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
156 |
19634 | 157 for (;;) |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
158 { |
19634 | 159 char buf[BLOCKSIZE]; |
39718
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
160 /* When the stream is not seekable, start with a single-byte block, |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
161 so that we can use ungetc() in the case that send() fails. */ |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
162 size_t blocksize = (nseek == 0 && off < 0 ? 1 : BLOCKSIZE); |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
163 ssize_t size = fread (buf, 1, blocksize, stream); |
19634 | 164 if (size == 0) |
165 { | |
166 /* On Linux < 4.9, the value for an empty stream is wrong (all 0). | |
39710
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
167 See <https://patchwork.kernel.org/patch/9308641/>. |
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
168 This was not fixed properly until November 2016, |
191b096795a6
af_alg: Comment and style improvements.
Bruno Haible <bruno@clisp.org>
parents:
39707
diff
changeset
|
169 see <https://patchwork.kernel.org/patch/9434741/>. */ |
19637
91ffcfdc9b64
af_alg: fix my typo in afalg_buffer
Paul Eggert <eggert@cs.ucla.edu>
parents:
19636
diff
changeset
|
170 result = ferror (stream) ? -EIO : nseek == 0 ? -EAFNOSUPPORT : 0; |
19634 | 171 break; |
172 } | |
19636
b9a17c2eedf8
af_alg: recover better from crypto failures
Paul Eggert <eggert@cs.ucla.edu>
parents:
19635
diff
changeset
|
173 nseek -= size; |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
174 if (send (ofd, buf, size, MSG_MORE) != size) |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
175 { |
39718
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
176 if (nseek == -1) |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
177 { |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
178 /* 1 byte of pushback buffer is guaranteed on stream, even |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
179 if stream is not seekable. */ |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
180 ungetc ((unsigned char) buf[0], stream); |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
181 result = -EAFNOSUPPORT; |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
182 } |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
183 else if (fseeko (stream, nseek, SEEK_CUR) == 0) |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
184 /* The position of stream has been restored. */ |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
185 result = -EAFNOSUPPORT; |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
186 else |
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
187 result = -EIO; |
19634 | 188 break; |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
189 } |
39707
5fd4481b1d32
af_alg: avoid hangs when reading from streams
Pádraig Brady <P@draigBrady.com>
parents:
39706
diff
changeset
|
190 |
39711
e693c621c472
maint: clarify comments about sticky EOF
Pádraig Brady <P@draigBrady.com>
parents:
39710
diff
changeset
|
191 /* Don't assume that EOF is sticky. See: |
39707
5fd4481b1d32
af_alg: avoid hangs when reading from streams
Pádraig Brady <P@draigBrady.com>
parents:
39706
diff
changeset
|
192 <https://sourceware.org/bugzilla/show_bug.cgi?id=19476>. */ |
5fd4481b1d32
af_alg: avoid hangs when reading from streams
Pádraig Brady <P@draigBrady.com>
parents:
39706
diff
changeset
|
193 if (feof (stream)) |
5fd4481b1d32
af_alg: avoid hangs when reading from streams
Pádraig Brady <P@draigBrady.com>
parents:
39706
diff
changeset
|
194 { |
5fd4481b1d32
af_alg: avoid hangs when reading from streams
Pádraig Brady <P@draigBrady.com>
parents:
39706
diff
changeset
|
195 result = 0; |
5fd4481b1d32
af_alg: avoid hangs when reading from streams
Pádraig Brady <P@draigBrady.com>
parents:
39706
diff
changeset
|
196 break; |
5fd4481b1d32
af_alg: avoid hangs when reading from streams
Pádraig Brady <P@draigBrady.com>
parents:
39706
diff
changeset
|
197 } |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
198 } |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
199 |
39717
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
200 if (result == 0 && read (ofd, resblock, hashlen) != hashlen) |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
201 { |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
202 if (nseek == 0 || fseeko (stream, nseek, SEEK_CUR) == 0) |
39718
9068bde9c37d
af_alg: Fail in continuable manner on Linux/powerpc64le.
Bruno Haible <bruno@clisp.org>
parents:
39717
diff
changeset
|
203 /* The position of stream has been restored. */ |
39717
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
204 result = -EAFNOSUPPORT; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
205 else |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
206 result = -EIO; |
d4d7547d5731
af_alg: Fix state of stream after sendfile() succeeds.
Bruno Haible <bruno@clisp.org>
parents:
39711
diff
changeset
|
207 } |
39706
21fef17e5c30
af_alg: fix error handling when hash not returned
Pádraig Brady <P@draigBrady.com>
parents:
19637
diff
changeset
|
208 } |
19636
b9a17c2eedf8
af_alg: recover better from crypto failures
Paul Eggert <eggert@cs.ucla.edu>
parents:
19635
diff
changeset
|
209 close (ofd); |
19624
9d18c9f06872
af_alg: Fix a resource leak.
Bruno Haible <bruno@clisp.org>
parents:
19623
diff
changeset
|
210 return result; |
19598
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
211 } |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
212 |
e5aa8f083cad
sha1sum: use AF_ALG when available
Matteo Croce <mcroce@redhat.com>
parents:
diff
changeset
|
213 #endif |