]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/bsnprintf.c
Detect mount/junction points and ignore junctions in Windows
[bacula/bacula] / bacula / src / lib / bsnprintf.c
index 41aa2901f5f33249389cb1e59cb44aa81c204aec..d808ca8d13f38bf04853f40f322bb47e6fa16742 100644 (file)
@@ -1,27 +1,12 @@
-/*
- * Copyright Patrick Powell 1995
- *
- * This code is based on code written by Patrick Powell
- * (papowell@astart.com) It may be used for any purpose as long
- * as this notice remains intact on all source code distributions.
- *
- * Adapted for Bacula -- note there were lots of bugs in
- *     the original code: %lld and %s were seriously broken, and
- *     with FP turned off %f seg faulted.
- *
- *   Kern Sibbald, November MMV
- *
- *   Version $Id$
- */
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2005-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2005-2010 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
+   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.
 
@@ -30,7 +15,7 @@
    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
+   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.
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
+/*
+ * Copyright Patrick Powell 1995
+ *
+ * This code is based on code written by Patrick Powell
+ * (papowell@astart.com) It may be used for any purpose as long
+ * as this notice remains intact on all source code distributions.
+ *
+ * Adapted for Bacula -- note there were lots of bugs in
+ *     the original code: %lld and %s were seriously broken, and
+ *     with FP turned off %f seg faulted.
+ *
+ *   Kern Sibbald, November MMV
+ *
+ */
 
 
 
 #include "bacula.h"
+#include <wchar.h>
+
 #define FP_OUTPUT 1 /* Bacula uses floating point */
 
 /* Define the following if you want all the features of
@@ -64,6 +65,8 @@
 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,
                    const char *value, int flags, int min, int max);
+static int32_t fmtwstr(char *buffer, int32_t currlen, int32_t maxlen,
+                   const wchar_t *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);
 
@@ -107,10 +110,12 @@ static int32_t fmtfp(char *buffer, int32_t currlen, int32_t maxlen,
 #define DP_F_DOT        (1 << 7)
 
 /* Conversion Flags */
-#define DP_C_INT16   1
-#define DP_C_INT32   2
-#define DP_C_LDOUBLE 3
-#define DP_C_INT64   4
+#define DP_C_INT16    1
+#define DP_C_INT32    2
+#define DP_C_LDOUBLE  3
+#define DP_C_INT64    4
+#define DP_C_WCHAR    5      /* wide characters */
+#define DP_C_SIZE_T   6
 
 #define char_to_int(p) ((p)- '0')
 #undef MAX
@@ -140,6 +145,7 @@ int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args)
    char ch;
    int64_t value;
    char *strvalue;
+   wchar_t *wstrvalue;
    int min;
    int max;
    int state;
@@ -238,11 +244,17 @@ int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args)
          case 'l':
             cflags = DP_C_INT32;
             ch = *format++;
-            if (ch == 'l') {       /* It's a long long */
+            if (ch == 's') {
+               cflags = DP_C_WCHAR;
+            } else if (ch == 'l') {       /* It's a long long */
                cflags = DP_C_INT64;
                ch = *format++;
             }
             break;
+         case 'z':
+            cflags = DP_C_SIZE_T;
+            ch = *format++;
+            break;
          case 'L':
             cflags = DP_C_LDOUBLE;
             ch = *format++;
@@ -266,6 +278,8 @@ int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args)
                value = va_arg(args, int32_t);
             } else if (cflags == DP_C_INT64) {
                value = va_arg(args, int64_t);
+            } else if (cflags == DP_C_SIZE_T) {
+               value = va_arg(args, ssize_t);
             } else {
                value = va_arg(args, int);
             }
@@ -292,6 +306,8 @@ int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args)
                value = va_arg(args, uint32_t);
             } else if (cflags == DP_C_INT64) {
                value = va_arg(args, uint64_t);
+            } else if (cflags == DP_C_SIZE_T) {
+               value = va_arg(args, size_t);
             } else {
                value = va_arg(args, unsigned int);
             }
@@ -330,8 +346,20 @@ int bvsnprintf(char *buffer, int32_t maxlen, const char *format, va_list args)
             outch(ch);
             break;
          case 's':
-            strvalue = va_arg(args, char *);
-            currlen = fmtstr(buffer, currlen, maxlen, strvalue, flags, min, max);
+            if (cflags != DP_C_WCHAR) {
+              strvalue = va_arg(args, char *);
+              if (!strvalue) {
+                 strvalue = (char *)"<NULL>";
+              }
+              currlen = fmtstr(buffer, currlen, maxlen, strvalue, flags, min, max);
+            } else {
+              /* %ls means to edit wide characters */
+              wstrvalue = va_arg(args, wchar_t *);
+              if (!wstrvalue) {
+                 wstrvalue = (wchar_t *)L"<NULL>";
+              }
+              currlen = fmtwstr(buffer, currlen, maxlen, wstrvalue, flags, min, max);
+            }
             break;
          case 'p':
             flags |= DP_F_UNSIGNED;
@@ -415,9 +443,6 @@ static int32_t fmtstr(char *buffer, int32_t currlen, int32_t maxlen,
    } else if (max < 0) {
       max = maxlen;
    }
