Clean up after the change of 2006-12-28.
[coreutils.git] / lib / randread.c
blob5462d446c9d8d3891c36b76cda5f136b91b07e8f
1 /* Generate buffers of random data.
3 Copyright (C) 2006 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 /* Written by Paul Eggert. */
21 #include <config.h>
23 #include "randread.h"
25 #include <errno.h>
26 #include <error.h>
27 #include <exitfail.h>
28 #include <quotearg.h>
29 #include <stdbool.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
35 #include "gettext.h"
36 #define _(msgid) gettext (msgid)
38 #include "rand-isaac.h"
39 #include "stdio-safer.h"
40 #include "unlocked-io.h"
41 #include "xalloc.h"
43 #ifndef MIN
44 # define MIN(a, b) ((a) < (b) ? (a) : (b))
45 #endif
47 #ifndef __attribute__
48 # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
49 # define __attribute__(x)
50 # endif
51 #endif
53 #ifndef ATTRIBUTE_UNUSED
54 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
55 #endif
57 #if _STRING_ARCH_unaligned
58 # define ALIGNED_POINTER(ptr, type) true
59 #else
60 # define alignof(type) offsetof (struct { char c; type x; }, x)
61 # define ALIGNED_POINTER(ptr, type) ((size_t) (ptr) % alignof (type) == 0)
62 #endif
64 #ifndef DEFAULT_RANDOM_FILE
65 # define DEFAULT_RANDOM_FILE "/dev/urandom"
66 #endif
68 /* The maximum buffer size used for reads of random data. Using the
69 value 2 * ISAAC_BYTES makes this the largest power of two that
70 would not otherwise cause struct randread_source to grow. */
71 #define RANDREAD_BUFFER_SIZE (2 * ISAAC_BYTES)
73 /* A source of random data for generating random buffers. */
74 struct randread_source
76 /* Stream to read random bytes from. If null, the behavior is
77 undefined; the current implementation uses ISAAC in this case,
78 but this is for old-fashioned implementations that lack
79 /dev/urandom and callers should not rely on this. */
80 FILE *source;
82 /* Function to call, and its argument, if there is an input error or
83 end of file when reading from the stream; errno is nonzero if
84 there was an error. If this function returns, it should fix the
85 problem before returning. The default handler assumes that
86 handler_arg is the file name of the source. */
87 void (*handler) (void const *);
88 void const *handler_arg;
90 /* The buffer for SOURCE. It's kept here to simplify storage
91 allocation and to make it easier to clear out buffered random
92 data. */
93 union
95 /* The stream buffer, if SOURCE is not null. */
96 char c[RANDREAD_BUFFER_SIZE];
98 /* The buffered ISAAC pseudorandom buffer, if SOURCE is null. */
99 struct isaac
101 /* The number of bytes that are buffered at the end of data.b. */
102 size_t buffered;
104 /* State of the ISAAC generator. */
105 struct isaac_state state;
107 /* Up to a buffer's worth of pseudorandom data. */
108 union
110 uint32_t w[ISAAC_WORDS];
111 unsigned char b[ISAAC_BYTES];
112 } data;
113 } isaac;
114 } buf;
118 /* The default error handler. */
120 static void
121 randread_error (void const *file_name)
123 if (file_name)
124 error (exit_failure, errno,
125 _(errno == 0 ? "%s: end of file" : "%s: read error"),
126 quotearg_colon (file_name));
127 abort ();
130 /* Simply return a new randread_source object with the default error
131 handler. */
133 static struct randread_source *
134 simple_new (FILE *source, void const *handler_arg)
136 struct randread_source *s = xmalloc (sizeof *s);
137 s->source = source;
138 s->handler = randread_error;
139 s->handler_arg = handler_arg;
140 return s;
143 /* Create and initialize a random data source from NAME, or use a
144 reasonable default source if NAME is null. BYTES_BOUND is an upper
145 bound on the number of bytes that will be needed. If zero, it is a
146 hard bound; otherwise it is just an estimate.
148 If NAME is not null, NAME is saved for use as the argument of the
149 default handler. Unless a non-default handler is used, NAME's
150 lifetime should be at least that of the returned value.
152 Return NULL (setting errno) on failure. */
154 struct randread_source *
155 randread_new (char const *name, size_t bytes_bound)
157 if (bytes_bound == 0)
158 return simple_new (NULL, NULL);
159 else
161 char const *file_name = (name ? name : DEFAULT_RANDOM_FILE);
162 FILE *source = fopen_safer (file_name, "rb");
163 struct randread_source *s;
165 if (! source)
167 if (name)
168 return NULL;
169 file_name = NULL;
172 s = simple_new (source, file_name);
174 if (source)
175 setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound));
176 else
178 s->buf.isaac.buffered = 0;
179 isaac_seed (&s->buf.isaac.state);
182 return s;
187 /* Set S's handler and its argument. HANDLER (HANDLER_ARG) is called
188 when there is a read error or end of file from the random data
189 source; errno is nonzero if there was an error. If HANDLER
190 returns, it should fix the problem before returning. The default
191 handler assumes that handler_arg is the file name of the source; it
192 does not return. */
194 void
195 randread_set_handler (struct randread_source *s, void (*handler) (void const *))
197 s->handler = handler;
200 void
201 randread_set_handler_arg (struct randread_source *s, void const *handler_arg)
203 s->handler_arg = handler_arg;
207 /* Place SIZE random bytes into the buffer beginning at P, using
208 the stream in S. */
210 static void
211 readsource (struct randread_source *s, unsigned char *p, size_t size)
213 for (;;)
215 size_t inbytes = fread (p, sizeof *p, size, s->source);
216 int fread_errno = errno;
217 p += inbytes;
218 size -= inbytes;
219 if (size == 0)
220 break;
221 errno = (ferror (s->source) ? fread_errno : 0);
222 s->handler (s->handler_arg);
227 /* Place SIZE pseudorandom bytes into the buffer beginning at P, using
228 the buffered ISAAC generator in ISAAC. */
230 static void
231 readisaac (struct isaac *isaac, unsigned char *p, size_t size)
233 size_t inbytes = isaac->buffered;
235 for (;;)
237 if (size <= inbytes)
239 memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, size);
240 isaac->buffered = inbytes - size;
241 return;
244 memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, inbytes);
245 p += inbytes;
246 size -= inbytes;
248 /* If P is aligned, write to *P directly to avoid the overhead
249 of copying from the buffer. */
250 if (ALIGNED_POINTER (p, uint32_t))
252 uint32_t *wp = (uint32_t *) p;
253 while (ISAAC_BYTES <= size)
255 isaac_refill (&isaac->state, wp);
256 wp += ISAAC_WORDS;
257 size -= ISAAC_BYTES;
258 if (size == 0)
260 isaac->buffered = 0;
261 return;
264 p = (unsigned char *) wp;
267 isaac_refill (&isaac->state, isaac->data.w);
268 inbytes = ISAAC_BYTES;
273 /* Consume random data from *S to generate a random buffer BUF of size
274 SIZE. */
276 void
277 randread (struct randread_source *s, void *buf, size_t size)
279 if (s->source)
280 readsource (s, buf, size);
281 else
282 readisaac (&s->buf.isaac, buf, size);
286 /* Clear *S so that it no longer contains undelivered random data, and
287 deallocate any system resources associated with *S. Return 0 if
288 successful, a negative number (setting errno) if not (this is rare,
289 but can occur in theory if there is an input error). */
292 randread_free (struct randread_source *s)
294 FILE *source = s->source;
295 memset (s, 0, sizeof *s);
296 free (s);
297 return (source ? fclose (source) : 0);