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