]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/edit.c
Implement kb,mb,and gb modifiers + add Makefile to win32 directory + Michel Meyers...
[bacula/bacula] / bacula / src / lib / edit.c
index b601c53c068e8139463156c9adecee1fe5672da0..b9e24a7bc3828ba09d88a6cdf5f0d75ea8b6ab63 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include "bacula.h"
+#include <math.h>
 
 /* We assume ASCII input and don't worry about overflow */
 uint64_t str_to_uint64(char *str) 
@@ -93,6 +94,59 @@ char *edit_uint64(uint64_t val, char *buf)
    return buf;
 }
 
+/*
+ * Given a string "str", separate the integer part into
+ *   str, and the modifier into mod.
+ */
+static bool get_modifier(char *str, char *mod, int mod_len)
+{
+   int i, len;
+   /*
+    * Look for modifier by walking back looking for the first
+    *  space or digit.
+    */
+   strip_trailing_junk(str);
+   len = strlen(str);
+   /* Strip trailing spaces */
+   for (i=len; i>0; i--) {
+      if (!B_ISSPACE(str[i-1])) {
+        break;
+      }
+      str[i-1] = 0;
+   }
+   /* Find beginning of the modifier */
+   for ( ; i>0; i--) {
+      if (!B_ISALPHA(str[i-1])) {
+        break;
+      }
+   }
+   /* If not found, error */
+   if (i == 0 || i == len) {
+      Dmsg2(200, "error i=%d len=%d\n", i, len);
+      return false;
+   }
+   /* Move modifier to mod */
+   bstrncpy(mod, &str[i], mod_len);
+   if (strlen(mod) == 0) {              /* Make sure we have a modifier */
+      Dmsg0(200, "No modifier found\n");
+      return false;
+   }
+   Dmsg2(200, "in=%s  mod=%s:\n", str, mod);
+   /* Backup over any spaces in front of modifier */
+   for ( ; i>0; i--) {
+      if (B_ISSPACE(str[i-1])) {
+        continue;
+      }
+      str[i] = 0;
+      break;
+   }
+   /* The remainder (beginning) should be our number */
+   if (!is_a_number(str)) {
+      Dmsg0(200, "input not a number\n");
+      return false;
+   }
+   return true;
+}
 
 /*
  * Convert a string duration to utime_t (64 bit seconds)
@@ -101,39 +155,41 @@ char *edit_uint64(uint64_t val, char *buf)
  */
 int duration_to_utime(char *str, utime_t *value)
 {
-   int i, ch, len;
+   int i, mod_len;
    double val;
-   /* Default to 1 day if no modifier given */
-   static int  mod[] = {'*',       's', 'n', 'h', 'd',      'w',    'm', 'q', 'y', 0};
-   static int mult[] = {60*60*24,   1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30, 
-                 60*60*24*91, 60*60*24*365};
+   char mod_str[20];
+   /*
+    * The "n" = mins and months appears before minutes so that m maps
+    *   to months. These "kludges" make it compatible with pre 1.31 
+    *  Baculas.
+    */
+   static const char *mod[] = {"n", "seconds", "months", "minutes", 
+                  "hours", "days", "weeks",   "quarters",   "years", NULL};
+   static const int32_t mult[] = {60,  1, 60*60*24*30, 60, 
+                 60*60, 60*60*24, 60*60*24*7, 60*60*24*91, 60*60*24*365};
 
-   /* Look for modifier */
-   len = strlen(str);
-   ch = str[len - 1];
-   i = 0;
-   if (B_ISALPHA(ch)) {
-      if (B_ISUPPER(ch)) {
-        ch = tolower(ch);
-      }
-      while (mod[++i] != 0) {
-        if (ch == mod[i]) {
-           len--;
-           str[len] = 0; /* strip modifier */
-           break;
-        }
+   if (!get_modifier(str, mod_str, sizeof(mod_str))) {
+      return 0;
+   }
+   /* Now find the multiplier corresponding to the modifier */
+   mod_len = strlen(mod_str);
+   for (i=0; mod[i]; i++) {
+      if (strncasecmp(mod_str, mod[i], mod_len) == 0) {
+        break;
       }
    }
-   if (mod[i] == 0 || !is_a_number(str)) {
-      return 0;
+   if (mod[i] == NULL) {
+      Dmsg0(200, "Modifier not found\n");
+      return 0;                      /* modifer not found */
    }
+   Dmsg2(200, "str=%s: mult=%d\n", str, mult[i]);
+   errno = 0;
    val = strtod(str, NULL);
    if (errno != 0 || val < 0) {
       return 0;
    }
-   *value = (utime_t)(val * mult[i]);
+  *value = (utime_t)(val * mult[i]);
    return 1;
-
 }
 
 /*
@@ -142,14 +198,14 @@ int duration_to_utime(char *str, utime_t *value)
 char *edit_utime(utime_t val, char *buf)
 {
    char mybuf[30];
-   static int mult[] = {60*60*24*365, 60*60*24*30, 60*60*24, 60*60, 60};
-   static char *mod[]  = {"year",  "month",  "day", "hour", "min"};
+   static const int32_t mult[] = {60*60*24*365, 60*60*24*30, 60*60*24, 60*60, 60};
+   static const char *mod[]  = {"year",  "month",  "day", "hour", "min"};
    int i;
    uint32_t times;
 
    *buf = 0;
    for (i=0; i<5; i++) {
-      times = val / mult[i];
+      times = (uint32_t)(val / mult[i]);
       if (times > 0) {
         val = val - (utime_t)times * mult[i];
          sprintf(mybuf, "%d %s%s ", times, mod[i], times>1?"s":"");
@@ -170,55 +226,41 @@ char *edit_utime(utime_t val, char *buf)
  * Returns 0: if error
           1: if OK, and value stored in value
  */
-int size_to_uint64(char *str, int str_len, uint64_t *rtn_value)
+int size_to_uint64(char *str, int str_len, uint64_t *value)
 {
-   int i, ch;
-   double value;
-   int mod[]  = {'*', 'k', 'm', 'g', 0}; /* first item * not used */
-   uint64_t mult[] = {1,            /* byte */
-                     1024,          /* kilobyte */
-                     1048576,       /* megabyte */
-                     1073741824};   /* gigabyte */
-
-#ifdef we_have_a_compiler_that_works
-   int mod[]  = {'*', 'k', 'm', 'g', 't', 0};
-   uint64_t mult[] = {1,            /* byte */
-                     1024,          /* kilobyte */
-                     1048576,       /* megabyte */
-                     1073741824,    /* gigabyte */
-                     1099511627776};/* terabyte */
-#endif
-
-   Dmsg0(400, "Enter sized to uint64\n");
+   int i, mod_len;
+   double val;
+   char mod_str[20];
+   static const char *mod[]  = {"*", "k", "kb", "m", "mb",  "g", "gb",  NULL}; /* first item * not used */
+   const int64_t mult[] = {1,            /* byte */
+                          1024,          /* kilobyte */
+                          1000,          /* kb kilobyte */
+                          1048576,       /* megabyte */
+                          1000000,       /* mb megabyte */
+                          1073741824,    /* gigabyte */
+                          1000000000};   /* gb gigabyte */
 
-   /* Look for modifier */
-   ch = str[str_len - 1];
-   i = 0;
-   if (B_ISALPHA(ch)) {
-      if (B_ISUPPER(ch)) {
-        ch = tolower(ch);
-      }
-      while (mod[++i] != 0) {
-        if (ch == mod[i]) {
-           str_len--;
-           str[str_len] = 0; /* strip modifier */
-           break;
-        }
+   if (!get_modifier(str, mod_str, sizeof(mod_str))) {
+      return 0;
+   }
+   /* Now find the multiplier corresponding to the modifier */
+   mod_len = strlen(mod_str);
+   for (i=0; mod[i]; i++) {
+      if (strncasecmp(mod_str, mod[i], mod_len) == 0) {
+        break;
       }
    }
-   if (mod[i] == 0 || !is_a_number(str)) {
-      return 0;
+   if (mod[i] == NULL) {
+      Dmsg0(200, "Modifier not found\n");
+      return 0;                      /* modifer not found */
    }
-   Dmsg3(400, "size str=:%s: %f i=%d\n", str, strtod(str, NULL), i);
-
-   value = (uint64_t)strtod(str, NULL);
-   Dmsg1(400, "Int value = %d\n", (int)value);
-   if (errno != 0 || value < 0) {
+   Dmsg2(200, "str=%s: mult=%d\n", str, mult[i]);
+   errno = 0;
+   val = strtod(str, NULL);
+   if (errno != 0 || val < 0) {
       return 0;
    }
-   *rtn_value = (uint64_t)(value * mult[i]);
-   Dmsg2(400, "Full value = %f %" lld "\n", strtod(str, NULL) * mult[i],
-       value *mult[i]);
+  *value = (utime_t)(val * mult[i]);
    return 1;
 }
 
@@ -228,13 +270,13 @@ int size_to_uint64(char *str, int str_len, uint64_t *rtn_value)
  */
 int is_a_number(const char *n)
 {
-   int digit_seen = 0;
+   bool digit_seen = false;
 
    if( *n == '-' || *n == '+' ) {
       n++;
    }
    while (B_ISDIGIT(*n)) {
-      digit_seen = 1;
+      digit_seen = true;
       n++;
    }
    if (digit_seen && *n == '.') {
@@ -254,14 +296,56 @@ int is_a_number(const char *n)
  */
 int is_an_integer(const char *n)
 {
-   int digit_seen = 0;
+   bool digit_seen = false;
    while (B_ISDIGIT(*n)) {
-      digit_seen = 1;
+      digit_seen = true;
       n++;
    }
    return digit_seen && *n==0;
 }
 
+/*
+ * Check if Bacula Resoure Name is valid
+ */
+/* 
+ * Check if the Volume name has legal characters
+ * If ua is non-NULL send the message
+ */
+bool is_name_valid(char *name, POOLMEM **msg)
+{
+   int len;
+   char *p;
+   /* Special characters to accept */
+   const char *accept = ":.-_ ";
+
+   /* Restrict the characters permitted in the Volume name */
+   for (p=name; *p; p++) {
+      if (B_ISALPHA(*p) || B_ISDIGIT(*p) || strchr(accept, (int)(*p))) {
+        continue;
+      }
+      if (msg) {
+         Mmsg(msg, _("Illegal character \"%c\" in name.\n"), *p);
+      }
+      return false;
+   }
+   len = strlen(name);
+   if (len >= MAX_NAME_LENGTH) {
+      if (msg) {
+         Mmsg(msg, _("Name too long.\n"));
+      }
+      return false;
+   }
+   if (len == 0) {
+      if (msg) {
+         Mmsg(msg,  _("Volume name must be at least one character long.\n"));
+      }
+      return false;
+   }
+   return true;
+}
+
+
+
 /*
  * Add commas to a string, which is presumably
  * a number.  
@@ -291,3 +375,25 @@ char *add_commas(char *val, char *buf)
    }   
    return buf;
 }
+
+#ifdef TEST_PROGRAM
+void d_msg(char*, int, int, char*, ...)
+{}
+int main(int argc, char *argv[])
+{
+   char *str[] = {"3", "3n", "3 hours", "3.5 day", "3 week", "3 m", "3 q", "3 years"};
+   utime_t val;
+   char buf[100];
+   char outval[100];
+
+   for (int i=0; i<8; i++) {
+      strcpy(buf, str[i]);
+      if (!duration_to_utime(buf, &val)) {
+         printf("Error return from duration_to_utime for in=%s\n", str[i]);
+        continue;
+      }
+      edit_utime(val, outval);
+      printf("in=%s val=%lld outval=%s\n", str[i], val, outval);
+   }
+}
+#endif