-   if (!value) {
-      value = "<NULL>";
-   }
    strln = strlen(value);
    if (strln > max) {
       strln = max;                /* truncate to max */
@@ -446,6 +471,48 @@ static int32_t fmtstr(char *buffer, int32_t currlen, int32_t maxlen,
    return currlen;
 }
 
+static int32_t fmtwstr(char *buffer, int32_t currlen, int32_t maxlen,
+                   const wchar_t *value, int flags, int min, int max)
+{
+   int padlen, strln;              /* amount to pad */
+   int cnt = 0;
+   char ch;
+
+
+   if (flags & DP_F_DOT && max < 0) {   /* Max not specified */
+      max = 0;
+   } else if (max < 0) {
+      max = maxlen;
+   }
+   strln = wcslen(value);
+   if (strln > max) {
+      strln = max;                /* truncate to max */
+   }
+   padlen = min - strln;
+   if (padlen < 0) {
+      padlen = 0;
+   }
+   if (flags & DP_F_MINUS) {
+      padlen = -padlen;            /* Left Justify */
+   }
+
+   while (padlen > 0) {
+      outch(' ');
+      --padlen;
+   }
+   while (*value && (cnt < max)) {
+      
+      ch = (*value++) & 0xff;
+      outch(ch);
+      ++cnt;
+   }
+   while (padlen < 0) {
+      outch(' ');
+      ++padlen;
+   }
+   return currlen;
+}
+
 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
 
 static int32_t fmtint(char *buffer, int32_t currlen, int32_t maxlen,
@@ -685,6 +752,7 @@ static int32_t fmtfp(char *buffer, int32_t currlen, int32_t maxlen,
 
    if (!result) {
       r_length = 0;
+      dummy[0] = 0;
       result = dummy;
    } else {
       r_length = strlen(result);
@@ -805,13 +873,14 @@ static int32_t fmtfp(char *buffer, int32_t currlen, int32_t maxlen,
 #ifndef LONG_STRING
 #define LONG_STRING 1024
 #endif
-int main(void)
+
+int main(int argc, char *argv[])
 {
    char buf1[LONG_STRING];
    char buf2[LONG_STRING];
 
 #ifdef FP_OUTPUT
-   char *fp_fmt[] = {
+   const char *fp_fmt[] = {
       "%-1.5f",
       "%1.5f",
       "%123.9f",
@@ -831,7 +900,7 @@ int main(void)
       0.9996, 1.996, 4.136, 6442452944.1234, 0, 23365.5
    };
 #endif
-   char *int_fmt[] = {
+   const char *int_fmt[] = {
       "%-1.5d",
       "%1.5d",
       "%123.9d",
@@ -854,7 +923,7 @@ int main(void)
    };
    long int_nums[] = { -1, 134, 91340, 341, 0203, 0 };
 
-   char *ll_fmt[] = {
+   const char *ll_fmt[] = {
       "%-1.8lld",
       "%1.8lld",
       "%123.9lld",
@@ -868,7 +937,7 @@ int main(void)
    };
    int64_t ll_nums[] = { -1976, 789134567890LL, 91340, 34123, 0203, 0 };
 
-   char *s_fmt[] = {
+   const char *s_fmt[] = {
       "%-1.8s",
       "%1.8s",
       "%123.9s",
@@ -884,7 +953,26 @@ int main(void)
       "%3.s",
       NULL
    };
-   char *s_nums[] = { "abc", "def", "ghi", "123", "4567", "a", "bb", "ccccccc", NULL};
+   const char *s_nums[] = { "abc", "def", "ghi", "123", "4567", "a", "bb", "ccccccc", NULL};
+
+   const char *ls_fmt[] = {
+      "%-1.8ls",
+      "%1.8ls",
+      "%123.9ls",
+      "%5.8ls",
+      "%10.5ls",
+      "% 10.3ls",
+      "%+22.1ls",
+      "%01.3ls",
+      "%ls",
+      "%10ls",
+      "%3ls",
+      "%3.0ls",
+      "%3.ls",
+      NULL
+   };
+   const wchar_t *ls_nums[] = { L"abc", L"def", L"ghi", L"123", L"4567", L"a", L"bb", L"ccccccc", NULL};
+
 
 
    int x, y;
@@ -967,8 +1055,31 @@ int main(void)
       }
    }
 
+   for (x = 0; ls_fmt[x] != NULL; x++) {
+      for (y = 0; ls_nums[y] != 0; y++) {
+         int pcount, bcount;
+         bcount = bsnprintf(buf1, sizeof(buf1), ls_fmt[x], ls_nums[y]);
+         printf("%s\n", buf1);
+         pcount = sprintf(buf2, ls_fmt[x], ls_nums[y]);
+         if (bcount != pcount) {
+            printf("bsnprintf count %d doesn't match sprintf count %d\n",
+               bcount, pcount);
+         }
+         if (strcmp(buf1, buf2)) {
+            printf
+               ("bsnprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
+                ls_fmt[x], buf1, buf2);
+            fail++;
+         }
+         num++;
+      }
+   }
+
+
 
    printf("%d tests failed out of %d.\n", fail, num);
+
+   exit(fail > 0);
 }
 #endif /* TEST_PROGRAM */