]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Fix a text sizing problem in the tray-monitor reported in
authorKern Sibbald <kern@sibbald.com>
Fri, 30 Jan 2009 09:20:41 +0000 (09:20 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 30 Jan 2009 09:20:41 +0000 (09:20 +0000)
     bug #1219, with patch included. + reorganize patches

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@8414 91ce42f0-d328-0410-95d8-f526ca767f89

21 files changed:
bacula/AUTHORS
bacula/patches/2.4.3-getmsg.patch [deleted file]
bacula/patches/2.4.3-jobs.patch [deleted file]
bacula/patches/2.4.3-migrate-log.patch [deleted file]
bacula/patches/2.4.3-migrate.patch [deleted file]
bacula/patches/2.4.3-migrate2.patch [deleted file]
bacula/patches/2.4.3-orphaned-jobs.patch [deleted file]
bacula/patches/2.4.3-prune.patch [deleted file]
bacula/patches/2.4.3-purge-bug.patch [deleted file]
bacula/patches/2.4.3-win32-runscript-unicode-path.patch [deleted file]
bacula/patches/2.4.4-reload.patch
bacula/patches/2.4.4-tray-sizing.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-getmsg.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-jobs.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-migrate-log.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-migrate.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-migrate2.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-orphaned-jobs.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-prune.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-purge-bug.patch [new file with mode: 0644]
bacula/patches/2.4.x/2.4.3-win32-runscript-unicode-path.patch [new file with mode: 0644]

index 0d6d9554f95c4308fff92277a392bce770d43f15..e6e181f2782cba448f243a8a3aaa51a0cb63c78f 100644 (file)
@@ -99,6 +99,7 @@ Tim Oberfoell
 Tomas Cameron
 Tullio Andreatta
 Ulrich Leodolter
+Vitaliy Kosharskiy
 Wolfgang Denk
 Yuri Timofeev
 Yves Orton
diff --git a/bacula/patches/2.4.3-getmsg.patch b/bacula/patches/2.4.3-getmsg.patch
deleted file mode 100644 (file)
index 926cbcd..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
- This patch used the jcr stored in the BSOCK packet during callbacks
- to the Director rather than looking them up in the JCR list.
-
- It can be applied to Bacula version 2.4.3 (or earlier) with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-getmsg.patch
- ./configure <your options>
- make
- ...
- make install
-
-
-Index: src/dird/getmsg.c
-===================================================================
---- src/dird/getmsg.c  (revision 7970)
-+++ src/dird/getmsg.c  (working copy)
-@@ -1,7 +1,7 @@
- /*
-    Bacula® - The Network Backup Solution
--   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
-+   Copyright (C) 2000-2008 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.
-@@ -20,7 +20,7 @@
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-    02110-1301, USA.
--   Bacula® is a registered trademark of John Walker.
-+   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.
-@@ -102,12 +102,12 @@
-    char Job[MAX_NAME_LENGTH];
-    char MsgType[20];
-    int type, level;
--   JCR *jcr;
-+   JCR *jcr = bs->jcr();
-    char *msg;
-    for (;;) {
-       n = bs->recv();
--      Dmsg2(100, "bget_dirmsg %d: %s", n, bs->msg);
-+      Dmsg2(300, "bget_dirmsg %d: %s\n", n, bs->msg);
-       if (is_bnet_stop(bs)) {
-          return n;                    /* error or terminate */
-@@ -142,7 +142,7 @@
-             bs->fsend("btime %s\n", edit_uint64(get_current_btime(),ed1));
-             break;
-          default:
--            Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
-+            Jmsg1(jcr, M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
-             return n;
-          }
-          continue;
-@@ -160,21 +160,13 @@
-        *  Try to fulfill it.
-        */
-       if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) {
--         Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-+         Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-          continue;
-       }
--      if (strcmp(Job, "*System*") == 0) {
--         jcr = NULL;                  /* No jcr */
--      } else if (!(jcr=get_jcr_by_full_name(Job))) {
--         Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg);
--         continue;
--      }
--      Dmsg1(900, "Getmsg got jcr 0x%x\n", jcr);
-       /* Skip past "Jmsg Job=nnn" */
-       if (!(msg=find_msg_start(bs->msg))) {
--         Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
--         free_jcr(jcr);
-+         Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-          continue;
-       }
-@@ -185,8 +177,7 @@
-       if (bs->msg[0] == 'J') {           /* Job message */
-          if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d",
-                     Job, &type, &level) != 3) {
--            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
--            free_jcr(jcr);
-+            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-             continue;
-          }
-          Dmsg1(900, "Got msg: %s\n", bs->msg);
-@@ -199,7 +190,6 @@
-          }
-          Dmsg1(900, "Dispatch msg: %s", msg);
-          dispatch_message(jcr, type, level, msg);
--         free_jcr(jcr);
-          continue;
-       }
-       /*
-@@ -209,21 +199,16 @@
-       if (bs->msg[0] == 'C') {        /* Catalog request */
-          Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg);
-          catalog_request(jcr, bs);
--         Dmsg1(900, "Calling freejcr 0x%x\n", jcr);
--         free_jcr(jcr);
-          continue;
-       }
-       if (bs->msg[0] == 'U') {        /* SD sending attributes */
-          Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg);
-          catalog_update(jcr, bs);
--         Dmsg1(900, "Calling freejcr 0x%x\n", jcr);
--         free_jcr(jcr);
-          continue;
-       }
-       if (bs->msg[0] == 'M') {        /* Mount request */
-          Dmsg1(900, "Mount req: %s", bs->msg);
-          mount_request(jcr, bs, msg);
--         free_jcr(jcr);
-          continue;
-       }
-       if (bs->msg[0] == 'S') {       /* Status change */
-@@ -232,9 +217,8 @@
-          if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) {
-             jcr->SDJobStatus = JobStatus; /* current status */
-          } else {
--            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-+            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-          }
--         free_jcr(jcr);
-          continue;
-       }
- #ifdef needed
diff --git a/bacula/patches/2.4.3-jobs.patch b/bacula/patches/2.4.3-jobs.patch
deleted file mode 100644 (file)
index 25d2d3c..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-
- This patch corrects two problems:
- 1. If you start more than 60 jobs within a 1 minute period, the unique
-    jobname (critical for the daemons) can be duplicated leading to 
-    authentication failures and orphaned jobs.
- 2. FD jobs that fail SD authentication were not properly cleaned up.
-
- Apply it to Bacula 2.4.3 (possibly earlier versions)
- with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-jobs.patch
- ./configure <your-options>
- make
- ...
- make install
-
-
-Index: src/dird/job.c
-===================================================================
---- src/dird/job.c     (revision 8011)
-+++ src/dird/job.c     (working copy)
-@@ -758,17 +758,17 @@
-    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-    static time_t last_start_time = 0;
-    static int seq = 0;
--   time_t now;
-+   time_t now = time(NULL);
-    struct tm tm;
-    char dt[MAX_TIME_LENGTH];
-    char name[MAX_NAME_LENGTH];
-    char *p;
-+   int len;
-    /* Guarantee unique start time -- maximum one per second, and
-     * thus unique Job Name
-     */
-    P(mutex);                          /* lock creation of jobs */
--   now = time(NULL);
-    seq++;
-    if (seq > 59) {                    /* wrap as if it is seconds */
-       seq = 0;
-@@ -783,9 +783,10 @@
-    /* Form Unique JobName */
-    (void)localtime_r(&now, &tm);
-    /* Use only characters that are permitted in Windows filenames */
--   strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M", &tm);
-+   strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
-+   len = strlen(dt) + 5;   /* dt + .%02d EOS */
-    bstrncpy(name, base_name, sizeof(name));
--   name[sizeof(name)-22] = 0;          /* truncate if too long */
-+   name[sizeof(name)-len] = 0;          /* truncate if too long */
-    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s.%02d", name, dt, seq); /* add date & time */
-    /* Convert spaces into underscores */
-    for (p=jcr->Job; *p; p++) {
-@@ -793,6 +794,7 @@
-          *p = '_';
-       }
-    }
-+   Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
- }
- /* Called directly from job rescheduling */
-Index: src/stored/job.c
-===================================================================
---- src/stored/job.c   (revision 8011)
-+++ src/stored/job.c   (working copy)
-@@ -228,21 +228,25 @@
-    if (!(jcr=get_jcr_by_full_name(job_name))) {
-       Jmsg1(NULL, M_FATAL, 0, _("FD connect failed: Job name not found: %s\n"), job_name);
-       Dmsg1(3, "**** Job \"%s\" not found\n", job_name);
-+      fd->close();
-       return;
-    }
--   jcr->file_bsock = fd;
--   jcr->file_bsock->set_jcr(jcr);
--
-    Dmsg1(110, "Found Job %s\n", job_name);
-    if (jcr->authenticated) {
-       Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s already authenticated.\n"),
-          (uint32_t)jcr->JobId, jcr->Job);
-+      Dmsg2(50, "Hey!!!! JobId %u Job %s already authenticated.\n",
-+         (uint32_t)jcr->JobId, jcr->Job);
-+      fd->close();
-       free_jcr(jcr);
-       return;
-    }
-+   jcr->file_bsock = fd;
-+   jcr->file_bsock->set_jcr(jcr);
-+
-    /*
-     * Authenticate the File daemon
-     */
-Index: src/lib/bnet_server.c
-===================================================================
---- src/lib/bnet_server.c      (revision 8011)
-+++ src/lib/bnet_server.c      (working copy)
-@@ -1,7 +1,7 @@
- /*
-    Bacula® - The Network Backup Solution
--   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
-+   Copyright (C) 2000-2008 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.
-@@ -20,7 +20,7 @@
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-    02110-1301, USA.
--   Bacula® is a registered trademark of John Walker.
-+   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.
-@@ -137,7 +137,7 @@
-                   be.bstrerror());
-          }
-       }
--      listen(fd_ptr->fd, 5);       /* tell system we are ready */
-+      listen(fd_ptr->fd, 20);      /* tell system we are ready */
-       sockfds.append(fd_ptr);
-    }
-    /* Start work queue thread */
diff --git a/bacula/patches/2.4.3-migrate-log.patch b/bacula/patches/2.4.3-migrate-log.patch
deleted file mode 100644 (file)
index c593cc2..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-
- This patch should cause all Job Log records to be migrated when the
- Job is migrated. It fixes the second issue reported in bug #1171.
-
- Apply it to Bacula 2.4.3 (possibly earlier versions)
- with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-migrate.patch
- ./configure <your-options>
- make
- ...
- make install
-
-Index: src/dird/migrate.c
-===================================================================
---- src/dird/migrate.c (revision 7926)
-+++ src/dird/migrate.c (working copy)
-@@ -402,14 +402,6 @@
-    }
-    migration_cleanup(jcr, jcr->JobStatus);
--   if (mig_jcr) {
--      char jobid[50];
--      UAContext *ua = new_ua_context(jcr);
--      edit_uint64(jcr->previous_jr.JobId, jobid);
--      /* Purge all old file records, but leave Job record */
--      purge_files_from_jobs(ua, jobid);
--      free_ua_context(ua);
--   }
-    return true;
- }
-@@ -1087,11 +1079,26 @@
-          edit_uint64(mig_jcr->jr.JobId, ec2));
-       db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
--      /* Now mark the previous job as migrated if it terminated normally */
--      if (jcr->JobStatus == JS_Terminated) {
-+      /*
-+       * If we terminated a migration normally:
-+       *   - mark the previous job as migrated
-+       *   - move any Log records to the new JobId
-+       *   - Purge the File records from the previous job
-+       */
-+      if (jcr->JobType == JT_MIGRATE && jcr->JobStatus == JS_Terminated) {
-+         char old_jobid[50], new_jobid[50];
-          Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s",
--              (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, ec1));
-+              (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, new_jobid));
-          db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
-+         UAContext *ua = new_ua_context(jcr);
-+         /* Move JobLog to new JobId */
-+         Mmsg(query, "UPDATE Log SET JobId=%s WHERE JobId=%s",
-+           new_jobid,
-+           edit_uint64(jcr->previous_jr.JobId, old_jobid));
-+         db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
-+         /* Purge all old file records, but leave Job record */
-+         purge_files_from_jobs(ua, old_jobid);
-+         free_ua_context(ua);
-       } 
-       if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) {
-@@ -1100,7 +1107,6 @@
-          set_jcr_job_status(jcr, JS_ErrorTerminated);
-       }
--
-       update_bootstrap_file(mig_jcr);
-       if (!db_get_job_volume_names(mig_jcr, mig_jcr->db, mig_jcr->jr.JobId, &mig_jcr->VolumeName)) {
diff --git a/bacula/patches/2.4.3-migrate.patch b/bacula/patches/2.4.3-migrate.patch
deleted file mode 100644 (file)
index 138c09c..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-
- This patch should prevent migration jobs from attempting to migrate
- jobs that failed.  Apply it to Bacula 2.4.3 (possibly earlier versions)
- with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-migrate.patch
- ./configure <your-options>
- make
- ...
- make install
-
-
-Index: src/dird/migrate.c
-===================================================================
---- src/dird/migrate.c (revision 7757)
-+++ src/dird/migrate.c (working copy)
-@@ -377,7 +377,7 @@
-     * to avoid two threads from using the BSOCK structure at
-     * the same time.
-     */
--   if (!bnet_fsend(sd, "run")) {
-+   if (!sd->fsend("run")) {
-       return false;
-    }
-@@ -520,6 +520,7 @@
-    "SELECT DISTINCT Job.JobId,Job.StartTime FROM Job,Pool,Client"
-    " WHERE Client.Name='%s' AND Pool.Name='%s' AND Job.PoolId=Pool.PoolId"
-    " AND Job.ClientId=Client.ClientId AND Job.Type='B'"
-+   " AND Job.JobStatus = 'T'"
-    " ORDER by Job.StartTime";
- /* Get Volume names in Pool */
-@@ -533,9 +534,9 @@
-    "SELECT DISTINCT Job.JobId,Job.StartTime FROM Media,JobMedia,Job"
-    " WHERE Media.VolumeName='%s' AND Media.MediaId=JobMedia.MediaId"
-    " AND JobMedia.JobId=Job.JobId AND Job.Type='B'"
-+   " AND Job.JobStatus = 'T' AND Media.Enabled=1"
-    " ORDER by Job.StartTime";
--
- const char *sql_smallest_vol = 
-    "SELECT Media.MediaId FROM Media,Pool,JobMedia WHERE"
-    " Media.MediaId in (SELECT DISTINCT MediaId from JobMedia) AND"
-@@ -570,7 +571,6 @@
- const char *sql_job_bytes =
-    "SELECT SUM(JobBytes) FROM Job WHERE JobId IN (%s)";
--
- /* Get Media Ids in Pool */
- const char *sql_mediaids =
-    "SELECT MediaId FROM Media,Pool WHERE"
diff --git a/bacula/patches/2.4.3-migrate2.patch b/bacula/patches/2.4.3-migrate2.patch
deleted file mode 100644 (file)
index 9d37e8c..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-
- This patch should fix two bugs: 
- - Bug #1206 -- sql error when there are no files to migrate. 
- - Bug #1171 -- Job catalog log is not migrated during migration.
-
- Apply it to a fully patched (requires two previous migration patches)
- 2.4.3 version  with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-migrate2.patch
- ./configure <your-options>
- make
- ...
- make install
-
-
-Index: src/dird/migrate.c
-===================================================================
---- src/dird/migrate.c (revision 8152)
-+++ src/dird/migrate.c (working copy)
-@@ -122,6 +122,12 @@
-    Dmsg2(dbglevel, "Read pool=%s (From %s)\n", jcr->rpool->name(), jcr->rpool_source);
-+   if (!get_or_create_fileset_record(jcr)) {
-+      Dmsg1(dbglevel, "JobId=%d no FileSet\n", (int)jcr->JobId);
-+      Jmsg(jcr, M_FATAL, 0, _("Could not get or create the FileSet record.\n"));
-+      return false;
-+   }
-+
-    /* If we find a job or jobs to migrate it is previous_jr.JobId */
-    count = get_job_to_migrate(jcr);
-    if (count < 0) {
-@@ -139,12 +145,6 @@
-       return true;                    /* no work */
-    }
--   if (!get_or_create_fileset_record(jcr)) {
--      Dmsg1(dbglevel, "JobId=%d no FileSet\n", (int)jcr->JobId);
--      Jmsg(jcr, M_FATAL, 0, _("Could not get or create the FileSet record.\n"));
--      return false;
--   }
--
-    create_restore_bootstrap_file(jcr);
-    if (jcr->previous_jr.JobId == 0 || jcr->ExpectedFiles == 0) {
-@@ -1062,6 +1062,11 @@
-     *  mig_jcr is jcr of the newly migrated job.
-     */
-    if (mig_jcr) {
-+      char old_jobid[50], new_jobid[50];
-+
-+      edit_uint64(jcr->previous_jr.JobId, old_jobid);
-+      edit_uint64(mig_jcr->jr.JobId, new_jobid);
-+
-       mig_jcr->JobFiles = jcr->JobFiles = jcr->SDJobFiles;
-       mig_jcr->JobBytes = jcr->JobBytes = jcr->SDJobBytes;
-       mig_jcr->VolSessionId = jcr->VolSessionId;
-@@ -1076,7 +1081,7 @@
-                   "JobTDate=%s WHERE JobId=%s", 
-          jcr->previous_jr.cStartTime, jcr->previous_jr.cEndTime, 
-          edit_uint64(jcr->previous_jr.JobTDate, ec1),
--         edit_uint64(mig_jcr->jr.JobId, ec2));
-+         new_jobid);
-       db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
-       /*
-@@ -1086,15 +1091,13 @@
-        *   - Purge the File records from the previous job
-        */
-       if (jcr->JobType == JT_MIGRATE && jcr->JobStatus == JS_Terminated) {
--         char old_jobid[50], new_jobid[50];
-          Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s",
--              (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, new_jobid));
-+              (char)JT_MIGRATED_JOB, old_jobid);
-          db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
-          UAContext *ua = new_ua_context(jcr);
-          /* Move JobLog to new JobId */
-          Mmsg(query, "UPDATE Log SET JobId=%s WHERE JobId=%s",
--           new_jobid,
--           edit_uint64(jcr->previous_jr.JobId, old_jobid));
-+           new_jobid, old_jobid);
-          db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
-          /* Purge all old file records, but leave Job record */
-          purge_files_from_jobs(ua, old_jobid);
diff --git a/bacula/patches/2.4.3-orphaned-jobs.patch b/bacula/patches/2.4.3-orphaned-jobs.patch
deleted file mode 100644 (file)
index 6162c9e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-
- This patch fixes a case of orphaned jobs (and possible deadlock)
- during pruning.
- Apply it to Bacula 2.4.3 (possibly earlier versions) with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-orphaned-jobs.patch
- ./configure <your-options>
- make
- ...
- make install
-
-Index: src/dird/ua_prune.c
-===================================================================
---- src/dird/ua_prune.c        (revision 7949)
-+++ src/dird/ua_prune.c        (working copy)
-@@ -468,6 +468,7 @@
-             break;
-          }
-       }
-+      endeach_jcr(jcr);
-       if (skip) {
-          continue;
-       }
diff --git a/bacula/patches/2.4.3-prune.patch b/bacula/patches/2.4.3-prune.patch
deleted file mode 100644 (file)
index 7af00a7..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-
- This patch should fix the bug reported on the bacula-users list where
- a retention period of 100 years does immediate prunning.
- Apply it to 2.4.3 (or earlier versions) with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-prune.patch
- ./configure <your-options>
- make
- ...
- make install
-
-Index: src/dird/ua_prune.c
-===================================================================
---- src/dird/ua_prune.c        (revision 7757)
-+++ src/dird/ua_prune.c        (working copy)
-@@ -202,7 +202,7 @@
-    now = (utime_t)time(NULL);
-    /* Select Jobs -- for counting */
--   Mmsg(query, count_select_job, edit_uint64(now - period, ed1), 
-+   Mmsg(query, count_select_job, edit_int64(now - period, ed1), 
-         edit_int64(cr.ClientId, ed2));
-    Dmsg3(050, "select now=%u period=%u sql=%s\n", (uint32_t)now, 
-                (uint32_t)period, query.c_str());
-@@ -230,7 +230,7 @@
-    del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
-    /* Now process same set but making a delete list */
--   Mmsg(query, select_job, edit_uint64(now - period, ed1), 
-+   Mmsg(query, select_job, edit_int64(now - period, ed1), 
-         edit_int64(cr.ClientId, ed2));
-    db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)&del);
-@@ -318,7 +318,7 @@
-     * Select all files that are older than the JobRetention period
-     *  and stuff them into the "DeletionCandidates" table.
-     */
--   edit_uint64(now - period, ed1);
-+   edit_int64(now - period, ed1);
-    Mmsg(query, insert_delcand, (char)JobType, ed1, 
-         edit_int64(cr.ClientId, ed2));
-    if (!db_sql_query(ua->db, query.c_str(), NULL, (void *)NULL)) {
-@@ -443,10 +443,10 @@
-    edit_int64(mr->MediaId, ed1); 
-    period = mr->VolRetention;
-    now = (utime_t)time(NULL);
--   edit_uint64(now-period, ed2);
-+   edit_int64(now-period, ed2);
-    Mmsg(query, sel_JobMedia, ed1, ed2);
--   Dmsg3(250, "Now=%d period=%d now-period=%d\n", (int)now, (int)period,
--      (int)(now-period));
-+   Dmsg3(250, "Now=%d period=%d now-period=%s\n", (int)now, (int)period,
-+      ed2);
-    Dmsg1(050, "Query=%s\n", query.c_str());
-    if (!db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)del)) {
diff --git a/bacula/patches/2.4.3-purge-bug.patch b/bacula/patches/2.4.3-purge-bug.patch
deleted file mode 100644 (file)
index 4682962..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-
- This patch corrects appears to fix bug #1188, where a Volume can
- be purged while it is being written.
-
- Apply it to Bacula 2.4.3 (possibly earlier versions)
- with:
-
- cd <bacula-source>
- patch -p0 <2.4.3-purge-bug.patch
- ./configure <your-options>
- make
- ...
- make install
-
-
-Index: src/dird/ua_purge.c
-===================================================================
---- src/dird/ua_purge.c        (revision 8054)
-+++ src/dird/ua_purge.c        (working copy)
-@@ -463,6 +463,9 @@
-    bool purged = false;
-    char ed1[50];
-+   if (mr->FirstWritten == 0 || mr->LastWritten == 0) {
-+      goto bail_out;               /* not written cannot purge */
-+   }
-    if (strcmp(mr->VolStatus, "Purged") == 0) {
-       purged = true;
-       goto bail_out;
diff --git a/bacula/patches/2.4.3-win32-runscript-unicode-path.patch b/bacula/patches/2.4.3-win32-runscript-unicode-path.patch
deleted file mode 100644 (file)
index b4b0674..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-
- This patch fix #1110 about a problem when executing a program with
- Unicode path.
-
- It can be applied to 2.4.3 (and previous versions) with:
-
-  cd <bacula-source>
-  patch -p0 <2.4.3-win32-runscript-unicode-path.patch
-  ./configure <your-options>
-  make
-  ...
-  make install
-
-
-Index: src/win32/compat/compat.cpp
-===================================================================
---- src/win32/compat/compat.cpp        (révision 7772)
-+++ src/win32/compat/compat.cpp        (copie de travail)
-@@ -1807,6 +1807,97 @@
- }
- /**
-+ * Create the process with UTF8 API
-+ */
-+static BOOL
-+CreateChildProcessW(const char *comspec, const char *cmdLine,
-+                    PROCESS_INFORMATION *hProcInfo,
-+                    HANDLE in, HANDLE out, HANDLE err)
-+{
-+   STARTUPINFOW siStartInfo;
-+   BOOL bFuncRetn = FALSE;
-+
-+   // Set up members of the STARTUPINFO structure.
-+   ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
-+   siStartInfo.cb = sizeof(siStartInfo);
-+   // setup new process to use supplied handles for stdin,stdout,stderr
-+
-+   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-+   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
-+
-+   siStartInfo.hStdInput = in;
-+   siStartInfo.hStdOutput = out;
-+   siStartInfo.hStdError = err;
-+   
-+   // Convert argument to WCHAR
-+   POOLMEM *cmdLine_wchar = get_pool_memory(PM_FNAME);
-+   POOLMEM *comspec_wchar = get_pool_memory(PM_FNAME);
-+
-+   UTF8_2_wchar(&cmdLine_wchar, cmdLine);
-+   UTF8_2_wchar(&comspec_wchar, comspec);
-+
-+   // Create the child process.
-+   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec_wchar, cmdLine_wchar);
-+
-+   // try to execute program
-+   bFuncRetn = p_CreateProcessW((WCHAR*)comspec_wchar,
-+                                (WCHAR*)cmdLine_wchar,// command line
-+                                NULL,      // process security attributes
-+                                NULL,      // primary thread security attributes
-+                                TRUE,      // handles are inherited
-+                                0,         // creation flags
-+                                NULL,      // use parent's environment
-+                                NULL,      // use parent's current directory
-+                                &siStartInfo,  // STARTUPINFO pointer
-+                                hProcInfo);   // receives PROCESS_INFORMATION
-+
-+   free_pool_memory(cmdLine_wchar);
-+   free_pool_memory(comspec_wchar);
-+
-+   return bFuncRetn;
-+}
-+
-+
-+/**
-+ * Create the process with ANSI API
-+ */
-+static BOOL
-+CreateChildProcessA(const char *comspec, char *cmdLine,
-+                    PROCESS_INFORMATION *hProcInfo,
-+                    HANDLE in, HANDLE out, HANDLE err)
-+{
-+   STARTUPINFOA siStartInfo;
-+   BOOL bFuncRetn = FALSE;
-+
-+   // Set up members of the STARTUPINFO structure.
-+   ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
-+   siStartInfo.cb = sizeof(siStartInfo);
-+   // setup new process to use supplied handles for stdin,stdout,stderr
-+   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
-+   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
-+
-+   siStartInfo.hStdInput = in;
-+   siStartInfo.hStdOutput = out;
-+   siStartInfo.hStdError = err;
-+
-+   // Create the child process.
-+   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
-+
-+   // try to execute program
-+   bFuncRetn = p_CreateProcessA(comspec,
-+                                cmdLine,  // command line
-+                                NULL,     // process security attributes
-+                                NULL,     // primary thread security attributes
-+                                TRUE,     // handles are inherited
-+                                0,        // creation flags
-+                                NULL,     // use parent's environment
-+                                NULL,     // use parent's current directory
-+                                &siStartInfo,// STARTUPINFO pointer
-+                                hProcInfo);// receives PROCESS_INFORMATION
-+   return bFuncRetn;
-+}
-+
-+/**
-  * OK, so it would seem CreateProcess only handles true executables:
-  * .com or .exe files.  So grab $COMSPEC value and pass command line to it.
-  */
-@@ -1815,44 +1906,30 @@
- {
-    static const char *comspec = NULL;
-    PROCESS_INFORMATION piProcInfo;
--   STARTUPINFOA siStartInfo;
-    BOOL bFuncRetn = FALSE;
--   if (comspec == NULL) {
-+   if (!p_CreateProcessA || !p_CreateProcessW)
-+      return INVALID_HANDLE_VALUE;
-+
-+   if (comspec == NULL) 
-       comspec = getenv("COMSPEC");
--   }
-    if (comspec == NULL) // should never happen
-       return INVALID_HANDLE_VALUE;
-    // Set up members of the PROCESS_INFORMATION structure.
-    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
--   // Set up members of the STARTUPINFO structure.
--
--   ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
--   siStartInfo.cb = sizeof(STARTUPINFO);
--   // setup new process to use supplied handles for stdin,stdout,stderr
-    // if supplied handles are not used the send a copy of our STD_HANDLE
-    // as appropriate
--   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
--   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
-+   if (in == INVALID_HANDLE_VALUE)
-+      in = GetStdHandle(STD_INPUT_HANDLE);
--   if (in != INVALID_HANDLE_VALUE)
--      siStartInfo.hStdInput = in;
--   else
--      siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
-+   if (out == INVALID_HANDLE_VALUE)
-+      out = GetStdHandle(STD_OUTPUT_HANDLE);
--   if (out != INVALID_HANDLE_VALUE)
--      siStartInfo.hStdOutput = out;
--   else
--      siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
--   if (err != INVALID_HANDLE_VALUE)
--      siStartInfo.hStdError = err;
--   else
--      siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-+   if (err == INVALID_HANDLE_VALUE)
-+      err = GetStdHandle(STD_ERROR_HANDLE);
--   // Create the child process.
--
-    char *exeFile;
-    const char *argStart;
-@@ -1860,43 +1937,32 @@
-       return INVALID_HANDLE_VALUE;
-    }
--   int cmdLen = strlen(comspec) + 4 + strlen(exeFile) + strlen(argStart) + 1;
-+   POOL_MEM cmdLine(PM_FNAME);
-+   Mmsg(cmdLine, "%s /c %s%s", comspec, exeFile, argStart);
--   char *cmdLine = (char *)alloca(cmdLen);
--
--   snprintf(cmdLine, cmdLen, "%s /c %s%s", comspec, exeFile, argStart);
--
-    free(exeFile);
--   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
-+   if (p_CreateProcessW && p_MultiByteToWideChar) {
-+      bFuncRetn = CreateChildProcessW(comspec, cmdLine.c_str(), &piProcInfo,
-+                                      in, out, err);
-+   } else {
-+      bFuncRetn = CreateChildProcessA(comspec, cmdLine.c_str(), &piProcInfo,
-+                                      in, out, err);
-+   }
--   // try to execute program
--   bFuncRetn = CreateProcessA(comspec,
--                              cmdLine,       // command line
--                              NULL,          // process security attributes
--                              NULL,          // primary thread security attributes
--                              TRUE,          // handles are inherited
--                              0,             // creation flags
--                              NULL,          // use parent's environment
--                              NULL,          // use parent's current directory
--                              &siStartInfo,  // STARTUPINFO pointer
--                              &piProcInfo);  // receives PROCESS_INFORMATION
--
-    if (bFuncRetn == 0) {
-       ErrorExit("CreateProcess failed\n");
-       const char *err = errorString();
--      Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n", comspec, cmdLine, err);
-+      Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n",comspec,cmdLine.c_str(),err);
-       LocalFree((void *)err);
-       return INVALID_HANDLE_VALUE;
-    }
-    // we don't need a handle on the process primary thread so we close
-    // this now.
-    CloseHandle(piProcInfo.hThread);
--
-    return piProcInfo.hProcess;
- }
--
- void
- ErrorExit (LPCSTR lpszMessage)
- {
-Index: src/win32/compat/winapi.c
-===================================================================
---- src/win32/compat/winapi.c  (révision 7772)
-+++ src/win32/compat/winapi.c  (copie de travail)
-@@ -88,6 +88,9 @@
- t_SHGetFolderPath       p_SHGetFolderPath = NULL;
-+t_CreateProcessA        p_CreateProcessA = NULL;
-+t_CreateProcessW        p_CreateProcessW = NULL;
-+
- void 
- InitWinAPIWrapper() 
- {
-@@ -104,6 +107,12 @@
-    HMODULE hLib = LoadLibraryA("KERNEL32.DLL");
-    if (hLib) {
-+      /* create process calls */
-+      p_CreateProcessA = (t_CreateProcessA)
-+         GetProcAddress(hLib, "CreateProcessA");
-+      p_CreateProcessW = (t_CreateProcessW)
-+         GetProcAddress(hLib, "CreateProcessW");
-+
-       /* create file calls */
-       p_CreateFileA = (t_CreateFileA)
-           GetProcAddress(hLib, "CreateFileA");
-Index: src/win32/winapi.h
-===================================================================
---- src/win32/winapi.h (révision 7772)
-+++ src/win32/winapi.h (copie de travail)
-@@ -138,6 +138,32 @@
- typedef BOOL (WINAPI * t_AttachConsole) (DWORD);
-+typedef BOOL (WINAPI *t_CreateProcessA) (
-+   LPCSTR,
-+   LPSTR,
-+   LPSECURITY_ATTRIBUTES,
-+   LPSECURITY_ATTRIBUTES,
-+   BOOL,
-+   DWORD,
-+   PVOID,
-+   LPCSTR,
-+   LPSTARTUPINFOA,
-+   LPPROCESS_INFORMATION);
-+typedef BOOL (WINAPI *t_CreateProcessW) (
-+   LPCWSTR,
-+   LPWSTR,
-+   LPSECURITY_ATTRIBUTES,
-+   LPSECURITY_ATTRIBUTES,
-+   BOOL,
-+   DWORD,
-+   PVOID,
-+   LPCWSTR,
-+   LPSTARTUPINFOW,
-+   LPPROCESS_INFORMATION);
-+
-+extern t_CreateProcessA DLL_IMP_EXP p_CreateProcessA;
-+extern t_CreateProcessW DLL_IMP_EXP p_CreateProcessW;
-+
- extern t_GetFileAttributesA   DLL_IMP_EXP p_GetFileAttributesA;
- extern t_GetFileAttributesW   DLL_IMP_EXP p_GetFileAttributesW;
index 72a6867a3a70b18af2f30ac4b1b0fe5dc688b596..367a0d6dad3cfa59a08eddc6bdf25df1a5955b0a 100644 (file)
@@ -1,3 +1,16 @@
+
+ This patch fixes bug #1211 crash during reload with bad dird.conf file.
+
+ Apply it to version 2.4.4 with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.4-reload.patch
+ ./configure <your options>
+ make
+ ...
+ make install
+
+
 Index: src/lib/parse_conf.c
 ===================================================================
 --- src/lib/parse_conf.c       (revision 8393)
diff --git a/bacula/patches/2.4.4-tray-sizing.patch b/bacula/patches/2.4.4-tray-sizing.patch
new file mode 100644 (file)
index 0000000..abeffb7
--- /dev/null
@@ -0,0 +1,59 @@
+
+ This patch fixes a text sizing problem in the tray-monitor.
+ It fixes bug #1219.
+
+ Apply it to version 2.4.4 with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.4-tray-sizing.patch
+ ./configure <your options>
+ make
+ ...
+ make install
+
+
+Index: src/tray-monitor/tray-monitor.c
+===================================================================
+--- src/tray-monitor/tray-monitor.c    (revision 8393)
++++ src/tray-monitor/tray-monitor.c    (working copy)
+@@ -1,7 +1,7 @@
+ /*
+    Bacula® - The Network Backup Solution
+-   Copyright (C) 2004-2007 Free Software Foundation Europe e.V.
++   Copyright (C) 2004-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.
+@@ -97,6 +97,7 @@
+ static GtkWidget *textview;
+ static GtkTextBuffer *buffer;
+ static GtkWidget *timeoutspinner;
++static GtkWidget *scrolledWindow;
+ char** xpm_generic_var;
+ static gboolean blinkstate = TRUE;
+@@ -409,9 +410,13 @@
+    }
+    gtk_box_pack_start(GTK_BOX(vbox), daemon_table, FALSE, FALSE, 0);
+-
++  
+    textview = gtk_text_view_new();
++   scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
++   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
++   gtk_container_add(GTK_CONTAINER (scrolledWindow), textview);
++   
+    buffer = gtk_text_buffer_new(NULL);
+    gtk_text_buffer_set_text(buffer, "", -1);
+@@ -456,7 +461,7 @@
+    gtk_text_view_set_buffer(GTK_TEXT_VIEW(textview), buffer);
+-   gtk_box_pack_start(GTK_BOX(vbox), textview, TRUE, TRUE, 0);
++   gtk_box_pack_start(GTK_BOX(vbox), scrolledWindow, TRUE, TRUE, 0);
+    GtkWidget* hbox = gtk_hbox_new(FALSE, 10);
diff --git a/bacula/patches/2.4.x/2.4.3-getmsg.patch b/bacula/patches/2.4.x/2.4.3-getmsg.patch
new file mode 100644 (file)
index 0000000..926cbcd
--- /dev/null
@@ -0,0 +1,135 @@
+ This patch used the jcr stored in the BSOCK packet during callbacks
+ to the Director rather than looking them up in the JCR list.
+
+ It can be applied to Bacula version 2.4.3 (or earlier) with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.3-getmsg.patch
+ ./configure <your options>
+ make
+ ...
+ make install
+
+
+Index: src/dird/getmsg.c
+===================================================================
+--- src/dird/getmsg.c  (revision 7970)
++++ src/dird/getmsg.c  (working copy)
+@@ -1,7 +1,7 @@
+ /*
+    Bacula® - The Network Backup Solution
+-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
++   Copyright (C) 2000-2008 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.
+@@ -20,7 +20,7 @@
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+-   Bacula® is a registered trademark of John Walker.
++   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.
+@@ -102,12 +102,12 @@
+    char Job[MAX_NAME_LENGTH];
+    char MsgType[20];
+    int type, level;
+-   JCR *jcr;
++   JCR *jcr = bs->jcr();
+    char *msg;
+    for (;;) {
+       n = bs->recv();
+-      Dmsg2(100, "bget_dirmsg %d: %s", n, bs->msg);
++      Dmsg2(300, "bget_dirmsg %d: %s\n", n, bs->msg);
+       if (is_bnet_stop(bs)) {
+          return n;                    /* error or terminate */
+@@ -142,7 +142,7 @@
+             bs->fsend("btime %s\n", edit_uint64(get_current_btime(),ed1));
+             break;
+          default:
+-            Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
++            Jmsg1(jcr, M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
+             return n;
+          }
+          continue;
+@@ -160,21 +160,13 @@
+        *  Try to fulfill it.
+        */
+       if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) {
+-         Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
++         Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+          continue;
+       }
+-      if (strcmp(Job, "*System*") == 0) {
+-         jcr = NULL;                  /* No jcr */
+-      } else if (!(jcr=get_jcr_by_full_name(Job))) {
+-         Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg);
+-         continue;
+-      }
+-      Dmsg1(900, "Getmsg got jcr 0x%x\n", jcr);
+       /* Skip past "Jmsg Job=nnn" */
+       if (!(msg=find_msg_start(bs->msg))) {
+-         Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+-         free_jcr(jcr);
++         Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+          continue;
+       }
+@@ -185,8 +177,7 @@
+       if (bs->msg[0] == 'J') {           /* Job message */
+          if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d",
+                     Job, &type, &level) != 3) {
+-            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+-            free_jcr(jcr);
++            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+             continue;
+          }
+          Dmsg1(900, "Got msg: %s\n", bs->msg);
+@@ -199,7 +190,6 @@
+          }
+          Dmsg1(900, "Dispatch msg: %s", msg);
+          dispatch_message(jcr, type, level, msg);
+-         free_jcr(jcr);
+          continue;
+       }
+       /*
+@@ -209,21 +199,16 @@
+       if (bs->msg[0] == 'C') {        /* Catalog request */
+          Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg);
+          catalog_request(jcr, bs);
+-         Dmsg1(900, "Calling freejcr 0x%x\n", jcr);
+-         free_jcr(jcr);
+          continue;
+       }
+       if (bs->msg[0] == 'U') {        /* SD sending attributes */
+          Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg);
+          catalog_update(jcr, bs);
+-         Dmsg1(900, "Calling freejcr 0x%x\n", jcr);
+-         free_jcr(jcr);
+          continue;
+       }
+       if (bs->msg[0] == 'M') {        /* Mount request */
+          Dmsg1(900, "Mount req: %s", bs->msg);
+          mount_request(jcr, bs, msg);
+-         free_jcr(jcr);
+          continue;
+       }
+       if (bs->msg[0] == 'S') {       /* Status change */
+@@ -232,9 +217,8 @@
+          if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) {
+             jcr->SDJobStatus = JobStatus; /* current status */
+          } else {
+-            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
++            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+          }
+-         free_jcr(jcr);
+          continue;
+       }
+ #ifdef needed
diff --git a/bacula/patches/2.4.x/2.4.3-jobs.patch b/bacula/patches/2.4.x/2.4.3-jobs.patch
new file mode 100644 (file)
index 0000000..25d2d3c
--- /dev/null
@@ -0,0 +1,127 @@
+
+ This patch corrects two problems:
+ 1. If you start more than 60 jobs within a 1 minute period, the unique
+    jobname (critical for the daemons) can be duplicated leading to 
+    authentication failures and orphaned jobs.
+ 2. FD jobs that fail SD authentication were not properly cleaned up.
+
+ Apply it to Bacula 2.4.3 (possibly earlier versions)
+ with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.3-jobs.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+
+Index: src/dird/job.c
+===================================================================
+--- src/dird/job.c     (revision 8011)
++++ src/dird/job.c     (working copy)
+@@ -758,17 +758,17 @@
+    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+    static time_t last_start_time = 0;
+    static int seq = 0;
+-   time_t now;
++   time_t now = time(NULL);
+    struct tm tm;
+    char dt[MAX_TIME_LENGTH];
+    char name[MAX_NAME_LENGTH];
+    char *p;
++   int len;
+    /* Guarantee unique start time -- maximum one per second, and
+     * thus unique Job Name
+     */
+    P(mutex);                          /* lock creation of jobs */
+-   now = time(NULL);
+    seq++;
+    if (seq > 59) {                    /* wrap as if it is seconds */
+       seq = 0;
+@@ -783,9 +783,10 @@
+    /* Form Unique JobName */
+    (void)localtime_r(&now, &tm);
+    /* Use only characters that are permitted in Windows filenames */
+-   strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M", &tm);
++   strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
++   len = strlen(dt) + 5;   /* dt + .%02d EOS */
+    bstrncpy(name, base_name, sizeof(name));
+-   name[sizeof(name)-22] = 0;          /* truncate if too long */
++   name[sizeof(name)-len] = 0;          /* truncate if too long */
+    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s.%02d", name, dt, seq); /* add date & time */
+    /* Convert spaces into underscores */
+    for (p=jcr->Job; *p; p++) {
+@@ -793,6 +794,7 @@
+          *p = '_';
+       }
+    }
++   Dmsg2(100, "JobId=%u created Job=%s\n", jcr->JobId, jcr->Job);
+ }
+ /* Called directly from job rescheduling */
+Index: src/stored/job.c
+===================================================================
+--- src/stored/job.c   (revision 8011)
++++ src/stored/job.c   (working copy)
+@@ -228,21 +228,25 @@
+    if (!(jcr=get_jcr_by_full_name(job_name))) {
+       Jmsg1(NULL, M_FATAL, 0, _("FD connect failed: Job name not found: %s\n"), job_name);
+       Dmsg1(3, "**** Job \"%s\" not found\n", job_name);
++      fd->close();
+       return;
+    }
+-   jcr->file_bsock = fd;
+-   jcr->file_bsock->set_jcr(jcr);
+-
+    Dmsg1(110, "Found Job %s\n", job_name);
+    if (jcr->authenticated) {
+       Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s already authenticated.\n"),
+          (uint32_t)jcr->JobId, jcr->Job);
++      Dmsg2(50, "Hey!!!! JobId %u Job %s already authenticated.\n",
++         (uint32_t)jcr->JobId, jcr->Job);
++      fd->close();
+       free_jcr(jcr);
+       return;
+    }
++   jcr->file_bsock = fd;
++   jcr->file_bsock->set_jcr(jcr);
++
+    /*
+     * Authenticate the File daemon
+     */
+Index: src/lib/bnet_server.c
+===================================================================
+--- src/lib/bnet_server.c      (revision 8011)
++++ src/lib/bnet_server.c      (working copy)
+@@ -1,7 +1,7 @@
+ /*
+    Bacula® - The Network Backup Solution
+-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
++   Copyright (C) 2000-2008 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.
+@@ -20,7 +20,7 @@
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+-   Bacula® is a registered trademark of John Walker.
++   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.
+@@ -137,7 +137,7 @@
+                   be.bstrerror());
+          }
+       }
+-      listen(fd_ptr->fd, 5);       /* tell system we are ready */
++      listen(fd_ptr->fd, 20);      /* tell system we are ready */
+       sockfds.append(fd_ptr);
+    }
+    /* Start work queue thread */
diff --git a/bacula/patches/2.4.x/2.4.3-migrate-log.patch b/bacula/patches/2.4.x/2.4.3-migrate-log.patch
new file mode 100644 (file)
index 0000000..c593cc2
--- /dev/null
@@ -0,0 +1,71 @@
+
+ This patch should cause all Job Log records to be migrated when the
+ Job is migrated. It fixes the second issue reported in bug #1171.
+
+ Apply it to Bacula 2.4.3 (possibly earlier versions)
+ with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.3-migrate.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+Index: src/dird/migrate.c
+===================================================================
+--- src/dird/migrate.c (revision 7926)
++++ src/dird/migrate.c (working copy)
+@@ -402,14 +402,6 @@
+    }
+    migration_cleanup(jcr, jcr->JobStatus);
+-   if (mig_jcr) {
+-      char jobid[50];
+-      UAContext *ua = new_ua_context(jcr);
+-      edit_uint64(jcr->previous_jr.JobId, jobid);
+-      /* Purge all old file records, but leave Job record */
+-      purge_files_from_jobs(ua, jobid);
+-      free_ua_context(ua);
+-   }
+    return true;
+ }
+@@ -1087,11 +1079,26 @@
+          edit_uint64(mig_jcr->jr.JobId, ec2));
+       db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
+-      /* Now mark the previous job as migrated if it terminated normally */
+-      if (jcr->JobStatus == JS_Terminated) {
++      /*
++       * If we terminated a migration normally:
++       *   - mark the previous job as migrated
++       *   - move any Log records to the new JobId
++       *   - Purge the File records from the previous job
++       */
++      if (jcr->JobType == JT_MIGRATE && jcr->JobStatus == JS_Terminated) {
++         char old_jobid[50], new_jobid[50];
+          Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s",
+-              (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, ec1));
++              (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, new_jobid));
+          db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
++         UAContext *ua = new_ua_context(jcr);
++         /* Move JobLog to new JobId */
++         Mmsg(query, "UPDATE Log SET JobId=%s WHERE JobId=%s",
++           new_jobid,
++           edit_uint64(jcr->previous_jr.JobId, old_jobid));
++         db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
++         /* Purge all old file records, but leave Job record */
++         purge_files_from_jobs(ua, old_jobid);
++         free_ua_context(ua);
+       } 
+       if (!db_get_job_record(jcr, jcr->db, &jcr->jr)) {
+@@ -1100,7 +1107,6 @@
+          set_jcr_job_status(jcr, JS_ErrorTerminated);
+       }
+-
+       update_bootstrap_file(mig_jcr);
+       if (!db_get_job_volume_names(mig_jcr, mig_jcr->db, mig_jcr->jr.JobId, &mig_jcr->VolumeName)) {
diff --git a/bacula/patches/2.4.x/2.4.3-migrate.patch b/bacula/patches/2.4.x/2.4.3-migrate.patch
new file mode 100644 (file)
index 0000000..138c09c
--- /dev/null
@@ -0,0 +1,53 @@
+
+ This patch should prevent migration jobs from attempting to migrate
+ jobs that failed.  Apply it to Bacula 2.4.3 (possibly earlier versions)
+ with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.3-migrate.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+
+Index: src/dird/migrate.c
+===================================================================
+--- src/dird/migrate.c (revision 7757)
++++ src/dird/migrate.c (working copy)
+@@ -377,7 +377,7 @@
+     * to avoid two threads from using the BSOCK structure at
+     * the same time.
+     */
+-   if (!bnet_fsend(sd, "run")) {
++   if (!sd->fsend("run")) {
+       return false;
+    }
+@@ -520,6 +520,7 @@
+    "SELECT DISTINCT Job.JobId,Job.StartTime FROM Job,Pool,Client"
+    " WHERE Client.Name='%s' AND Pool.Name='%s' AND Job.PoolId=Pool.PoolId"
+    " AND Job.ClientId=Client.ClientId AND Job.Type='B'"
++   " AND Job.JobStatus = 'T'"
+    " ORDER by Job.StartTime";
+ /* Get Volume names in Pool */
+@@ -533,9 +534,9 @@
+    "SELECT DISTINCT Job.JobId,Job.StartTime FROM Media,JobMedia,Job"
+    " WHERE Media.VolumeName='%s' AND Media.MediaId=JobMedia.MediaId"
+    " AND JobMedia.JobId=Job.JobId AND Job.Type='B'"
++   " AND Job.JobStatus = 'T' AND Media.Enabled=1"
+    " ORDER by Job.StartTime";
+-
+ const char *sql_smallest_vol = 
+    "SELECT Media.MediaId FROM Media,Pool,JobMedia WHERE"
+    " Media.MediaId in (SELECT DISTINCT MediaId from JobMedia) AND"
+@@ -570,7 +571,6 @@
+ const char *sql_job_bytes =
+    "SELECT SUM(JobBytes) FROM Job WHERE JobId IN (%s)";
+-
+ /* Get Media Ids in Pool */
+ const char *sql_mediaids =
+    "SELECT MediaId FROM Media,Pool WHERE"
diff --git a/bacula/patches/2.4.x/2.4.3-migrate2.patch b/bacula/patches/2.4.x/2.4.3-migrate2.patch
new file mode 100644 (file)
index 0000000..9d37e8c
--- /dev/null
@@ -0,0 +1,85 @@
+
+ This patch should fix two bugs: 
+ - Bug #1206 -- sql error when there are no files to migrate. 
+ - Bug #1171 -- Job catalog log is not migrated during migration.
+
+ Apply it to a fully patched (requires two previous migration patches)
+ 2.4.3 version  with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.3-migrate2.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+
+Index: src/dird/migrate.c
+===================================================================
+--- src/dird/migrate.c (revision 8152)
++++ src/dird/migrate.c (working copy)
+@@ -122,6 +122,12 @@
+    Dmsg2(dbglevel, "Read pool=%s (From %s)\n", jcr->rpool->name(), jcr->rpool_source);
++   if (!get_or_create_fileset_record(jcr)) {
++      Dmsg1(dbglevel, "JobId=%d no FileSet\n", (int)jcr->JobId);
++      Jmsg(jcr, M_FATAL, 0, _("Could not get or create the FileSet record.\n"));
++      return false;
++   }
++
+    /* If we find a job or jobs to migrate it is previous_jr.JobId */
+    count = get_job_to_migrate(jcr);
+    if (count < 0) {
+@@ -139,12 +145,6 @@
+       return true;                    /* no work */
+    }
+-   if (!get_or_create_fileset_record(jcr)) {
+-      Dmsg1(dbglevel, "JobId=%d no FileSet\n", (int)jcr->JobId);
+-      Jmsg(jcr, M_FATAL, 0, _("Could not get or create the FileSet record.\n"));
+-      return false;
+-   }
+-
+    create_restore_bootstrap_file(jcr);
+    if (jcr->previous_jr.JobId == 0 || jcr->ExpectedFiles == 0) {
+@@ -1062,6 +1062,11 @@
+     *  mig_jcr is jcr of the newly migrated job.
+     */
+    if (mig_jcr) {
++      char old_jobid[50], new_jobid[50];
++
++      edit_uint64(jcr->previous_jr.JobId, old_jobid);
++      edit_uint64(mig_jcr->jr.JobId, new_jobid);
++
+       mig_jcr->JobFiles = jcr->JobFiles = jcr->SDJobFiles;
+       mig_jcr->JobBytes = jcr->JobBytes = jcr->SDJobBytes;
+       mig_jcr->VolSessionId = jcr->VolSessionId;
+@@ -1076,7 +1081,7 @@
+                   "JobTDate=%s WHERE JobId=%s", 
+          jcr->previous_jr.cStartTime, jcr->previous_jr.cEndTime, 
+          edit_uint64(jcr->previous_jr.JobTDate, ec1),
+-         edit_uint64(mig_jcr->jr.JobId, ec2));
++         new_jobid);
+       db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
+       /*
+@@ -1086,15 +1091,13 @@
+        *   - Purge the File records from the previous job
+        */
+       if (jcr->JobType == JT_MIGRATE && jcr->JobStatus == JS_Terminated) {
+-         char old_jobid[50], new_jobid[50];
+          Mmsg(query, "UPDATE Job SET Type='%c' WHERE JobId=%s",
+-              (char)JT_MIGRATED_JOB, edit_uint64(jcr->previous_jr.JobId, new_jobid));
++              (char)JT_MIGRATED_JOB, old_jobid);
+          db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
+          UAContext *ua = new_ua_context(jcr);
+          /* Move JobLog to new JobId */
+          Mmsg(query, "UPDATE Log SET JobId=%s WHERE JobId=%s",
+-           new_jobid,
+-           edit_uint64(jcr->previous_jr.JobId, old_jobid));
++           new_jobid, old_jobid);
+          db_sql_query(mig_jcr->db, query.c_str(), NULL, NULL);
+          /* Purge all old file records, but leave Job record */
+          purge_files_from_jobs(ua, old_jobid);
diff --git a/bacula/patches/2.4.x/2.4.3-orphaned-jobs.patch b/bacula/patches/2.4.x/2.4.3-orphaned-jobs.patch
new file mode 100644 (file)
index 0000000..6162c9e
--- /dev/null
@@ -0,0 +1,24 @@
+
+ This patch fixes a case of orphaned jobs (and possible deadlock)
+ during pruning.
+ Apply it to Bacula 2.4.3 (possibly earlier versions) with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.3-orphaned-jobs.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+Index: src/dird/ua_prune.c
+===================================================================
+--- src/dird/ua_prune.c        (revision 7949)
++++ src/dird/ua_prune.c        (working copy)
+@@ -468,6 +468,7 @@
+             break;
+          }
+       }
++      endeach_jcr(jcr);
+       if (skip) {
+          continue;
+       }
diff --git a/bacula/patches/2.4.x/2.4.3-prune.patch b/bacula/patches/2.4.x/2.4.3-prune.patch
new file mode 100644 (file)
index 0000000..7af00a7
--- /dev/null
@@ -0,0 +1,57 @@
+
+ This patch should fix the bug reported on the bacula-users list where
+ a retention period of 100 years does immediate prunning.
+ Apply it to 2.4.3 (or earlier versions) with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.3-prune.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+Index: src/dird/ua_prune.c
+===================================================================
+--- src/dird/ua_prune.c        (revision 7757)
++++ src/dird/ua_prune.c        (working copy)
+@@ -202,7 +202,7 @@
+    now = (utime_t)time(NULL);
+    /* Select Jobs -- for counting */
+-   Mmsg(query, count_select_job, edit_uint64(now - period, ed1), 
++   Mmsg(query, count_select_job, edit_int64(now - period, ed1), 
+         edit_int64(cr.ClientId, ed2));
+    Dmsg3(050, "select now=%u period=%u sql=%s\n", (uint32_t)now, 
+                (uint32_t)period, query.c_str());
+@@ -230,7 +230,7 @@
+    del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+    /* Now process same set but making a delete list */
+-   Mmsg(query, select_job, edit_uint64(now - period, ed1), 
++   Mmsg(query, select_job, edit_int64(now - period, ed1), 
+         edit_int64(cr.ClientId, ed2));
+    db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)&del);
+@@ -318,7 +318,7 @@
+     * Select all files that are older than the JobRetention period
+     *  and stuff them into the "DeletionCandidates" table.
+     */
+-   edit_uint64(now - period, ed1);
++   edit_int64(now - period, ed1);
+    Mmsg(query, insert_delcand, (char)JobType, ed1, 
+         edit_int64(cr.ClientId, ed2));
+    if (!db_sql_query(ua->db, query.c_str(), NULL, (void *)NULL)) {
+@@ -443,10 +443,10 @@
+    edit_int64(mr->MediaId, ed1); 
+    period = mr->VolRetention;
+    now = (utime_t)time(NULL);
+-   edit_uint64(now-period, ed2);
++   edit_int64(now-period, ed2);
+    Mmsg(query, sel_JobMedia, ed1, ed2);
+-   Dmsg3(250, "Now=%d period=%d now-period=%d\n", (int)now, (int)period,
+-      (int)(now-period));
++   Dmsg3(250, "Now=%d period=%d now-period=%s\n", (int)now, (int)period,
++      ed2);
+    Dmsg1(050, "Query=%s\n", query.c_str());
+    if (!db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)del)) {
diff --git a/bacula/patches/2.4.x/2.4.3-purge-bug.patch b/bacula/patches/2.4.x/2.4.3-purge-bug.patch
new file mode 100644 (file)
index 0000000..4682962
--- /dev/null
@@ -0,0 +1,29 @@
+
+ This patch corrects appears to fix bug #1188, where a Volume can
+ be purged while it is being written.
+
+ Apply it to Bacula 2.4.3 (possibly earlier versions)
+ with:
+
+ cd <bacula-source>
+ patch -p0 <2.4.3-purge-bug.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+
+Index: src/dird/ua_purge.c
+===================================================================
+--- src/dird/ua_purge.c        (revision 8054)
++++ src/dird/ua_purge.c        (working copy)
+@@ -463,6 +463,9 @@
+    bool purged = false;
+    char ed1[50];
++   if (mr->FirstWritten == 0 || mr->LastWritten == 0) {
++      goto bail_out;               /* not written cannot purge */
++   }
+    if (strcmp(mr->VolStatus, "Purged") == 0) {
+       purged = true;
+       goto bail_out;
diff --git a/bacula/patches/2.4.x/2.4.3-win32-runscript-unicode-path.patch b/bacula/patches/2.4.x/2.4.3-win32-runscript-unicode-path.patch
new file mode 100644 (file)
index 0000000..b4b0674
--- /dev/null
@@ -0,0 +1,289 @@
+
+ This patch fix #1110 about a problem when executing a program with
+ Unicode path.
+
+ It can be applied to 2.4.3 (and previous versions) with:
+
+  cd <bacula-source>
+  patch -p0 <2.4.3-win32-runscript-unicode-path.patch
+  ./configure <your-options>
+  make
+  ...
+  make install
+
+
+Index: src/win32/compat/compat.cpp
+===================================================================
+--- src/win32/compat/compat.cpp        (révision 7772)
++++ src/win32/compat/compat.cpp        (copie de travail)
+@@ -1807,6 +1807,97 @@
+ }
+ /**
++ * Create the process with UTF8 API
++ */
++static BOOL
++CreateChildProcessW(const char *comspec, const char *cmdLine,
++                    PROCESS_INFORMATION *hProcInfo,
++                    HANDLE in, HANDLE out, HANDLE err)
++{
++   STARTUPINFOW siStartInfo;
++   BOOL bFuncRetn = FALSE;
++
++   // Set up members of the STARTUPINFO structure.
++   ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
++   siStartInfo.cb = sizeof(siStartInfo);
++   // setup new process to use supplied handles for stdin,stdout,stderr
++
++   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
++   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
++
++   siStartInfo.hStdInput = in;
++   siStartInfo.hStdOutput = out;
++   siStartInfo.hStdError = err;
++   
++   // Convert argument to WCHAR
++   POOLMEM *cmdLine_wchar = get_pool_memory(PM_FNAME);
++   POOLMEM *comspec_wchar = get_pool_memory(PM_FNAME);
++
++   UTF8_2_wchar(&cmdLine_wchar, cmdLine);
++   UTF8_2_wchar(&comspec_wchar, comspec);
++
++   // Create the child process.
++   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec_wchar, cmdLine_wchar);
++
++   // try to execute program
++   bFuncRetn = p_CreateProcessW((WCHAR*)comspec_wchar,
++                                (WCHAR*)cmdLine_wchar,// command line
++                                NULL,      // process security attributes
++                                NULL,      // primary thread security attributes
++                                TRUE,      // handles are inherited
++                                0,         // creation flags
++                                NULL,      // use parent's environment
++                                NULL,      // use parent's current directory
++                                &siStartInfo,  // STARTUPINFO pointer
++                                hProcInfo);   // receives PROCESS_INFORMATION
++
++   free_pool_memory(cmdLine_wchar);
++   free_pool_memory(comspec_wchar);
++
++   return bFuncRetn;
++}
++
++
++/**
++ * Create the process with ANSI API
++ */
++static BOOL
++CreateChildProcessA(const char *comspec, char *cmdLine,
++                    PROCESS_INFORMATION *hProcInfo,
++                    HANDLE in, HANDLE out, HANDLE err)
++{
++   STARTUPINFOA siStartInfo;
++   BOOL bFuncRetn = FALSE;
++
++   // Set up members of the STARTUPINFO structure.
++   ZeroMemory( &siStartInfo, sizeof(siStartInfo) );
++   siStartInfo.cb = sizeof(siStartInfo);
++   // setup new process to use supplied handles for stdin,stdout,stderr
++   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
++   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
++
++   siStartInfo.hStdInput = in;
++   siStartInfo.hStdOutput = out;
++   siStartInfo.hStdError = err;
++
++   // Create the child process.
++   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
++
++   // try to execute program
++   bFuncRetn = p_CreateProcessA(comspec,
++                                cmdLine,  // command line
++                                NULL,     // process security attributes
++                                NULL,     // primary thread security attributes
++                                TRUE,     // handles are inherited
++                                0,        // creation flags
++                                NULL,     // use parent's environment
++                                NULL,     // use parent's current directory
++                                &siStartInfo,// STARTUPINFO pointer
++                                hProcInfo);// receives PROCESS_INFORMATION
++   return bFuncRetn;
++}
++
++/**
+  * OK, so it would seem CreateProcess only handles true executables:
+  * .com or .exe files.  So grab $COMSPEC value and pass command line to it.
+  */
+@@ -1815,44 +1906,30 @@
+ {
+    static const char *comspec = NULL;
+    PROCESS_INFORMATION piProcInfo;
+-   STARTUPINFOA siStartInfo;
+    BOOL bFuncRetn = FALSE;
+-   if (comspec == NULL) {
++   if (!p_CreateProcessA || !p_CreateProcessW)
++      return INVALID_HANDLE_VALUE;
++
++   if (comspec == NULL) 
+       comspec = getenv("COMSPEC");
+-   }
+    if (comspec == NULL) // should never happen
+       return INVALID_HANDLE_VALUE;
+    // Set up members of the PROCESS_INFORMATION structure.
+    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
+-   // Set up members of the STARTUPINFO structure.
+-
+-   ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
+-   siStartInfo.cb = sizeof(STARTUPINFO);
+-   // setup new process to use supplied handles for stdin,stdout,stderr
+    // if supplied handles are not used the send a copy of our STD_HANDLE
+    // as appropriate
+-   siStartInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+-   siStartInfo.wShowWindow = SW_SHOWMINNOACTIVE;
++   if (in == INVALID_HANDLE_VALUE)
++      in = GetStdHandle(STD_INPUT_HANDLE);
+-   if (in != INVALID_HANDLE_VALUE)
+-      siStartInfo.hStdInput = in;
+-   else
+-      siStartInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
++   if (out == INVALID_HANDLE_VALUE)
++      out = GetStdHandle(STD_OUTPUT_HANDLE);
+-   if (out != INVALID_HANDLE_VALUE)
+-      siStartInfo.hStdOutput = out;
+-   else
+-      siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+-   if (err != INVALID_HANDLE_VALUE)
+-      siStartInfo.hStdError = err;
+-   else
+-      siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
++   if (err == INVALID_HANDLE_VALUE)
++      err = GetStdHandle(STD_ERROR_HANDLE);
+-   // Create the child process.
+-
+    char *exeFile;
+    const char *argStart;
+@@ -1860,43 +1937,32 @@
+       return INVALID_HANDLE_VALUE;
+    }
+-   int cmdLen = strlen(comspec) + 4 + strlen(exeFile) + strlen(argStart) + 1;
++   POOL_MEM cmdLine(PM_FNAME);
++   Mmsg(cmdLine, "%s /c %s%s", comspec, exeFile, argStart);
+-   char *cmdLine = (char *)alloca(cmdLen);
+-
+-   snprintf(cmdLine, cmdLen, "%s /c %s%s", comspec, exeFile, argStart);
+-
+    free(exeFile);
+-   Dmsg2(150, "Calling CreateProcess(%s, %s, ...)\n", comspec, cmdLine);
++   if (p_CreateProcessW && p_MultiByteToWideChar) {
++      bFuncRetn = CreateChildProcessW(comspec, cmdLine.c_str(), &piProcInfo,
++                                      in, out, err);
++   } else {
++      bFuncRetn = CreateChildProcessA(comspec, cmdLine.c_str(), &piProcInfo,
++                                      in, out, err);
++   }
+-   // try to execute program
+-   bFuncRetn = CreateProcessA(comspec,
+-                              cmdLine,       // command line
+-                              NULL,          // process security attributes
+-                              NULL,          // primary thread security attributes
+-                              TRUE,          // handles are inherited
+-                              0,             // creation flags
+-                              NULL,          // use parent's environment
+-                              NULL,          // use parent's current directory
+-                              &siStartInfo,  // STARTUPINFO pointer
+-                              &piProcInfo);  // receives PROCESS_INFORMATION
+-
+    if (bFuncRetn == 0) {
+       ErrorExit("CreateProcess failed\n");
+       const char *err = errorString();
+-      Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n", comspec, cmdLine, err);
++      Dmsg3(99, "CreateProcess(%s, %s, ...)=%s\n",comspec,cmdLine.c_str(),err);
+       LocalFree((void *)err);
+       return INVALID_HANDLE_VALUE;
+    }
+    // we don't need a handle on the process primary thread so we close
+    // this now.
+    CloseHandle(piProcInfo.hThread);
+-
+    return piProcInfo.hProcess;
+ }
+-
+ void
+ ErrorExit (LPCSTR lpszMessage)
+ {
+Index: src/win32/compat/winapi.c
+===================================================================
+--- src/win32/compat/winapi.c  (révision 7772)
++++ src/win32/compat/winapi.c  (copie de travail)
+@@ -88,6 +88,9 @@
+ t_SHGetFolderPath       p_SHGetFolderPath = NULL;
++t_CreateProcessA        p_CreateProcessA = NULL;
++t_CreateProcessW        p_CreateProcessW = NULL;
++
+ void 
+ InitWinAPIWrapper() 
+ {
+@@ -104,6 +107,12 @@
+    HMODULE hLib = LoadLibraryA("KERNEL32.DLL");
+    if (hLib) {
++      /* create process calls */
++      p_CreateProcessA = (t_CreateProcessA)
++         GetProcAddress(hLib, "CreateProcessA");
++      p_CreateProcessW = (t_CreateProcessW)
++         GetProcAddress(hLib, "CreateProcessW");
++
+       /* create file calls */
+       p_CreateFileA = (t_CreateFileA)
+           GetProcAddress(hLib, "CreateFileA");
+Index: src/win32/winapi.h
+===================================================================
+--- src/win32/winapi.h (révision 7772)
++++ src/win32/winapi.h (copie de travail)
+@@ -138,6 +138,32 @@
+ typedef BOOL (WINAPI * t_AttachConsole) (DWORD);
++typedef BOOL (WINAPI *t_CreateProcessA) (
++   LPCSTR,
++   LPSTR,
++   LPSECURITY_ATTRIBUTES,
++   LPSECURITY_ATTRIBUTES,
++   BOOL,
++   DWORD,
++   PVOID,
++   LPCSTR,
++   LPSTARTUPINFOA,
++   LPPROCESS_INFORMATION);
++typedef BOOL (WINAPI *t_CreateProcessW) (
++   LPCWSTR,
++   LPWSTR,
++   LPSECURITY_ATTRIBUTES,
++   LPSECURITY_ATTRIBUTES,
++   BOOL,
++   DWORD,
++   PVOID,
++   LPCWSTR,
++   LPSTARTUPINFOW,
++   LPPROCESS_INFORMATION);
++
++extern t_CreateProcessA DLL_IMP_EXP p_CreateProcessA;
++extern t_CreateProcessW DLL_IMP_EXP p_CreateProcessW;
++
+ extern t_GetFileAttributesA   DLL_IMP_EXP p_GetFileAttributesA;
+ extern t_GetFileAttributesW   DLL_IMP_EXP p_GetFileAttributesW;