]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/util.c
Big backport from Enterprise
[bacula/bacula] / bacula / src / lib / util.c
index 5d3bffa30afa8ee894efd1cbf7e0ee21ba7caeb8..12b3d35420f11dcc5ba281e7d6210dfc956fc562 100644 (file)
@@ -1,36 +1,25 @@
 /*
-   Bacula® - The Network Backup Solution
-
-   Copyright (C) 2000-2009 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 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
-   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., 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.
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2017 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is 
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
  *   util.c  miscellaneous utility subroutines for Bacula
  *
  *    Kern Sibbald, MM
- *
- *   Version $Id$
  */
 
 #include "bacula.h"
  *
  */
 
+bool is_null(const void *ptr)
+{
+   return ptr == NULL;
+}
+
 /* Return true of buffer has all zero bytes */
-bool is_buf_zero(char *buf, int len)
+bool is_buf_zero(const char *buf, int len)
 {
    uint64_t *ip;
-   char *p;
+   const char *p;
    int i, len64, done, rem;
 
    if (buf[0] != 0) {
@@ -71,6 +65,15 @@ bool is_buf_zero(char *buf, int len)
    return true;
 }
 
+/*
+ * Subroutine that cannot be suppressed by GCC 6.0
+ */
+void bmemzero(void *buf, size_t size)
+{
+   memset(buf, 0, size);
+   return;
+}
+
 
 /* Convert a string in place to lower case */
 void lcase(char *str)
@@ -167,6 +170,114 @@ char *encode_time(utime_t utime, char *buf)
 
 
 
+static char hexatable[]="0123456789abcdef";
+
+/*
+ * do an hexadump of data[0:len] into buf[0:capacity]
+ * a space is inserted between every 4 bytes
+ * usage:
+ *    char buf[10];
+ *    Dmsg2("msglen=%d msg=%s", fd->msglen, hexdump(fd->msg, fd->msglen, buf, sizeof(buf));
+ * ==>
+ *    msglen=36 msg=12345678 12345678
+ */
+char *hexdump(const char *data, int len, char *buf, int capacity, bool add_spaces)
+{
+   char *b=buf;
+   int i=0;
+   while (i<len && capacity>2) {
+      if (add_spaces && i>0 && i%4==0 ) {
+         *(b++)=' ';
+         capacity--;
+      }
+      if (capacity>2) {
+         *(b++)=hexatable[(data[i]&0xF0)>>4];
+         *(b++)=hexatable[data[i++]&0x0F];
+      }
+      capacity-=2;
+   }
+   *b='\0';
+   return buf;
+}
+
+/*
+ * do an ASCII dump of data[0:len] into buf[0:capacity]
+ * non printable chars are replaced by hexa "\xx"
+ * usage:
+ *    char buf[10];
+ *    Dmsg2("msglen=%d msg=%s", fd->msglen, asciidump(fd->msg, fd->msglen, buf, sizeof(buf));
+ * ==>
+ *    msglen=5 msg=abcd\10
+ */
+char *asciidump(const char *data, int len, char *buf, int capacity)
+{
+   char *b=buf;
+   const unsigned char *p=(const unsigned char *)data;
+   if (!data) {
+      strncpy(buf, "<NULL>", capacity);
+      return buf;
+   }
+   while (len>0 && capacity>1) {
+      if (isprint(*p)) {
+         *(b++)=*(p++);
+         capacity--;
+      } else {
+         if (capacity>3) {
+            *(b++)='\\';
+            *(b++)=hexatable[((*p)&0xF0)>>4];
+            *(b++)=hexatable[(*(p++))&0x0F];
+         }
+         capacity-=3;
+      }
+      len--;
+   }
+   *b='\0';
+   return buf;
+}
+
+char *smartdump(const char *data, int len, char *buf, int capacity, bool *is_ascii)
+{
+   char *b=buf;
+   int l=len;
+   int c=capacity;
+   const unsigned char *p=(const unsigned char *)data;
+   if (!data) {
+      strncpy(buf, "<NULL>", capacity);
+      return buf;
+   }
+   if (is_ascii != NULL) {
+      *is_ascii = false;
+   }
+   while (l>0 && c>1) {
+      if (isprint(*p)) {
+         *(b++)=*(p++);
+      } else if (isspace(*p) || *p=='\0') {
+         *(b++)=' ';
+         p++;
+      } else {
+         return hexdump(data, len, buf, capacity);
+      }
+      c--;
+      l--;
+   }
+   *b='\0';
+   if (is_ascii != NULL) {
+      *is_ascii = true;
+   }
+   return buf;
+}
+
+/*
+ * check if x is a power  two
+ */
+int is_power_of_two(uint64_t x)
+{
+   while ( x%2 == 0 && x > 1) {
+      x /= 2;
+   }
+   return (x == 1);
+}
+
 /*
  * Convert a JobStatus code into a human readable form
  */
@@ -188,6 +299,9 @@ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen)
    case JS_Terminated:
       jobstat = _("OK");
       break;
