PageRenderTime 34ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/bacula-5.2.10/src/lib/base64.c

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