]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/base64.c
Fix seg fault in SQlite driver
[bacula/bacula] / bacula / src / lib / base64.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *   Generic base 64 input and output routines
30  *
31  *    Written by Kern E. Sibbald, March MM.
32  *
33  *   Version $Id$
34  */
35
36
37 #include "bacula.h"
38
39
40 #ifdef TEST_MODE
41 #include <glob.h>
42 #endif
43
44
45 static uint8_t const base64_digits[64] =
46 {
47   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
48   'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
49   'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
50   'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
51   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
52 };
53
54 static int base64_inited = 0;
55 static uint8_t base64_map[128];
56
57
58 /* Initialize the Base 64 conversion routines */
59 void
60 base64_init(void)
61 {
62    int i;
63    memset(base64_map, 0, sizeof(base64_map));
64    for (i=0; i<64; i++)
65       base64_map[(uint8_t)base64_digits[i]] = i;
66    base64_inited = 1;
67 }
68
69 /* Convert a value to base64 characters.
70  * The result is stored in where, which
71  * must be at least 8 characters long.
72  *
73  * Returns the number of characters
74  * stored (not including the EOS).
75  */
76 int
77 to_base64(intmax_t value, char *where)
78 {
79    uintmax_t val;
80    int i = 0;
81    int n;
82
83    /* Handle negative values */
84    if (value < 0) {
85       where[i++] = '-';
86       value = -value;
87    }
88
89    /* Determine output size */
90    val = value;
91    do {
92       val >>= 6;
93       i++;
94    } while (val);
95    n = i;
96
97    /* Output characters */
98    val = value;
99    where[i] = 0;
100    do {
101       where[--i] = base64_digits[val & (uintmax_t)0x3F];
102       val >>= 6;
103    } while (val);
104    return n;
105 }
106
107 /*
108  * Convert the Base 64 characters in where to
109  * a value. No checking is done on the validity
110  * of the characters!!
111  *
112  * Returns the value.
113  */
114 int
115 from_base64(intmax_t *value, char *where)
116 {
117    uintmax_t val = 0;
118    int i, neg;
119
120    if (!base64_inited)
121       base64_init();
122    /* Check if it is negative */
123    i = neg = 0;
124    if (where[i] == '-') {
125       i++;
126       neg = 1;
127    }
128    /* Construct value */
129    while (where[i] != 0 && where[i] != ' ') {
130       val <<= 6;
131       val += base64_map[(uint8_t)where[i++]];
132    }
133
134    *value = neg ? -(intmax_t)val : (intmax_t)val;
135    return i;
136 }
137
138
139 /*
140  * Encode binary data in bin of len bytes into
141  * buf as base64 characters.
142  *
143  * If compatible is true, the bin_to_base64 routine will be compatible
144  * with what the rest of the world uses.
145  *
146  *  Returns: the number of characters stored not
147  *           including the EOS
148  */
149 int
150 bin_to_base64(char *buf, int buflen, char *bin, int binlen, int compatible)
151 {
152    uint32_t reg, save, mask;
153    int rem, i;
154    int j = 0;
155
156    reg = 0;
157    rem = 0;
158    buflen--;                       /* allow for storing EOS */
159    for (i=0; i < binlen; ) {
160       if (rem < 6) {
161          reg <<= 8;
162          if (compatible) {
163             reg |= (uint8_t)bin[i++];
164          } else {
165             reg |= (int8_t)bin[i++];
166          }
167          rem += 8;
168       }
169       save = reg;
170       reg >>= (rem - 6);
171       if (j < buflen) {
172          buf[j++] = base64_digits[reg & 0x3F];
173       }
174       reg = save;
175       rem -= 6;
176    }
177    if (rem && j < buflen) {
178       mask = (1 << rem) - 1;
179       if (compatible) {
180          buf[j++] = base64_digits[(reg & mask) << (6 - rem)];
181       } else {
182          buf[j++] = base64_digits[reg & mask];
183       }
184    }
185    buf[j] = 0;
186    return j;
187 }
188
189 #ifdef BIN_TEST
190 int main(int argc, char *argv[])
191 {
192    int xx = 0;
193    int len;
194    char buf[100];
195    char junk[100];
196    int i;
197
198 #ifdef xxxx
199    for (i=0; i < 1000; i++) {
200       bin_to_base64(buf, sizeof(buf), (char *)&xx, 4, true);
201       printf("xx=%s\n", buf);
202       xx++;
203    }
204 #endif
205    junk[0] = 0xFF;
206    for (i=1; i<100; i++) {
207       junk[i] = junk[i-1]-1;
208    }
209    len = bin_to_base64(buf, sizeof(buf) junk, 16, true);
210    printf("len=%d junk=%s\n", len, buf);
211    return 0;
212 }
213 #endif
214
215 #ifdef TEST_MODE
216 static int errfunc(const char *epath, int eernoo)
217 {
218   printf("in errfunc\n");
219   return 1;
220 }
221
222
223 /*
224  * Test the base64 routines by encoding and decoding
225  * lstat() packets.
226  */
227 int main(int argc, char *argv[])
228 {
229    char where[500];
230    int i;
231    glob_t my_glob;
232    char *fname;
233    struct stat statp;
234    struct stat statn;
235    int debug_level = 0;
236    char *p;
237    time_t t = 1028712799;
238
239    if (argc > 1 && strcmp(argv[1], "-v") == 0)
240       debug_level++;
241
242    base64_init();
243
244    my_glob.gl_offs = 0;
245    glob("/etc/grub.conf", GLOB_MARK, errfunc, &my_glob);
246
247    for (i=0; my_glob.gl_pathv[i]; i++) {
248       fname = my_glob.gl_pathv[i];
249       if (lstat(fname, &statp) < 0) {
250          berrno be;
251          printf("Cannot stat %s: %s\n", fname, be.bstrerror(errno));
252          continue;
253       }
254       encode_stat(where, &statp, 0, 0);
255
256       printf("Encoded stat=%s\n", where);
257
258 #ifdef xxx
259       p = where;
260       p += to_base64((intmax_t)(statp.st_atime), p);
261       *p++ = ' ';
262       p += to_base64((intmax_t)t, p);
263       printf("%s %s\n", fname, where);
264
265       printf("%s %lld\n", "st_dev", (intmax_t)statp.st_dev);
266       printf("%s %lld\n", "st_ino", (intmax_t)statp.st_ino);
267       printf("%s %lld\n", "st_mode", (intmax_t)statp.st_mode);
268       printf("%s %lld\n", "st_nlink", (intmax_t)statp.st_nlink);
269       printf("%s %lld\n", "st_uid", (intmax_t)statp.st_uid);
270       printf("%s %lld\n", "st_gid", (intmax_t)statp.st_gid);
271       printf("%s %lld\n", "st_rdev", (intmax_t)statp.st_rdev);
272       printf("%s %lld\n", "st_size", (intmax_t)statp.st_size);
273       printf("%s %lld\n", "st_blksize", (intmax_t)statp.st_blksize);
274       printf("%s %lld\n", "st_blocks", (intmax_t)statp.st_blocks);
275       printf("%s %lld\n", "st_atime", (intmax_t)statp.st_atime);
276       printf("%s %lld\n", "st_mtime", (intmax_t)statp.st_mtime);
277       printf("%s %lld\n", "st_ctime", (intmax_t)statp.st_ctime);
278 #endif
279
280       if (debug_level)
281          printf("%s: len=%d val=%s\n", fname, strlen(where), where);
282
283       decode_stat(where, &statn);
284
285       if (statp.st_dev != statn.st_dev ||
286           statp.st_ino != statn.st_ino ||
287           statp.st_mode != statn.st_mode ||
288           statp.st_nlink != statn.st_nlink ||
289           statp.st_uid != statn.st_uid ||
290           statp.st_gid != statn.st_gid ||
291           statp.st_rdev != statn.st_rdev ||
292           statp.st_size != statn.st_size ||
293           statp.st_blksize != statn.st_blksize ||
294           statp.st_blocks != statn.st_blocks ||
295           statp.st_atime != statn.st_atime ||
296           statp.st_mtime != statn.st_mtime ||
297           statp.st_ctime != statn.st_ctime) {
298
299          printf("%s: %s\n", fname, where);
300          encode_stat(where, &statn, 0, 0);
301          printf("%s: %s\n", fname, where);
302          printf("NOT EQAL\n");
303       }
304
305    }
306    globfree(&my_glob);
307
308    printf("%d files examined\n", i);
309
310    to_base64(UINT32_MAX, where);
311    printf("UINT32_MAX=%s\n", where);
312
313    return 0;
314 }
315 #endif