]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/util.c
- Use a bigger buffer 32K as suggested by Arno in bpipe.c.
[bacula/bacula] / bacula / src / lib / util.c
index 9c1ce536c37deb4b07bb1ecaa14686ac2ad32f10..1d53dc2e227fc7d7a2da67043579f2cfd3911f34 100644 (file)
@@ -1,13 +1,13 @@
 /*
  *   util.c  miscellaneous utility subroutines for Bacula
- * 
+ *
  *    Kern Sibbald, MM
  *
  *   Version $Id$
  */
 
 /*
-   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+   Copyright (C) 2000-2004 Kern Sibbald and John Walker
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
 /* Return true of buffer has all zero bytes */
 int is_buf_zero(char *buf, int len)
 {
-   uint64_t *ip = (uint64_t *)buf;
+   uint64_t *ip;
    char *p;
    int i, len64, done, rem;
 
+   if (buf[0] != 0) {
+      return 0;
+   }
+   ip = (uint64_t *)buf;
    /* Optimize by checking uint64_t for zero */
-   len64 = len >> sizeof(uint64_t);
+   len64 = len / sizeof(uint64_t);
    for (i=0; i < len64; i++) {
       if (ip[i] != 0) {
         return 0;
       }
    }
-   done = len64 << sizeof(uint64_t);  /* bytes already checked */
+   done = len64 * sizeof(uint64_t);  /* bytes already checked */
    p = buf + done;
    rem = len - done;
    for (i = 0; i < rem; i++) {
@@ -71,7 +75,7 @@ void lcase(char *str)
    }
 }
 
-/* Convert spaces to non-space character. 
+/* Convert spaces to non-space character.
  * This makes scanf of fields containing spaces easier.
  */
 void
@@ -84,6 +88,21 @@ bash_spaces(char *str)
    }
 }
 
+/* Convert spaces to non-space character.
+ * This makes scanf of fields containing spaces easier.
+ */
+void
+bash_spaces(POOL_MEM &pm)
+{
+   char *str = pm.c_str();
+   while (*str) {
+      if (*str == ' ')
+        *str = 0x1;
+      str++;
+   }
+}
+
+
 /* Convert non-space characters (0x1) back into spaces */
 void
 unbash_spaces(char *str)
@@ -95,12 +114,53 @@ unbash_spaces(char *str)
    }
 }
 
