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