]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/base64.c
ebl add Error status in update volume=xxx status=yyyy
[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    Bacula® - The Network Backup Solution
10
11    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
12
13    The main author of Bacula is Kern Sibbald, with contributions from
14    many others, a complete list can be found in the file AUTHORS.
15    This program is Free Software; you can redistribute it and/or
16    modify it under the terms of version two of the GNU General Public
17    License as published by the Free Software Foundation plus additions
18    that are listed in the file LICENSE.
19
20    This program is distributed in the hope that it will be useful, but
21    WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23    General Public License for more details.
24
25    You should have received a copy of the GNU General Public License
26    along with this program; if not, write to the Free Software
27    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28    02110-1301, USA.
29
30    Bacula® is a registered trademark of John Walker.
31    The licensor of Bacula is the Free Software Foundation Europe
32    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
33    Switzerland, email:ftf@fsfeurope.org.
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          printf("Cannot stat %s: %s\n", fname, strerror(errno));
251          continue;
252       }
253       encode_stat(where, &statp);
254
255       printf("Encoded stat=%s\n", where);
256
257 #ifdef xxx
258       p = where;
259       p += to_base64((intmax_t)(statp.st_atime), p);
260       *p++ = ' ';
261       p += to_base64((intmax_t)t, p);
262       printf("%s %s\n", fname, where);
263
264       printf("%s %lld\n", "st_dev", (intmax_t)statp.st_dev);
265       printf("%s %lld\n", "st_ino", (intmax_t)statp.st_ino);
266       printf("%s %lld\n", "st_mode", (intmax_t)statp.st_mode);
267       printf("%s %lld\n", "st_nlink", (intmax_t)statp.st_nlink);
268       printf("%s %lld\n", "st_uid", (intmax_t)statp.st_uid);
269       printf("%s %lld\n", "st_gid", (intmax_t)statp.st_gid);
270       printf("%s %lld\n", "st_rdev", (intmax_t)statp.st_rdev);
271       printf("%s %lld\n", "st_size", (intmax_t)statp.st_size);
272       printf("%s %lld\n", "st_blksize", (intmax_t)statp.st_blksize);
273       printf("%s %lld\n", "st_blocks", (intmax_t)statp.st_blocks);
274       printf("%s %lld\n", "st_atime", (intmax_t)statp.st_atime);
275       printf("%s %lld\n", "st_mtime", (intmax_t)statp.st_mtime);
276       printf("%s %lld\n", "st_ctime", (intmax_t)statp.st_ctime);
277 #endif
278
279       if (debug_level)
280          printf("%s: len=%d val=%s\n", fname, strlen(where), where);
281
282       decode_stat(where, &statn);
283
284       if (statp.st_dev != statn.st_dev ||
285           statp.st_ino != statn.st_ino ||
286           statp.st_mode != statn.st_mode ||
287           statp.st_nlink != statn.st_nlink ||
288           statp.st_uid != statn.st_uid ||
289           statp.st_gid != statn.st_gid ||
290           statp.st_rdev != statn.st_rdev ||
291           statp.st_size != statn.st_size ||
292           statp.st_blksize != statn.st_blksize ||
293           statp.st_blocks != statn.st_blocks ||
294           statp.st_atime != statn.st_atime ||
295           statp.st_mtime != statn.st_mtime ||
296           statp.st_ctime != statn.st_ctime) {
297
298          printf("%s: %s\n", fname, where);
299          encode_stat(where, &statn);
300          printf("%s: %s\n", fname, where);
301          printf("NOT EQAL\n");
302       }
303
304    }
305    globfree(&my_glob);
306
307    printf("%d files examined\n", i);
308
309    to_base64(UINT32_MAX, where);
310    printf("UINT32_MAX=%s\n", where);
311
312    return 0;
313 }
314 #endif