+/* Convert non-space characters (0x1) back into spaces */
+void
+unbash_spaces(POOL_MEM &pm)
+{
+   char *str = pm.c_str();
+   while (*str) {
+     if (*str == 0x1)
+        *str = ' ';
+     str++;
+   }
+}
+
+#if    HAVE_WIN32 && !HAVE_CONSOLE && !HAVE_WXCONSOLE
+extern long _timezone;
+extern int _daylight;
+extern long _dstbias;
+extern "C" void __tzset(void);
+extern "C" int _isindst(struct tm *);
+#endif
 
 char *encode_time(time_t time, char *buf)
 {
    struct tm tm;
    int n = 0;
 
+#if    HAVE_WIN32 && !HAVE_CONSOLE && !HAVE_WXCONSOLE
+    /*
+     * Gross kludge to avoid a seg fault in Microsoft's CRT localtime_r(),
+     * which incorrectly references a NULL returned from gmtime() if
+     * the time (adjusted for the current timezone) is invalid.
+     * This could happen if you have a bad date/time, or perhaps if you
+     * moved a file from one timezone to another?
+     */
+    struct tm *gtm;
+    time_t gtime;
+    __tzset();
+    gtime = time - _timezone;
+    if (!(gtm = gmtime(&gtime))) {
+       return buf;
+    }
+    if (_daylight && _isindst(gtm)) {
+       gtime -= _dstbias;
+       if (!gmtime(&gtime)) {
+         return buf;
+       }
+    }
+#endif
    if (localtime_r(&time, &tm)) {
       n = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
                   tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
@@ -109,31 +169,6 @@ char *encode_time(time_t time, char *buf)
    return buf+n;
 }
 
-/*
- * Concatenate a string (str) onto a pool memory buffer pm
- */
-int pm_strcat(POOLMEM **pm, char *str)
-{
-   int pmlen = strlen(*pm);
-   int len = strlen(str) + 1;
-
-   *pm = check_pool_memory_size(*pm, pmlen + len);
-   memcpy(*pm+pmlen, str, len);
-   return pmlen + len - 1;
-}
-
-
-/*
- * Copy a string (str) into a pool memory buffer pm
- */
-int pm_strcpy(POOLMEM **pm, char *str)
-{
-   int len = strlen(str) + 1;
-
-   *pm = check_pool_memory_size(*pm, len);
-   memcpy(*pm, str, len);
-   return len - 1;
-}
 
 
 /*
@@ -141,40 +176,84 @@ int pm_strcpy(POOLMEM **pm, char *str)
  */
 void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen)
 {
-   char *termstat, jstat[2];
+   const char *jobstat;
+   char buf[100];
 
    switch (JobStatus) {
-      case JS_Terminated:
-         termstat = _("OK");
-        break;
-     case JS_FatalError:
-     case JS_ErrorTerminated:
-         termstat = _("Error");
-        break;
-     case JS_Error:
-         termstat = _("Non-fatal error");
-        break;
-     case JS_Canceled:
-         termstat = _("Canceled");
-        break;
-     case JS_Differences:
-         termstat = _("Verify differences");
-        break;
-     default:
-        jstat[0] = last_job.JobStatus;
-        jstat[1] = 0;
-        termstat = jstat;
-        break;
+   case JS_Created:
+      jobstat = _("Created");
+      break;
+   case JS_Running:
+      jobstat = _("Running");
+      break;
+   case JS_Blocked:
+      jobstat = _("Blocked");
+      break;
+   case JS_Terminated:
+      jobstat = _("OK");
+      break;
+   case JS_FatalError:
+   case JS_ErrorTerminated:
+      jobstat = _("Error");
+      break;
+   case JS_Error:
+      jobstat = _("Non-fatal error");
+      break;
+   case JS_Canceled:
+      jobstat = _("Canceled");
+      break;
+   case JS_Differences:
+      jobstat = _("Verify differences");
+      break;
+   case JS_WaitFD:
+      jobstat = _("Waiting on FD");
+      break;
+   case JS_WaitSD:
+      jobstat = _("Wait on SD");
+      break;
+   case JS_WaitMedia:
+      jobstat = _("Wait for new Volume");
+      break;
+   case JS_WaitMount:
+      jobstat = _("Waiting for mount");
+      break;
+   case JS_WaitStoreRes:
+      jobstat = _("Waiting for Storage resource");
+      break;
+   case JS_WaitJobRes:
+      jobstat = _("Waiting for Job resource");
+      break;
+   case JS_WaitClientRes:
+      jobstat = _("Waiting for Client resource");
+      break;
+   case JS_WaitMaxJobs:
+      jobstat = _("Waiting on Max Jobs");
+      break;
+   case JS_WaitStartTime:
+      jobstat = _("Waiting for Start Time");
+      break;
+   case JS_WaitPriority:
+      jobstat = _("Waiting on Priority");
+      break;
+
+   default:
+      if (JobStatus == 0) {
+        buf[0] = 0;
+      } else {
+         bsnprintf(buf, sizeof(buf), _("Unknown Job termination status=%d"), JobStatus);
+      }
+      jobstat = buf;
+      break;
    }
-   bstrncpy(msg, termstat, maxlen);
+   bstrncpy(msg, jobstat, maxlen);
 }
 
 /*
  * Convert Job Termination Status into a string
  */
