Imported Upstream version 3.3.2
[debian/amanda] / common-src / simpleprng.c
1 /*
2  * Copyright (c) 2008-2012 Zmanda, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published
6  * by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16  *
17  * Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
18  * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19  */
20
21 #include "amanda.h"
22 #include "simpleprng.h"
23
24 /* A *very* basic linear congruential generator; values are as cited in
25  * http://en.wikipedia.org/wiki/Linear_congruential_generator for Numerical Recipes */
26
27 #define A 1664525
28 #define C 1013904223
29
30 void
31 simpleprng_seed(
32     simpleprng_state_t *state,
33     guint32 seed)
34 {
35     g_assert(seed != 0);
36     state->val = seed;
37     state->count = 0;
38 }
39
40 guint32
41 simpleprng_get_seed(
42     simpleprng_state_t *state)
43 {
44     return state->val;
45 }
46
47 guint32 simpleprng_rand(
48     simpleprng_state_t *state)
49 {
50     state->count++;
51     return (state->val = (A * state->val) + C);
52 }
53
54 void simpleprng_fill_buffer(
55     simpleprng_state_t *state,
56     gpointer buf,
57     size_t len)
58 {
59     guint8 *p = buf;
60     while (len--) {
61         *(p++) = simpleprng_rand_byte(state);
62     }
63 }
64
65 static char *
66 hexstr(guint8 *p, int len)
67 {
68     char *result = NULL;
69     int i;
70
71     for (i = 0; i < len; i++) {
72         if (result)
73             result = newvstrallocf(result, "%s %02x", result, (guint)(*(p++)));
74         else
75             result = vstrallocf("[%02x", (guint)(*(p++)));
76     }
77     result = newvstrallocf(result, "%s]", result);
78
79     return result;
80 }
81
82 gboolean simpleprng_verify_buffer(
83     simpleprng_state_t *state,
84     gpointer buf,
85     size_t len)
86 {
87     guint8 *p = buf;
88     while (len--) {
89         guint64 count = state->count;
90         guint8 expected = simpleprng_rand_byte(state);
91         guint8 got = *p;
92         if (expected != got) {
93             int remaining = MIN(len, 16);
94             guint8 expbytes[16] = { expected };
95             char *gotstr = hexstr(p, remaining);
96             char *expstr;
97             int i;
98
99             for (i = 1; i < remaining; i++)
100                 expbytes[i] = simpleprng_rand_byte(state);
101             expstr = hexstr(expbytes, remaining);
102
103             g_fprintf(stderr,
104                     "random value mismatch at offset %ju: got %s, expected %s\n",
105                     (uintmax_t)count, gotstr, expstr);
106             g_free(gotstr);
107             return FALSE;
108         }
109         p++;
110     }
111
112     return TRUE;
113 }