+   case JS_Incomplete:
+      jobstat = _("Incomplete job");
+      break;
    case JS_FatalError:
    case JS_ErrorTerminated:
       jobstat = _("Error");
@@ -308,17 +422,20 @@ void jobstatus_to_ascii_gui(int JobStatus, char *msg, int maxlen)
    }
 }
 
-
 /*
  * Convert Job Termination Status into a string
  */
-const char *job_status_to_str(int stat)
+const char *job_status_to_str(int status, int errors)
 {
    const char *str;
 
-   switch (stat) {
+   switch (status) {
    case JS_Terminated:
-      str = _("OK");
+      if (errors > 0) {
+         str = _("OK -- with warnings");
+      } else {
+         str = _("OK");
+      }
       break;
    case JS_Warnings:
       str = _("OK -- with warnings");
@@ -336,6 +453,12 @@ const char *job_status_to_str(int stat)
    case JS_Differences:
       str = _("Differences");
       break;
+   case JS_Created:
+      str = _("Created");
+      break;
+   case JS_Incomplete:
+      str = _("Incomplete");
+      break;
    default:
       str = _("Unknown term code");
       break;
@@ -349,46 +472,65 @@ const char *job_status_to_str(int stat)
  */
 const char *job_type_to_str(int type)
 {
-   const char *str;
+   const char *str = NULL;
 
    switch (type) {
    case JT_BACKUP:
       str = _("Backup");
       break;
+   case JT_MIGRATED_JOB:
+      str = _("Migrated Job");
+      break;
    case JT_VERIFY:
       str = _("Verify");
       break;
    case JT_RESTORE:
       str = _("Restore");
       break;
+   case JT_CONSOLE:
+      str = _("Console");
+      break;
+   case JT_SYSTEM:
+      str = _("System or Console");
+      break;
    case JT_ADMIN:
       str = _("Admin");
       break;
-   case JT_MIGRATE:
-      str = _("Migrate");
-      break;
-   case JT_COPY:
-      str = _("Copy");
+   case JT_ARCHIVE:
+      str = _("Archive");
       break;
    case JT_JOB_COPY:
       str = _("Job Copy");
       break;
-   case JT_CONSOLE:
-      str = _("Console");
+   case JT_COPY:
+      str = _("Copy");
       break;
-   case JT_SYSTEM:
-      str = _("System or Console");
+   case JT_MIGRATE:
+      str = _("Migrate");
       break;
    case JT_SCAN:
       str = _("Scan");
       break;
-   default:
+   }
+   if (!str) {
       str = _("Unknown Type");
-      break;
    }
    return str;
 }
 
+/* Convert ActionOnPurge to string (Truncate, Erase, Destroy)
+ */
+char *action_on_purge_to_string(int aop, POOL_MEM &ret)
+{
+   if (aop & ON_PURGE_TRUNCATE) {
+      pm_strcpy(ret, _("Truncate"));
+   }
+   if (!aop) {
+      pm_strcpy(ret, _("None"));
+   }
+   return ret.c_str();
+}
+
 /*
  * Convert Job Level into a string
  */
@@ -399,6 +541,7 @@ const char *job_level_to_str(int level)
    switch (level) {
    case L_BASE:
       str = _("Base");
+      break;
    case L_FULL:
       str = _("Full");
       break;
@@ -589,9 +732,7 @@ void make_session_key(char *key, char *seed, int mode)
       LARGE_INTEGER     li;
       DWORD             length;
       FILETIME          ft;
-      char             *p;
 
-      p = s;
       bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)GetCurrentProcessId());
       (void)getcwd(s + strlen(s), 256);
       bsnprintf(s + strlen(s), ss, "%lu", (uint32_t)GetTickCount());
@@ -695,10 +836,24 @@ void decode_session_key(char *decode, char *session, char *key, int maxlen)
  *  %j = Unique Job id
  *  %l = job level
  *  %n = Unadorned Job name
+ *  %p = Pool name (Director)
+ *  %P = Process PID
+ *  %w = Write Store (Director)
+ *  %x = Spool Data (Director)
+ *  %D = Director name (Director/FileDaemon)
+ *  %C = Cloned (Director)
+ *  %I = wjcr->JobId (Director)
+ *  %f = FileSet (Director)
+ *  %h = Client Address (Director)
  *  %s = Since time
  *  %t = Job type (Backup, ...)
  *  %r = Recipients
  *  %v = Volume name
+ *  %b = Job Bytes
+ *  %F = Job Files
+ *  %E = Job Errors
+ *  %R = Job ReadBytes
+ *  %S = Previous Job name (FileDaemon) for Incremental/Differential
  *
  *  omsg = edited output message
  *  imsg = input string containing edit codes (%x)
@@ -709,7 +864,7 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_co
 {
    char *p, *q;
    const char *str;
-   char add[20];
+   char add[50];
    char name[MAX_NAME_LENGTH];
    int i;
 
@@ -733,11 +888,14 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_co
             break;
          case 'e':
             if (jcr) {
-               str = job_status_to_str(jcr->JobStatus);
+               str = job_status_to_str(jcr->JobStatus, jcr->getErrors());
             } else {
                str = _("*none*");
             }
             break;
+         case 'E':                    /* Job Errors */
+            str = edit_uint64(jcr->getErrors(), add);
+            break;
          case 'i':
             if (jcr) {
                bsnprintf(add, sizeof(add), "%d", jcr->JobId);
@@ -755,7 +913,7 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_co
             break;
          case 'l':
             if (jcr) {
-               str = job_level_to_str(jcr->get_JobLevel());
+               str = job_level_to_str(jcr->getJobLevel());
             } else {
                str = _("*none*");
             }
@@ -784,9 +942,15 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_co
                str = _("*none*");
             }
             break;
+         case 'F':                    /* Job Files */
+            str = edit_uint64(jcr->JobFiles, add);
+            break;
+         case 'b':                    /* Job Bytes */
+            str = edit_uint64(jcr->JobBytes, add);
+            break;
          case 't':
             if (jcr) {
-               str = job_type_to_str(jcr->get_JobType());
+               str = job_type_to_str(jcr->getJobType());
             } else {
                str = _("*none*");
             }
@@ -802,10 +966,17 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to, job_co
                str = _("*none*");
             }
             break;
+         case 'P':
+            edit_uint64(getpid(), add);
+            str = add;
+            break;
+         case 'R':                    /* Job ReadBytes */
+            str = edit_uint64(jcr->ReadBytes, add);
+            break;
          default:
             str = NULL;
             if (callback != NULL) {
-                str = callback(jcr, p);
+               str = callback(jcr, p, add, sizeof(add));
             }
 
             if (!str) {