-char *job_status_to_str(int stat) 
+const char *job_status_to_str(int stat)
 {
-   char *str;
+   const char *str;
 
    switch (stat) {
    case JS_Terminated:
@@ -204,9 +283,9 @@ char *job_status_to_str(int stat)
 /*
  * Convert Job Type into a string
  */
-char *job_type_to_str(int type) 
+const char *job_type_to_str(int type)
 {
-   char *str;
+   const char *str;
 
    switch (type) {
    case JT_BACKUP:
@@ -231,9 +310,9 @@ char *job_type_to_str(int type)
 /*
  * Convert Job Level into a string
  */
-char *job_level_to_str(int level) 
+const char *job_level_to_str(int level)
 {
-   char *str;
+   const char *str;
 
    switch (level) {
    case L_BASE:
@@ -259,9 +338,15 @@ char *job_level_to_str(int level)
    case L_VERIFY_VOLUME_TO_CATALOG:
       str = _("Verify Volume to Catalog");
       break;
+   case L_VERIFY_DISK_TO_CATALOG:
+      str = _("Verify Disk to Catalog");
+      break;
    case L_VERIFY_DATA:
       str = _("Verify Data");
       break;
+   case L_NONE:
+      str = " ";
+      break;
    default:
       str = _("Unknown Job Level");
       break;
@@ -276,7 +361,7 @@ char *job_level_to_str(int level)
 
 char *encode_mode(mode_t mode, char *buf)
 {
-  char *cp = buf;  
+  char *cp = buf;
 
   *cp++ = S_ISDIR(mode) ? 'd' : S_ISBLK(mode)  ? 'b' : S_ISCHR(mode)  ? 'c' :
           S_ISLNK(mode) ? 'l' : S_ISFIFO(mode) ? 'f' : S_ISSOCK(mode) ? 's' : '-';
@@ -308,7 +393,7 @@ int do_shell_expansion(char *name, int name_len)
    POOLMEM *cmd;
    BPIPE *bpipe;
    char line[MAXSTRING];
-   char *shellcmd;
+   const char *shellcmd;
 
    /* Check if any meta characters are present */
    len = strlen(meta);
@@ -329,12 +414,15 @@ int do_shell_expansion(char *name, int name_len)
       pm_strcat(&cmd, name);
       pm_strcat(&cmd, "\"");
       Dmsg1(400, "Send: %s\n", cmd);
-      bpipe = open_bpipe(cmd, 0, "r");
-      *line = 0;
-      fgets(line, sizeof(line), bpipe->rfd);
-      strip_trailing_junk(line);
-      stat = close_bpipe(bpipe);
-      Dmsg2(400, "stat=%d got: %s\n", stat, line);
+      if ((bpipe = open_bpipe(cmd, 0, "r"))) {
+        *line = 0;
+        fgets(line, sizeof(line), bpipe->rfd);
+        strip_trailing_junk(line);
+        stat = close_bpipe(bpipe);
+         Dmsg2(400, "stat=%d got: %s\n", stat, line);
+      } else {
+        stat = 1;                    /* error */
+      }
       free_pool_memory(cmd);
       if (stat == 0) {
         bstrncpy(name, line, name_len);
@@ -360,7 +448,7 @@ void make_session_key(char *key, char *seed, int mode)
 
      s[0] = 0;
      if (seed != NULL) {
-       strcat(s, seed);
+       bstrncat(s, seed, sizeof(s));
      }
 
      /* The following creates a seed for the session key generator
@@ -370,19 +458,16 @@ void make_session_key(char *key, char *seed, int mode)
        available on your machine, replace it with something
        equivalent or, if you like, just delete it. */
 
-     sprintf(s + strlen(s), "%lu", (unsigned long) getpid());
-     sprintf(s + strlen(s), "%lu", (unsigned long) getppid());
+     sprintf(s + strlen(s), "%lu", (unsigned long)getpid());
+     sprintf(s + strlen(s), "%lu", (unsigned long)getppid());
      getcwd(s + strlen(s), 256);
-     sprintf(s + strlen(s), "%lu", (unsigned long) clock());
-     sprintf(s + strlen(s), "%lu", (unsigned long) time(NULL));
+     sprintf(s + strlen(s), "%lu", (unsigned long)clock());
+     sprintf(s + strlen(s), "%lu", (unsigned long)time(NULL));
 #ifdef Solaris
      sysinfo(SI_HW_SERIAL,s + strlen(s), 12);
 #endif
 #ifdef HAVE_GETHOSTID
      sprintf(s + strlen(s), "%lu", (unsigned long) gethostid());
-#endif
-#ifdef HAVE_GETDOMAINNAME
-     getdomainname(s + strlen(s), 256);
 #endif
      gethostname(s + strlen(s), 256);
      sprintf(s + strlen(s), "%u", (unsigned)getuid());
@@ -390,27 +475,27 @@ void make_session_key(char *key, char *seed, int mode)
      MD5Init(&md5c);
      MD5Update(&md5c, (unsigned char *)s, strlen(s));
      MD5Final(md5key, &md5c);
-     sprintf(s + strlen(s), "%lu", (unsigned long) ((time(NULL) + 65121) ^ 0x375F));
+     sprintf(s + strlen(s), "%lu", (unsigned long)((time(NULL) + 65121) ^ 0x375F));
      MD5Init(&md5c);
      MD5Update(&md5c, (unsigned char *)s, strlen(s));
      MD5Final(md5key1, &md5c);
 #define nextrand    (md5key[j] ^ md5key1[j])
      if (mode) {
        for (j = k = 0; j < 16; j++) {
-           unsigned char rb = nextrand;
+          unsigned char rb = nextrand;
 
 #define Rad16(x) ((x) + 'A')
-           key[k++] = Rad16((rb >> 4) & 0xF);
-           key[k++] = Rad16(rb & 0xF);
+          key[k++] = Rad16((rb >> 4) & 0xF);
+          key[k++] = Rad16(rb & 0xF);
 #undef Rad16
-           if (j & 1) {
-                 key[k++] = '-';
-           }
+          if (j & 1) {
+              key[k++] = '-';
+          }
        }
        key[--k] = 0;
      } else {
        for (j = 0; j < 16; j++) {
-           key[j] = nextrand;
+          key[j] = nextrand;
        }
      }
 }
@@ -428,19 +513,23 @@ void make_session_key(char *key, char *seed, int mode)
  *  %j = Unique Job name
  *  %l = job level
  *  %n = Unadorned Job name
+ *  %s = Since time
  *  %t = Job type (Backup, ...)
  *  %r = Recipients
+ *  %v = Volume name
  *
  *  omsg = edited output message
  *  imsg = input string containing edit codes (%x)
- *  to = recepients list 
+ *  to = recepients list
  *
  */
-POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to)   
+POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to)
 {
-   char *p, *str;
+   char *p, *q;
+   const char *str;
    char add[20];
    char name[MAX_NAME_LENGTH];
+   int i;
 
    *omsg = 0;
    Dmsg1(200, "edit_job_codes: %s\n", imsg);
@@ -451,42 +540,85 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to)
             str = "%";
            break;
          case 'c':
-           str = jcr->client_name;
-           if (!str) {
-               str = "";
+           if (jcr) {
+              str = jcr->client_name;
+           } else {
+               str = _("*none*");
            }
            break;
          case 'd':
             str = my_name;            /* Director's name */
            break;
          case 'e':
-           str = job_status_to_str(jcr->JobStatus); 
+           if (jcr) {
+              str = job_status_to_str(jcr->JobStatus);
+           } else {
+               str = _("*none*");
+           }
            break;
          case 'i':
-            bsnprintf(add, sizeof(add), "%d", jcr->JobId);
-           str = add;
+           if (jcr) {
+               bsnprintf(add, sizeof(add), "%d", jcr->JobId);
+              str = add;
+           } else {
+               str = _("*none*");
+           }
            break;
          case 'j':                    /* Job name */
-           str = jcr->Job;
+           if (jcr) {
+              str = jcr->Job;
+           } else {
+               str = _("*none*");
+           }
            break;
          case 'l':
-           str = job_level_to_str(jcr->JobLevel);
+           if (jcr) {
+              str = job_level_to_str(jcr->JobLevel);
+           } else {
+               str = _("*none*");
+           }
            break;
          case 'n':
-            bstrncpy(name, jcr->Job, sizeof(name));
-            /* There are three periods after the Job name */
-            for (int i=0; i<3; i++) {
-                if ((str=strrchr(name, '.')) != NULL) {
-                   *str = 0;
+            if (jcr) {
+               bstrncpy(name, jcr->Job, sizeof(name));
+               /* There are three periods after the Job name */
+               for (i=0; i<3; i++) {
+                   if ((q=strrchr(name, '.')) != NULL) {
+                      *q = 0;
+                  }
                }
+               str = name;
+            } else {
+                str = _("*none*");
             }
-            str = name;
             break;
          case 'r':
            str = to;
            break;
+         case 's':                    /* since time */
+           if (jcr && jcr->stime) {
+              str = jcr->stime;
+           } else {
+               str = _("*none*");
+           }
+           break;
          case 't':
-           str = job_type_to_str(jcr->JobType);
+           if (jcr) {
+              str = job_type_to_str(jcr->JobType);
+           } else {
+               str = _("*none*");
+           }
+           break;
+         case 'v':
+           if (jcr) {
+              if (jcr->VolumeName && jcr->VolumeName[0]) {
+                 str = jcr->VolumeName;
+              } else {
+                  str = "";
+              }
+           } else {
+               str = _("*none*");
+           }
            break;
         default:
             add[0] = '%';
@@ -509,7 +641,7 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to)
 
 void set_working_directory(char *wd)
 {
-   struct stat stat_buf; 
+   struct stat stat_buf;
 
    if (wd == NULL) {
       Emsg0(M_ERROR_TERM, 0, _("Working directory not defined. Cannot continue.\n"));