/*
Bacula® - The Network Backup Solution
- Copyright (C) 2005-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2005-2008 Free Software Foundation Europe e.V.
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 two of the GNU General Public
- License as published by the Free Software Foundation plus additions
- that are listed in the file LICENSE.
+ 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ 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.
#include "bacula.h"
#define FP_OUTPUT 1 /* Bacula uses floating point */
+
/* Define the following if you want all the features of
* normal printf, but with all the security problems.
* For Bacula we turn this off, and it silently ignores
int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args);
static int32_t fmtstr(char *buffer, int32_t currlen, int32_t maxlen,
- char *value, int flags, int min, int max);
+ const char *value, int flags, int min, int max);
static int32_t fmtint(char *buffer, int32_t currlen, int32_t maxlen,
int64_t value, int base, int min, int max, int flags);
#define fmtfp(b, c, m, f, min, max, fl) currlen
#endif
-#define outch(c) {int len=currlen; if (currlen++ < maxlen) { buffer[len] = (c);}}
-
+/*
+ * NOTE!!!! do not use this #define with a construct such
+ * as outch(--place);. It just will NOT work, because the
+ * decrement of place is done ONLY if there is room in the
+ * output buffer.
+ */
+#define outch(c) {int len=currlen; if (currlen < maxlen) \
+ { buffer[len] = (c); currlen++; }}
/* format read states */
#define DP_S_DEFAULT 0
/* Conversion Flags */
#define DP_C_INT16 1
-#define DP_C_INT32 2
+#define DP_C_INT32 2
#define DP_C_LDOUBLE 3
#define DP_C_INT64 4
*buffer = 0;
while (state != DP_S_DONE) {
- if ((ch == '\0') || (currlen >= maxlen))
+ if ((ch == '\0') || (currlen >= maxlen)) {
state = DP_S_DONE;
-
+ }
switch (state) {
case DP_S_DEFAULT:
if (ch == '%') {
currlen = fmtfp(buffer, currlen, maxlen, fvalue, min, max, flags);
break;
case 'c':
- outch(va_arg(args, int));
+ ch = va_arg(args, int);
+ outch(ch);
break;
case 's':
strvalue = va_arg(args, char *);
break;
case 'p':
flags |= DP_F_UNSIGNED;
- strvalue = va_arg(args, char *);
- currlen = fmtint(buffer, currlen, maxlen, (long)strvalue, 16, min, max, flags);
+ if (sizeof(char *) == 4) {
+ value = va_arg(args, uint32_t);
+ } else if (sizeof(char *) == 8) {
+ value = va_arg(args, uint64_t);
+ } else {
+ value = 0; /* we have a problem */
+ }
+ currlen = fmtint(buffer, currlen, maxlen, value, 16, min, max, flags);
break;
case 'n':
if (cflags == DP_C_INT16) {
}
static int32_t fmtstr(char *buffer, int32_t currlen, int32_t maxlen,
- char *value, int flags, int min, int max)
+ const char *value, int flags, int min, int max)
{
int padlen, strln; /* amount to pad */
int cnt = 0;
+ char ch;
- if (value == 0) {
- value = "<NULL>";
- }
if (flags & DP_F_DOT && max < 0) { /* Max not specified */
max = 0;
} else if (max < 0) {
max = maxlen;
}
+ if (!value) {
+ value = "<NULL>";
+ }
strln = strlen(value);
if (strln > max) {
strln = max; /* truncate to max */
--padlen;
}
while (*value && (cnt < max)) {
- outch(*value++);
+ ch = *value++;
+ outch(ch);
++cnt;
}
while (padlen < 0) {
{
int signvalue = 0;
uint64_t uvalue;
- char convert[20];
+ char convert[25];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
int caps = 0;
+ const char *cvt_string;
if (max < 0) {
max = 0;
caps = 1; /* Should characters be upper case? */
}
+ cvt_string = caps ? "0123456789ABCDEF" : "0123456789abcdef";
do {
- convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
- [uvalue % (unsigned)base];
+ convert[place++] = cvt_string[uvalue % (unsigned)base];
uvalue = (uvalue / (unsigned)base);
- } while (uvalue && (place < 20));
- if (place == 20) {
+ } while (uvalue && (place < (int)sizeof(convert)));
+ if (place == (int)sizeof(convert)) {
place--;
}
convert[place] = 0;
}
}
- /* Digits */
+ /* Output digits backward giving correct order */
while (place > 0) {
- outch(convert[--place]);
+ place--;
+ outch(convert[place]);
}
/* Left Justified spaces */
return result;
}
-static long round(LDOUBLE value)
+static int64_t round(LDOUBLE value)
{
- long intpart;
+ int64_t intpart;
- intpart = (long)value;
+ intpart = (int64_t)value;
value = value - intpart;
if (value >= 0.5)
intpart++;
int signvalue = 0;
LDOUBLE ufvalue;
#ifndef HAVE_FCVT
- char iconvert[20];
- char fconvert[20];
+ char iconvert[311];
+ char fconvert[311];
#else
char iconvert[311];
char fconvert[311];
char *result;
+ char dummy[10];
int dec_pt, sig;
int r_length;
extern char *fcvt(double value, int ndigit, int *decpt, int *sign);
int caps = 0;
int64_t intpart;
int64_t fracpart;
+ const char *cvt_str;
/*
* AIX manpage says the default is 0, but Solaris says the default
#endif
#ifndef HAVE_FCVT
- intpart = (long)ufvalue;
+ intpart = (int64_t)ufvalue;
/*
* Sorry, we only support 9 digits past the decimal because of our
intpart++;
fracpart -= (int64_t)pow10(max);
}
+
#ifdef DEBUG_SNPRINTF
- printf("fmtfp: %g %d.%d min=%d max=%d\n",
+ printf("fmtfp: %g %lld.%lld min=%d max=%d\n",
(double)fvalue, intpart, fracpart, min, max);
#endif
/* Convert integer part */
+ cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef";
do {
- iconvert[iplace++] =
- (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10];
+ iconvert[iplace++] = cvt_str[(int)(intpart % 10)];
intpart = (intpart / 10);
- } while (intpart && (iplace < 20));
- if (iplace == 20)
+ } while (intpart && (iplace < (int)sizeof(iconvert)));
+
+ if (iplace == (int)sizeof(fconvert)) {
iplace--;
+ }
iconvert[iplace] = 0;
/* Convert fractional part */
+ cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef";
do {
- fconvert[fplace++] =
- (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10];
+ fconvert[fplace++] = cvt_str[fracpart % 10];
fracpart = (fracpart / 10);
- } while (fracpart && (fplace < 20));
- if (fplace == 20)
+ } while (fracpart && (fplace < (int)sizeof(fconvert)));
+
+ if (fplace == (int)sizeof(fconvert)) {
fplace--;
+ }
fconvert[fplace] = 0;
#else /* use fcvt() */
- if (max > 310)
+ if (max > 310) {
max = 310;
+ }
# ifdef HAVE_FCVTL
result = fcvtl(ufvalue, max, &dec_pt, &sig);
# else
result = fcvt(ufvalue, max, &dec_pt, &sig);
# endif
- r_length = strlen(result);
+ if (!result) {
+ r_length = 0;
+ result = dummy;
+ } else {
+ r_length = strlen(result);
+ }
/*
* Fix broken fcvt implementation returns..
fplace = 0;
- while (r_length)
+ while (r_length) {
fconvert[fplace++] = result[--r_length];
+ }
while ((dec_pt < 0) && (fplace < max)) {
fconvert[fplace++] = '0';
}
while (iplace > 0) {
- outch(iconvert[--iplace]);
+ iplace--;
+ outch(iconvert[iplace]);
}
if (max > 0) {
outch('.');
while (fplace > 0) {
- outch(fconvert[--fplace]);
+ fplace--;
+ outch(fconvert[fplace]);
}
}
NULL
};
double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
- 0.9996, 1.996, 4.136, 6442452944.1234, 0
+ 0.9996, 1.996, 4.136, 6442452944.1234, 0, 23365.5
};
#endif
char *int_fmt[] = {