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