-/*
- * Generic base 64 input and output routines
- *
- * Written by Kern E. Sibbald, March MM.
- *
- * Version $Id$
- */
-
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Bacula® - The Network Backup Solution
+
+ Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of
- the License, or (at your option) any later version.
+ The main author of Bacula is Kern Sibbald, with contributions from
+ many others, a complete list can be found in the file AUTHORS.
+ This program is Free Software; you can redistribute it and/or
+ modify it under the terms of version three of the GNU Affero General Public
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
- You should have received a copy of the GNU General Public
- License along with this program; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+ Bacula® is a registered trademark of Kern Sibbald.
+ The licensor of Bacula is the Free Software Foundation Europe
+ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+ Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ * Generic base 64 input and output routines
+ *
+ * Written by Kern E. Sibbald, March MM.
+ *
+ * Version $Id$
*/
#include "bacula.h"
+
#ifdef TEST_MODE
#include <glob.h>
#endif
};
static int base64_inited = 0;
-static uint8_t base64_map[128];
-
+static uint8_t base64_map[256];
+
/* Initialize the Base 64 conversion routines */
void
base64_init(void)
-{
- int i;
+{
+ int i;
memset(base64_map, 0, sizeof(base64_map));
for (i=0; i<64; i++)
base64_map[(uint8_t)base64_digits[i]] = i;
* stored (not including the EOS).
*/
int
-to_base64(intmax_t value, char *where)
+to_base64(int64_t value, char *where)
{
- uintmax_t val;
+ uint64_t val;
int i = 0;
int n;
val = value;
where[i] = 0;
do {
- where[--i] = base64_digits[val & (uintmax_t)0x3F];
+ where[--i] = base64_digits[val & (uint64_t)0x3F];
val >>= 6;
} while (val);
return n;
* Returns the value.
*/
int
-from_base64(intmax_t *value, char *where)
-{
- uintmax_t val = 0;
+from_base64(int64_t *value, char *where)
+{
+ uint64_t val = 0;
int i, neg;
- if (!base64_inited)
+ if (!base64_inited)
base64_init();
/* Check if it is negative */
i = neg = 0;
val <<= 6;
val += base64_map[(uint8_t)where[i++]];
}
-
- *value = neg ? -(intmax_t)val : (intmax_t)val;
- return i;
-}
-/* Encode a stat structure into a base64 character string */
-void
-encode_stat(char *buf, struct stat *statp)
-{
- char *p = buf;
- /*
- * NOTE: we should use rdev as major and minor device if
- * it is a block or char device (S_ISCHR(statp->st_mode)
- * or S_ISBLK(statp->st_mode)). In all other cases,
- * it is not used.
- *
- */
- p += to_base64((intmax_t)statp->st_dev, p);
- *p++ = ' '; /* separate fields with a space */
- p += to_base64((intmax_t)statp->st_ino, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_mode, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_nlink, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_uid, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_gid, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_rdev, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_size, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_blksize, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_blocks, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_atime, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_mtime, p);
- *p++ = ' ';
- p += to_base64((intmax_t)statp->st_ctime, p);
- *p++ = 0;
- return;
+ *value = neg ? -(int64_t)val : (int64_t)val;
+ return i;
}
-/* Decode a stat packet from base64 characters */
-void
-decode_stat(char *buf, struct stat *statp)
-{
- char *p = buf;
- intmax_t val;
-
- p += from_base64(&val, p);
- statp->st_dev = val;
- p++; /* skip space */
- p += from_base64(&val, p);
- statp->st_ino = val;
- p++;
- p += from_base64(&val, p);
- statp->st_mode = val;
- p++;
- p += from_base64(&val, p);
- statp->st_nlink = val;
- p++;
- p += from_base64(&val, p);
- statp->st_uid = val;
- p++;
- p += from_base64(&val, p);
- statp->st_gid = val;
- p++;
- p += from_base64(&val, p);
- statp->st_rdev = val;
- p++;
- p += from_base64(&val, p);
- statp->st_size = val;
- p++;
- p += from_base64(&val, p);
- statp->st_blksize = val;
- p++;
- p += from_base64(&val, p);
- statp->st_blocks = val;
- p++;
- p += from_base64(&val, p);
- statp->st_atime = val;
- p++;
- p += from_base64(&val, p);
- statp->st_mtime = val;
- p++;
- p += from_base64(&val, p);
- statp->st_ctime = val;
- p++;
-}
-
/*
* Encode binary data in bin of len bytes into
* buf as base64 characters.
*
+ * If compatible is true, the bin_to_base64 routine will be compatible
+ * with what the rest of the world uses.
+ *
* Returns: the number of characters stored not
- * including the EOS
+ * including the EOS
*/
int
-bin_to_base64(char *buf, char *bin, int len)
+bin_to_base64(char *buf, int buflen, char *bin, int binlen, int compatible)
{
uint32_t reg, save, mask;
int rem, i;
reg = 0;
rem = 0;
- for (i=0; i<len; ) {
+ buflen--; /* allow for storing EOS */
+ for (i=0; i < binlen; ) {
if (rem < 6) {
- reg <<= 8;
- reg |= (uint8_t)bin[i++];
- rem += 8;
+ reg <<= 8;
+ if (compatible) {
+ reg |= (uint8_t)bin[i++];
+ } else {
+ reg |= (int8_t)bin[i++];
+ }
+ rem += 8;
}
save = reg;
reg >>= (rem - 6);
- buf[j++] = base64_digits[reg & (uint32_t)0x3F];
+ if (j < buflen) {
+ buf[j++] = base64_digits[reg & 0x3F];
+ }
reg = save;
rem -= 6;
}
- if (rem) {
- mask = 1;
- for (i=1; i<rem; i++) {
- mask = (mask << 1) | 1;
+ if (rem && j < buflen) {
+ mask = (1 << rem) - 1;
+ if (compatible) {
+ buf[j++] = base64_digits[(reg & mask) << (6 - rem)];
+ } else {
+ buf[j++] = base64_digits[reg & mask];
}
- buf[j++] = base64_digits[reg & mask];
}
buf[j] = 0;
return j;
}
+/*
+ * Decode base64 data in bin of len bytes into
+ * buf as binary characters.
+ *
+ * the base64_to_bin routine is compatible with what the rest of the world
+ * uses.
+ *
+ * Returns: the number of characters stored not
+ * including the EOS
+ */
+int base64_to_bin(char *dest, int dest_size, char *src, int srclen)
+{
+ int nprbytes;
+ uint8_t *bufout;
+ uint8_t *bufplain = (uint8_t*) dest;
+ const uint8_t *bufin;
+
+ if (!base64_inited)
+ base64_init();
+
+ if (dest_size < (((srclen + 3) / 4) * 3)) {
+ /* dest buffer too small */
+ *dest = 0;
+ return 0;
+ }
+
+ bufin = (const uint8_t *) src;
+ while ((*bufin != ' ') && (srclen != 0)) {
+ bufin++;
+ srclen--;
+ }
+
+ nprbytes = bufin - (const uint8_t *) src;
+ bufin = (const uint8_t *) src;
+ bufout = (uint8_t *) bufplain;
+
+ while (nprbytes > 4)
+ {
+ *(bufout++) = (base64_map[bufin[0]] << 2 | base64_map[bufin[1]] >> 4);
+ *(bufout++) = (base64_map[bufin[1]] << 4 | base64_map[bufin[2]] >> 2);
+ *(bufout++) = (base64_map[bufin[2]] << 6 | base64_map[bufin[3]]);
+ bufin += 4;
+ nprbytes -= 4;
+ }
+
+ /* Bacula base64 strings are not always padded with = */
+ if (nprbytes > 1) {
+ *(bufout++) = (base64_map[bufin[0]] << 2 | base64_map[bufin[1]] >> 4);
+ }
+ if (nprbytes > 2) {
+ *(bufout++) = (base64_map[bufin[1]] << 4 | base64_map[bufin[2]] >> 2);
+ }
+ if (nprbytes > 3) {
+ *(bufout++) = (base64_map[bufin[2]] << 6 | base64_map[bufin[3]]);
+ }
+ *bufout = 0;
+
+ return (bufout - (uint8_t *) dest);
+}
+
#ifdef BIN_TEST
int main(int argc, char *argv[])
{
char junk[100];
int i;
- for (i=0; i < 100; i++) {
- bin_to_base64(buf, (char *)&xx, 4);
+#ifdef xxxx
+ for (i=0; i < 1000; i++) {
+ bin_to_base64(buf, sizeof(buf), (char *)&xx, 4, true);
printf("xx=%s\n", buf);
xx++;
}
- len = bin_to_base64(buf, junk, 16);
+#endif
+ junk[0] = 0xFF;
+ for (i=1; i<100; i++) {
+ junk[i] = junk[i-1]-1;
+ }
+ len = bin_to_base64(buf, sizeof(buf), junk, 16, true);
printf("len=%d junk=%s\n", len, buf);
+
+ strcpy(junk, "This is a sample stringa");
+ len = bin_to_base64(buf, sizeof(buf), junk, strlen(junk), true);
+ buf[len] = 0;
+ base64_to_bin(junk, sizeof(junk), buf, len);
+ printf("buf=<%s>\n", junk);
return 0;
}
#endif
#ifdef TEST_MODE
static int errfunc(const char *epath, int eernoo)
{
- Dmsg0(-1, "in errfunc\n");
+ printf("in errfunc\n");
return 1;
}
* Test the base64 routines by encoding and decoding
* lstat() packets.
*/
-int main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
char where[500];
int i;
struct stat statp;
struct stat statn;
int debug_level = 0;
+ char *p;
+ int32_t j;
+ time_t t = 1028712799;
if (argc > 1 && strcmp(argv[1], "-v") == 0)
- debug_level++;
+ debug_level++;
base64_init();
my_glob.gl_offs = 0;
- glob("/etc/*", GLOB_MARK, errfunc, &my_glob);
+ glob("/etc/grub.conf", GLOB_MARK, errfunc, &my_glob);
for (i=0; my_glob.gl_pathv[i]; i++) {
fname = my_glob.gl_pathv[i];
if (lstat(fname, &statp) < 0) {
- printf("Cannot stat %s: %s\n", fname, strerror(errno));
- continue;
+ berrno be;
+ printf("Cannot stat %s: %s\n", fname, be.bstrerror(errno));
+ continue;
}
- encode_stat(where, &statp);
+ encode_stat(where, &statp, sizeof(statp), 0, 0);
+
+ printf("Encoded stat=%s\n", where);
+
+#ifdef xxx
+ p = where;
+ p += to_base64((int64_t)(statp.st_atime), p);
+ *p++ = ' ';
+ p += to_base64((int64_t)t, p);
+ printf("%s %s\n", fname, where);
+
+ printf("%s %lld\n", "st_dev", (int64_t)statp.st_dev);
+ printf("%s %lld\n", "st_ino", (int64_t)statp.st_ino);
+ printf("%s %lld\n", "st_mode", (int64_t)statp.st_mode);
+ printf("%s %lld\n", "st_nlink", (int64_t)statp.st_nlink);
+ printf("%s %lld\n", "st_uid", (int64_t)statp.st_uid);
+ printf("%s %lld\n", "st_gid", (int64_t)statp.st_gid);
+ printf("%s %lld\n", "st_rdev", (int64_t)statp.st_rdev);
+ printf("%s %lld\n", "st_size", (int64_t)statp.st_size);
+ printf("%s %lld\n", "st_blksize", (int64_t)statp.st_blksize);
+ printf("%s %lld\n", "st_blocks", (int64_t)statp.st_blocks);
+ printf("%s %lld\n", "st_atime", (int64_t)statp.st_atime);
+ printf("%s %lld\n", "st_mtime", (int64_t)statp.st_mtime);
+ printf("%s %lld\n", "st_ctime", (int64_t)statp.st_ctime);
+#endif
if (debug_level)
printf("%s: len=%d val=%s\n", fname, strlen(where), where);
-
- decode_stat(where, &statn);
-
- if (statp.st_dev != statn.st_dev ||
- statp.st_ino != statn.st_ino ||
- statp.st_mode != statn.st_mode ||
- statp.st_nlink != statn.st_nlink ||
- statp.st_uid != statn.st_uid ||
- statp.st_gid != statn.st_gid ||
- statp.st_rdev != statn.st_rdev ||
- statp.st_size != statn.st_size ||
- statp.st_blksize != statn.st_blksize ||
- statp.st_blocks != statn.st_blocks ||
- statp.st_atime != statn.st_atime ||
- statp.st_mtime != statn.st_mtime ||
- statp.st_ctime != statn.st_ctime) {
+
+ decode_stat(where, &statn, sizeof(statn), &j);
+
+ if (statp.st_dev != statn.st_dev ||
+ statp.st_ino != statn.st_ino ||
+ statp.st_mode != statn.st_mode ||
+ statp.st_nlink != statn.st_nlink ||
+ statp.st_uid != statn.st_uid ||
+ statp.st_gid != statn.st_gid ||
+ statp.st_rdev != statn.st_rdev ||
+ statp.st_size != statn.st_size ||
+ statp.st_blksize != statn.st_blksize ||
+ statp.st_blocks != statn.st_blocks ||
+ statp.st_atime != statn.st_atime ||
+ statp.st_mtime != statn.st_mtime ||
+ statp.st_ctime != statn.st_ctime) {
printf("%s: %s\n", fname, where);
- encode_stat(where, &statn);
+ encode_stat(where, &statn, sizeof(statn), 0, 0);
printf("%s: %s\n", fname, where);
printf("NOT EQAL\n");
}
printf("%d files examined\n", i);
+ to_base64(UINT32_MAX, where);
+ printf("UINT32_MAX=%s\n", where);
+
return 0;
-}
+}
#endif