Tizen 2.0 Release
[external/tizen-coreutils.git] / lib / randread.c
1 /* Generate buffers of random data.
2
3    Copyright (C) 2006 Free Software Foundation, Inc.
4
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.
9
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.
14
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.  */
18
19 /* Written by Paul Eggert.  */
20
21 #include <config.h>
22
23 #include "randread.h"
24
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>
34
35 #include "gettext.h"
36 #define _(msgid) gettext (msgid)
37
38 #include "rand-isaac.h"
39 #include "stdio-safer.h"
40 #include "unlocked-io.h"
41 #include "xalloc.h"
42
43 #ifndef MIN
44 # define MIN(a, b) ((a) < (b) ? (a) : (b))
45 #endif
46
47 #ifndef __attribute__
48 # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
49 #  define __attribute__(x)
50 # endif
51 #endif
52
53 #ifndef ATTRIBUTE_UNUSED
54 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
55 #endif
56
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
63
64 #ifndef DEFAULT_RANDOM_FILE
65 # define DEFAULT_RANDOM_FILE "/dev/urandom"
66 #endif
67
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)
72
73 /* A source of random data for generating random buffers.  */
74 struct randread_source
75 {
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;
81
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;
89
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
94   {
95     /* The stream buffer, if SOURCE is not null.  */
96     char c[RANDREAD_BUFFER_SIZE];
97
98     /* The buffered ISAAC pseudorandom buffer, if SOURCE is null.  */
99     struct isaac
100     {
101       /* The number of bytes that are buffered at the end of data.b.  */
102       size_t buffered;
103
104       /* State of the ISAAC generator.  */
105       struct isaac_state state;
106
107       /* Up to a buffer's worth of pseudorandom data.  */
108       union
109       {
110         uint32_t w[ISAAC_WORDS];
111         unsigned char b[ISAAC_BYTES];
112       } data;
113     } isaac;
114   } buf;
115 };
116
117
118 /* The default error handler.  */
119
120 static void
121 randread_error (void const *file_name)
122 {
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 ();
128 }
129
130 /* Simply return a new randread_source object with the default error
131    handler.  */
132
133 static struct randread_source *
134 simple_new (FILE *source, void const *handler_arg)
135 {
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;
141 }
142
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.
147
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.
151
152    Return NULL (setting errno) on failure.  */
153
154 struct randread_source *
155 randread_new (char const *name, size_t bytes_bound)
156 {
157   if (bytes_bound == 0)
158     return simple_new (NULL, NULL);
159   else
160     {
161       char const *file_name = (name ? name : DEFAULT_RANDOM_FILE);
162       FILE *source = fopen_safer (file_name, "rb");
163       struct randread_source *s;
164
165       if (! source)
166         {
167           if (name)
168             return NULL;
169           file_name = NULL;
170         }
171
172       s = simple_new (source, file_name);
173
174       if (source)
175         setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound));
176       else
177         {
178           s->buf.isaac.buffered = 0;
179           isaac_seed (&s->buf.isaac.state);
180         }
181
182       return s;
183     }
184 }
185
186
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.  */
193
194 void
195 randread_set_handler (struct randread_source *s, void (*handler) (void const *))
196 {
197   s->handler = handler;
198 }
199
200 void
201 randread_set_handler_arg (struct randread_source *s, void const *handler_arg)
202 {
203   s->handler_arg = handler_arg;
204 }
205
206
207 /* Place SIZE random bytes into the buffer beginning at P, using
208    the stream in S.  */
209
210 static void
211 readsource (struct randread_source *s, unsigned char *p, size_t size)
212 {
213   for (;;)
214     {
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);
223     }
224 }
225
226
227 /* Place SIZE pseudorandom bytes into the buffer beginning at P, using
228    the buffered ISAAC generator in ISAAC.  */
229
230 static void
231 readisaac (struct isaac *isaac, unsigned char *p, size_t size)
232 {
233   size_t inbytes = isaac->buffered;
234
235   for (;;)
236     {
237       if (size <= inbytes)
238         {
239           memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, size);
240           isaac->buffered = inbytes - size;
241           return;
242         }
243
244       memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, inbytes);
245       p += inbytes;
246       size -= inbytes;
247
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))
251         {
252           uint32_t *wp = (uint32_t *) p;
253           while (ISAAC_BYTES <= size)
254             {
255               isaac_refill (&isaac->state, wp);
256               wp += ISAAC_WORDS;
257               size -= ISAAC_BYTES;
258               if (size == 0)
259                 {
260                   isaac->buffered = 0;
261                   return;
262                 }
263             }
264           p = (unsigned char *) wp;
265         }
266
267       isaac_refill (&isaac->state, isaac->data.w);
268       inbytes = ISAAC_BYTES;
269     }
270 }
271
272
273 /* Consume random data from *S to generate a random buffer BUF of size
274    SIZE.  */
275
276 void
277 randread (struct randread_source *s, void *buf, size_t size)
278 {
279   if (s->source)
280     readsource (s, buf, size);
281   else
282     readisaac (&s->buf.isaac, buf, size);
283 }
284
285
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).  */
290
291 int
292 randread_free (struct randread_source *s)
293 {
294   FILE *source = s->source;
295   memset (s, 0, sizeof *s);
296   free (s);
297   return (source ? fclose (source) : 0);
298 }