2 Bacula® - The Network Backup Solution
4 Copyright (C) 2005-2010 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Copyright Patrick Powell 1995
31 * This code is based on code written by Patrick Powell
32 * (papowell@astart.com) It may be used for any purpose as long
33 * as this notice remains intact on all source code distributions.
35 * Adapted for Bacula -- note there were lots of bugs in
36 * the original code: %lld and %s were seriously broken, and
37 * with FP turned off %f seg faulted.
39 * Kern Sibbald, November MMV
46 #define FP_OUTPUT 1 /* Bacula uses floating point */
48 /* Define the following if you want all the features of
49 * normal printf, but with all the security problems.
50 * For Bacula we turn this off, and it silently ignores
51 * formats that could pose a security problem.
53 #undef SECURITY_PROBLEM
57 #ifdef HAVE_LONG_DOUBLE
58 #define LDOUBLE long double
60 #define LDOUBLE double
63 int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args);
64 static int32_t fmtstr(char *buffer, int32_t currlen, int32_t maxlen,
65 const char *value, int flags, int min, int max);
66 static int32_t fmtint(char *buffer, int32_t currlen, int32_t maxlen,
67 int64_t value, int base, int min, int max, int flags);
73 static int32_t fmtfp(char *buffer, int32_t currlen, int32_t maxlen,
74 LDOUBLE fvalue, int min, int max, int flags);
76 #define fmtfp(b, c, m, f, min, max, fl) currlen
80 * NOTE!!!! do not use this #define with a construct such
81 * as outch(--place);. It just will NOT work, because the
82 * decrement of place is done ONLY if there is room in the
85 #define outch(c) {int len=currlen; if (currlen < maxlen) \
86 { buffer[len] = (c); currlen++; }}
88 /* format read states */
89 #define DP_S_DEFAULT 0
98 /* format flags - Bits */
99 #define DP_F_MINUS (1 << 0)
100 #define DP_F_PLUS (1 << 1)
101 #define DP_F_SPACE (1 << 2)
102 #define DP_F_NUM (1 << 3)
103 #define DP_F_ZERO (1 << 4)
104 #define DP_F_UP (1 << 5)
105 #define DP_F_UNSIGNED (1 << 6)
106 #define DP_F_DOT (1 << 7)
108 /* Conversion Flags */
111 #define DP_C_LDOUBLE 3
114 #define char_to_int(p) ((p)- '0')
116 #define MAX(p,q) (((p) >= (q)) ? (p) : (q))
119 You might ask why does Bacula have it's own printf routine? Well,
120 There are two reasons: 1. Here (as opposed to library routines), we
121 define %d and %ld to be 32 bit; %lld and %q to be 64 bit. 2. We
122 disable %n for security reasons.
125 int bsnprintf(char *str, int32_t size, const char *fmt, ...)
130 va_start(arg_ptr, fmt);
131 len = bvsnprintf(str, size, fmt, arg_ptr);
137 int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args)
153 state = DP_S_DEFAULT;
154 currlen = flags = cflags = min = 0;
159 while (state != DP_S_DONE) {
160 if ((ch == '\0') || (currlen >= maxlen)) {
200 if (isdigit((unsigned char)ch)) {
201 min = 10 * min + char_to_int(ch);
203 } else if (ch == '*') {
204 min = va_arg(args, int);
219 if (isdigit((unsigned char)ch)) {
222 max = 10 * max + char_to_int(ch);
224 } else if (ch == '*') {
225 max = va_arg(args, int);
240 if (ch == 'l') { /* It's a long long */
246 cflags = DP_C_LDOUBLE;
249 case 'q': /* same as long long */
262 if (cflags == DP_C_INT16) {
263 value = va_arg(args, int32_t);
264 } else if (cflags == DP_C_INT32) {
265 value = va_arg(args, int32_t);
266 } else if (cflags == DP_C_INT64) {
267 value = va_arg(args, int64_t);
269 value = va_arg(args, int);
271 currlen = fmtint(buffer, currlen, maxlen, value, 10, min, max, flags);
279 } else if (ch == 'x') {
281 } else if (ch == 'X') {
287 flags |= DP_F_UNSIGNED;
288 if (cflags == DP_C_INT16) {
289 value = va_arg(args, uint32_t);
290 } else if (cflags == DP_C_INT32) {
291 value = va_arg(args, uint32_t);
292 } else if (cflags == DP_C_INT64) {
293 value = va_arg(args, uint64_t);
295 value = va_arg(args, unsigned int);
297 currlen = fmtint(buffer, currlen, maxlen, value, base, min, max, flags);
300 if (cflags == DP_C_LDOUBLE) {
301 fvalue = va_arg(args, LDOUBLE);
303 fvalue = va_arg(args, double);
305 currlen = fmtfp(buffer, currlen, maxlen, fvalue, min, max, flags);
310 if (cflags == DP_C_LDOUBLE) {
311 fvalue = va_arg(args, LDOUBLE);
313 fvalue = va_arg(args, double);
315 currlen = fmtfp(buffer, currlen, maxlen, fvalue, min, max, flags);
320 if (cflags == DP_C_LDOUBLE) {
321 fvalue = va_arg(args, LDOUBLE);
323 fvalue = va_arg(args, double);
325 currlen = fmtfp(buffer, currlen, maxlen, fvalue, min, max, flags);
328 ch = va_arg(args, int);
332 strvalue = va_arg(args, char *);
333 currlen = fmtstr(buffer, currlen, maxlen, strvalue, flags, min, max);
336 flags |= DP_F_UNSIGNED;
337 if (sizeof(char *) == 4) {
338 value = va_arg(args, uint32_t);
339 } else if (sizeof(char *) == 8) {
340 value = va_arg(args, uint64_t);
342 value = 0; /* we have a problem */
344 currlen = fmtint(buffer, currlen, maxlen, value, 16, min, max, flags);
347 if (cflags == DP_C_INT16) {
349 num = va_arg(args, int16_t *);
350 #ifdef SECURITY_PROBLEM
353 } else if (cflags == DP_C_INT32) {
355 num = va_arg(args, int32_t *);
356 #ifdef SECURITY_PROBLEM
357 *num = (int32_t)currlen;
359 } else if (cflags == DP_C_INT64) {
361 num = va_arg(args, int64_t *);
362 #ifdef SECURITY_PROBLEM
363 *num = (int64_t)currlen;
367 num = va_arg(args, int32_t *);
368 #ifdef SECURITY_PROBLEM
369 *num = (int32_t)currlen;
377 /* not supported yet, treat as next char */
385 state = DP_S_DEFAULT;
386 flags = cflags = min = 0;
393 break; /* some picky compilers need this */
396 if (currlen < maxlen - 1) {
397 buffer[currlen] = '\0';
399 buffer[maxlen - 1] = '\0';
404 static int32_t fmtstr(char *buffer, int32_t currlen, int32_t maxlen,
405 const char *value, int flags, int min, int max)
407 int padlen, strln; /* amount to pad */
412 if (flags & DP_F_DOT && max < 0) { /* Max not specified */
414 } else if (max < 0) {
420 strln = strlen(value);
422 strln = max; /* truncate to max */
424 padlen = min - strln;
428 if (flags & DP_F_MINUS) {
429 padlen = -padlen; /* Left Justify */
436 while (*value && (cnt < max)) {
448 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
450 static int32_t fmtint(char *buffer, int32_t currlen, int32_t maxlen,
451 int64_t value, int base, int min, int max, int flags)
457 int spadlen = 0; /* amount to space pad */
458 int zpadlen = 0; /* amount to zero pad */
460 const char *cvt_string;
468 if (!(flags & DP_F_UNSIGNED)) {
472 } else if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
474 } else if (flags & DP_F_SPACE) {
479 if (flags & DP_F_UP) {
480 caps = 1; /* Should characters be upper case? */
483 cvt_string = caps ? "0123456789ABCDEF" : "0123456789abcdef";
485 convert[place++] = cvt_string[uvalue % (unsigned)base];
486 uvalue = (uvalue / (unsigned)base);
487 } while (uvalue && (place < (int)sizeof(convert)));
488 if (place == (int)sizeof(convert)) {
493 zpadlen = max - place;
494 spadlen = min - MAX(max, place) - (signvalue ? 1 : 0);
499 if (flags & DP_F_ZERO) {
500 zpadlen = MAX(zpadlen, spadlen);
503 if (flags & DP_F_MINUS)
504 spadlen = -spadlen; /* Left Justifty */
506 #ifdef DEBUG_SNPRINTF
507 printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
508 zpadlen, spadlen, min, max, place);
512 while (spadlen > 0) {
524 while (zpadlen > 0) {
530 /* Output digits backward giving correct order */
533 outch(convert[place]);
536 /* Left Justified spaces */
537 while (spadlen < 0) {
546 static LDOUBLE abs_val(LDOUBLE value)
548 LDOUBLE result = value;
556 static LDOUBLE pow10(int exp)
568 static int64_t round(LDOUBLE value)
572 intpart = (int64_t)value;
573 value = value - intpart;
580 static int32_t fmtfp(char *buffer, int32_t currlen, int32_t maxlen,
581 LDOUBLE fvalue, int min, int max, int flags)
595 extern char *fcvt(double value, int ndigit, int *decpt, int *sign);
599 int padlen = 0; /* amount to pad */
607 * AIX manpage says the default is 0, but Solaris says the default
608 * is 6, and sprintf on AIX defaults to 6
613 ufvalue = abs_val(fvalue);
617 else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
619 else if (flags & DP_F_SPACE)
624 caps = 1; /* Should characters be upper case? */
628 intpart = (int64_t)ufvalue;
631 * Sorry, we only support 9 digits past the decimal because of our
637 /* We "cheat" by converting the fractional part to integer by
638 * multiplying by a factor of 10
640 fracpart = round((pow10(max)) * (ufvalue - intpart));
642 if (fracpart >= pow10(max)) {
644 fracpart -= (int64_t)pow10(max);
647 #ifdef DEBUG_SNPRINTF
648 printf("fmtfp: %g %lld.%lld min=%d max=%d\n",
649 (double)fvalue, intpart, fracpart, min, max);
652 /* Convert integer part */
653 cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef";
655 iconvert[iplace++] = cvt_str[(int)(intpart % 10)];
656 intpart = (intpart / 10);
657 } while (intpart && (iplace < (int)sizeof(iconvert)));
659 if (iplace == (int)sizeof(fconvert)) {
662 iconvert[iplace] = 0;
664 /* Convert fractional part */
665 cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef";
667 fconvert[fplace++] = cvt_str[fracpart % 10];
668 fracpart = (fracpart / 10);
669 } while (fracpart && (fplace < (int)sizeof(fconvert)));
671 if (fplace == (int)sizeof(fconvert)) {
674 fconvert[fplace] = 0;
675 #else /* use fcvt() */
680 result = fcvtl(ufvalue, max, &dec_pt, &sig);
682 result = fcvt(ufvalue, max, &dec_pt, &sig);
689 r_length = strlen(result);
693 * Fix broken fcvt implementation returns..
702 if (r_length < dec_pt)
713 fconvert[fplace++] = result[--r_length];
716 while ((dec_pt < 0) && (fplace < max)) {
717 fconvert[fplace++] = '0';
724 for (c = dec_pt; c; iconvert[iplace++] = result[--c]);
725 iconvert[iplace] = '\0';
730 for (c = (r_length - dec_pt); c; fconvert[fplace++] = result[--c]);
732 #endif /* HAVE_FCVT */
734 /* -1 for decimal point, another -1 if we are printing a sign */
735 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
736 zpadlen = max - fplace;
743 if (flags & DP_F_MINUS) {
744 padlen = -padlen; /* Left Justifty */
747 if ((flags & DP_F_ZERO) && (padlen > 0)) {
768 outch(iconvert[iplace]);
772 #ifdef DEBUG_SNPRINTF
773 printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
777 * Decimal point. This should probably use locale to find the correct
784 outch(fconvert[fplace]);
788 while (zpadlen > 0) {
799 #endif /* FP_OUTPUT */
805 #define LONG_STRING 1024
808 int main(int argc, char *argv[])
810 char buf1[LONG_STRING];
811 char buf2[LONG_STRING];
814 const char *fp_fmt[] = {
830 double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
831 0.9996, 1.996, 4.136, 6442452944.1234, 0, 23365.5
834 const char *int_fmt[] = {
855 long int_nums[] = { -1, 134, 91340, 341, 0203, 0 };
857 const char *ll_fmt[] = {
869 int64_t ll_nums[] = { -1976, 789134567890LL, 91340, 34123, 0203, 0 };
871 const char *s_fmt[] = {
887 const char *s_nums[] = { "abc", "def", "ghi", "123", "4567", "a", "bb", "ccccccc", NULL};
894 printf("Testing snprintf format codes against system sprintf...\n");
897 for (x = 0; fp_fmt[x] != NULL; x++)
898 for (y = 0; fp_nums[y] != 0; y++) {
899 bsnprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
900 sprintf(buf2, fp_fmt[x], fp_nums[y]);
901 if (strcmp(buf1, buf2)) {
903 ("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
904 fp_fmt[x], buf1, buf2);
911 for (x = 0; int_fmt[x] != NULL; x++)
912 for (y = 0; int_nums[y] != 0; y++) {
914 bcount = bsnprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
915 printf("%s\n", buf1);
916 pcount = sprintf(buf2, int_fmt[x], int_nums[y]);
917 if (bcount != pcount) {
918 printf("bsnprintf count %d doesn't match sprintf count %d\n",
921 if (strcmp(buf1, buf2)) {
923 ("bsnprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
924 int_fmt[x], buf1, buf2);
930 for (x = 0; ll_fmt[x] != NULL; x++) {
931 for (y = 0; ll_nums[y] != 0; y++) {
933 bcount = bsnprintf(buf1, sizeof(buf1), ll_fmt[x], ll_nums[y]);
934 printf("%s\n", buf1);
935 pcount = sprintf(buf2, ll_fmt[x], ll_nums[y]);
936 if (bcount != pcount) {
937 printf("bsnprintf count %d doesn't match sprintf count %d\n",
940 if (strcmp(buf1, buf2)) {
942 ("bsnprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
943 ll_fmt[x], buf1, buf2);
950 for (x = 0; s_fmt[x] != NULL; x++) {
951 for (y = 0; s_nums[y] != 0; y++) {
953 bcount = bsnprintf(buf1, sizeof(buf1), s_fmt[x], s_nums[y]);
954 printf("%s\n", buf1);
955 pcount = sprintf(buf2, s_fmt[x], s_nums[y]);
956 if (bcount != pcount) {
957 printf("bsnprintf count %d doesn't match sprintf count %d\n",
960 if (strcmp(buf1, buf2)) {
962 ("bsnprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
963 s_fmt[x], buf1, buf2);
971 printf("%d tests failed out of %d.\n", fail, num);
975 #endif /* TEST_PROGRAM */
977 #endif /* USE_BSNPRINTF */