]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/edit.c
ebl Work on copy jobs
[bacula/bacula] / bacula / src / lib / edit.c
index 21ca18566dbceb9ceb01226b34dfeed4adead2dd..8b13435f5fa62726ff20864edffe8dbabe8cfc98 100644 (file)
@@ -5,26 +5,33 @@
  *
  *   Version $Id$
  */
-
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2002-2006 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 two of the GNU 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 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.
+*/
 
 #include "bacula.h"
 #include <math.h>
@@ -84,24 +91,43 @@ int64_t str_to_int64(char *str)
  */
 char *edit_uint64_with_commas(uint64_t val, char *buf)
 {
-   /*
-    * Replacement for sprintf(buf, "%" llu, val)
-    */
-   char mbuf[50];
-   mbuf[sizeof(mbuf)-1] = 0;
-   int i = sizeof(mbuf)-2;                 /* edit backward */
-   if (val == 0) {
-      mbuf[i--] = '0';
-   } else {
-      while (val != 0) {
-         mbuf[i--] = "0123456789"[val%10];
-         val /= 10;
-      }
-   }
-   bstrncpy(buf, &mbuf[i+1], 27);
+   edit_uint64(val, buf);
    return add_commas(buf, buf);
 }
 
+/*
+ * Edit an integer into "human-readable" format with four or fewer
+ * significant digits followed by a suffix that indicates the scale
+ * factor.  The buf array inherits a 27 byte minimim length
+ * requirement from edit_unit64_with_commas(), although the output
+ * string is limited to eight characters.
+ */
+char *edit_uint64_with_suffix(uint64_t val, char *buf)
+{
+  int commas = 0;
+  char *c, mbuf[50];
+  const char *suffix[] =
+    { "", "K", "M", "G", "T", "P", "E", "Z", "Y", "FIX ME" };
+  int suffixes = sizeof(suffix) / sizeof(*suffix);
+
+  edit_uint64_with_commas(val, mbuf);
+
+  if ((c = strchr(mbuf, ',')) != NULL) {
+    commas++;
+    *c++ = '.';
+    while  ((c = strchr(c, ',')) != NULL) {
+      commas++;
+      *c++ = '\0';
+    }
+    mbuf[5] = '\0'; // drop this to get '123.456 TB' rather than '123.4 TB'
+  }
+
+  if (commas >= suffixes)
+    commas = suffixes - 1;
+  bsnprintf(buf, 27, "%s %s", mbuf, suffix[commas]);
+  return buf;
+}
+
 /*
  * Edit an integer number, the supplied buffer
  * must be at least 27 bytes long.  The incoming number
@@ -155,19 +181,25 @@ char *edit_int64(int64_t val, char *buf)
    return buf;
 }
 
+/*
+ * Edit an integer number with commas, the supplied buffer
+ * must be at least 27 bytes long.  The incoming number
+ * is always widened to 64 bits.
+ */
+char *edit_int64_with_commas(int64_t val, char *buf)
+{
+   edit_int64(val, buf);
+   return add_commas(buf, buf);
+}
 
 /*
- * Given a string "str", separate the integer part into
+ * Given a string "str", separate the numeric part into
  *   str, and the modifier into mod.
  */
 static bool get_modifier(char *str, char *num, int num_len, char *mod, int mod_len)
 {
    int i, len, num_begin, num_end, mod_begin, mod_end;
 
-   /*
-    * Look for modifier by walking back looking for the first
-    *   space or digit.
-    */
    strip_trailing_junk(str);
    len = strlen(str);
 
@@ -180,7 +212,7 @@ static bool get_modifier(char *str, char *num, int num_len, char *mod, int mod_l
 
    /* Walk through integer part */
    for ( ; i<len; i++) {
-      if (!B_ISDIGIT(str[i])) {
+      if (!B_ISDIGIT(str[i]) && str[i] != '.') {
          break;
       }
    }
@@ -191,6 +223,7 @@ static bool get_modifier(char *str, char *num, int num_len, char *mod, int mod_l
    if (num_len == 0) {
       return false;
    }
+   /* Eat any spaces in front of modifier */
    for ( ; i<len; i++) {
       if (!B_ISSPACE(str[i])) {
          break;
@@ -214,16 +247,17 @@ static bool get_modifier(char *str, char *num, int num_len, char *mod, int mod_l
       return false;
    }
    bstrncpy(str, &str[mod_end], len);
+   Dmsg2(900, "num=%s mod=%s\n", num, mod);
 
    return true;
 }
 
 /*
  * Convert a string duration to utime_t (64 bit seconds)
- * Returns 0: if error
-           1: if OK, and value stored in value
+ * Returns false: if error
+           true:  if OK, and value stored in value
  */
-int duration_to_utime(char *str, utime_t *value)
+bool duration_to_utime(char *str, utime_t *value)
 {
    int i, mod_len;
    double val, total = 0.0;
@@ -234,19 +268,19 @@ int duration_to_utime(char *str, utime_t *value)
     *   to months. These "kludges" make it compatible with pre 1.31
     *   Baculas.
     */
-   static const char *mod[] = {"n", "seconds", "months", "minutes",
+   static const char *mod[] = {"n", "seconds", "months", "minutes", "mins",
                   "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};
+   static const int32_t mult[] = {60,   1, 60*60*24*30, 60, 60,
+                  3600, 3600*24, 3600*24*7, 3600*24*91, 3600*24*365};
 
    while (*str) {
       if (!get_modifier(str, num_str, sizeof(num_str), mod_str, sizeof(mod_str))) {
-         return 0;
+         return false;
       }
       /* Now find the multiplier corresponding to the modifier */
       mod_len = strlen(mod_str);
       if (mod_len == 0) {
-         i = 1;                          /* assume seconds */
+         i = 1;                          /* default to seconds */
       } else {
          for (i=0; mod[i]; i++) {
             if (strncasecmp(mod_str, mod[i], mod_len) == 0) {
@@ -254,19 +288,19 @@ int duration_to_utime(char *str, utime_t *value)
             }
          }
          if (mod[i] == NULL) {
-            i = 1;                       /* no modifier, assume secs */
+            return false;
          }
       }
       Dmsg2(900, "str=%s: mult=%d\n", num_str, mult[i]);
       errno = 0;
       val = strtod(num_str, NULL);
       if (errno != 0 || val < 0) {
-         return 0;
+         return false;
       }
       total += val * mult[i];
    }
    *value = (utime_t)total;
-   return 1;
+   return true;
 }
 
 /*
@@ -300,10 +334,10 @@ char *edit_utime(utime_t val, char *buf, int buf_len)
 
 /*
  * Convert a size in bytes to uint64_t
- * Returns 0: if error
-           1: if OK, and value stored in value
+ * Returns false: if error
+           true:  if OK, and value stored in value
  */
-int size_to_uint64(char *str, int str_len, uint64_t *value)
+bool size_to_uint64(char *str, int str_len, uint64_t *value)
 {
    int i, mod_len;
    double val;
@@ -323,22 +357,26 @@ int size_to_uint64(char *str, int str_len, uint64_t *value)
    }
    /* 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_len == 0) {
+      i = 0;                          /* default with no modifier = 1 */
+   } else {
+      for (i=0; mod[i]; i++) {
+         if (strncasecmp(mod_str, mod[i], mod_len) == 0) {
+            break;
+         }
+      }
+      if (mod[i] == NULL) {
+         return false;
       }
-   }
-   if (mod[i] == NULL) {
-      i = 0;                          /* no modifier found, assume 1 */
    }
    Dmsg2(900, "str=%s: mult=%d\n", str, mult[i]);
    errno = 0;
    val = strtod(num_str, NULL);
    if (errno != 0 || val < 0) {
-      return 0;
+      return false;
    }
-  *value = (utime_t)(val * mult[i]);
-   return 1;
+   *value = (utime_t)(val * mult[i]);
+   return true;
 }
 
 /*
@@ -368,6 +406,27 @@ bool is_a_number(const char *n)
    return digit_seen && *n==0;
 }
 
+/*
+ * Check if specified string is a list of number or not
+ */
+bool is_a_number_list(const char *n)
+{
+   bool previous_digit = false; 
+   bool digit_seen = false;
+   while (*n) {
+      if (B_ISDIGIT(*n)) {
+         previous_digit=true;
+         digit_seen = true;
+      } else if (*n == ',' && previous_digit) {
+         previous_digit = false;
+      } else {
+         return false;
+      }
+      n++;
+   }
+   return digit_seen && *n==0; 
+}
+
 /*
  * Check if the specified string is an integer
  */