General:
 
-Version 2.0.2 released: xx January 2007
+Version 2.0.2 released: 30 January 2007
 28Jan08
 kes  Fix maxruntime bug #621.
 27Jan07
 
          stat = 0;
       } else {
          stat = mdb->num_rows;
-         DBId_t *SId;
+         DBId_t *SId = NULL;
          if (stat > 0) {
             *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
             SId = (DBId_t *)malloc(stat * sizeof(DBId_t));
-         } else {
-            SId = NULL;
          }
          for (i=0; i < stat; i++) {
             if ((row = sql_fetch_row(mdb)) == NULL) {
                }
             }
          }
+         if (SId) {
+            free(SId);
+         }
       }
       sql_free_result(mdb);
    }
 
       exit(1);
    }
    already_here = true;
+   stop_watchdog();
    generate_daemon_event(NULL, "Exit");
    write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
    delete_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
    free_config_resources();
    term_ua_server();
    term_msg();                        /* terminate message handler */
-   stop_watchdog();
    cleanup_crypto();
    close_memory_pool();               /* release free memory in pool */
    sm_dump(false);
 
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2007 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.
 
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2007 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.
 
       pthread_cond_destroy(&jcr->term_wait);
       jcr->term_wait_inited = false;
    }
+   if (jcr->db) {
+      db_close_database(jcr, jcr->db);
+      jcr->db = NULL;
+   }
    if (jcr->stime) {
       Dmsg0(200, "Free JCR stime\n");
       free_pool_memory(jcr->stime);
 
             Dmsg0(2300, "Back from running new job.\n");
          }
          /* Clean up and release old jcr */
-         if (jcr->db) {
-            db_close_database(jcr, jcr->db);
-            jcr->db = NULL;
-         }
          Dmsg2(2300, "====== Termination job=%d use_cnt=%d\n", jcr->JobId, jcr->use_count());
          jcr->SDJobStatus = 0;
          V(jq->mutex);                /* release internal lock */
 
 
 bail_out:
    Dmsg2(dbglevel, "Count=%d Jobids=%s\n", ids->count, ids->list);
+   foreach_dlist(item, item_chain) {
+      free(item->item);
+   }
    delete item_chain;
    return ok;
 }
 
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2007 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.
 
     
    findFILESET *fileset = ff->fileset;
    if (fileset) {
-      int i, j;
+      int i;
+      char *fname;
       
       for (i=0; i<fileset->include_list.size(); i++) {
          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
          
          /* look through all files and check */
-         for (j=0; j<incexe->name_list.size(); j++) {
-            char *fname = (char *)incexe->name_list.get(j);
+         foreach_alist(fname, &incexe->name_list) {
             /* fname should match x:/ */
             if (strlen(fname) >= 2 && B_ISALPHA(fname[0]) 
                && fname[1] == ':') {
             ff->drivetypes = fo->drivetype;
             bstrncat(ff->VerifyOpts, fo->VerifyOpts, sizeof(ff->VerifyOpts));
          }
-         for (j=0; j<incexe->name_list.size(); j++) {
-            Dmsg1(100, "F %s\n", (char *)incexe->name_list.get(j));
-            ff->top_fname = (char *)incexe->name_list.get(j);
+         char *fname;
+         foreach_alist(fname, &incexe->name_list) {
+            Dmsg1(100, "F %s\n", fname);
+            ff->top_fname = fname;
             if (find_one_file(jcr, ff, our_callback, his_pkt, ff->top_fname, (dev_t)-1, true) == 0) {
                return 0;                  /* error return */
             }
       }
       fnm_flags = (incexe->current_opts != NULL && incexe->current_opts->flags & FO_IGNORECASE)
              ? FNM_CASEFOLD : 0;
-      for (j=0; j<incexe->name_list.size(); j++) {
-         if (fnmatch((char *)incexe->name_list.get(j), ff->fname, fnmode|fnm_flags) == 0) {
+      char *fname;
+      foreach_alist(fname, &incexe->name_list) {
+         if (fnmatch(fname, ff->fname, fnmode|fnm_flags) == 0) {
             Dmsg1(100, "Reject wild2: %s\n", ff->fname);
             return false;          /* reject file */
          }
 
+++ /dev/null
-/*
- *  Bacula red-black binary tree routines.
- *
- *    btree is a binary tree with the links being in the data item.
- *
- *   Developped in part from ideas obtained from several online University
- *    courses. 
- *
- *   Kern Sibbald, November MMV
- *
- *   Version $Id$
- *
- */
-/*
-   Bacula® - The Network Backup Solution
-
-   Copyright (C) 2005-2006 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 plus additions
-   that are listed 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 John Walker.
-   The licensor of Bacula is the Free Software Foundation Europe
-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
-   Switzerland, email:ftf@fsfeurope.org.
-*/
-
-#include "bacula.h"
-#include "btree.h"
-
-/* ===================================================================
- *    btree
- */
-
-/*
- *  Insert an item in the tree, but only if it is unique
- *   otherwise, the item is returned non inserted
- *  The big trick is keeping the tree balanced after the 
- *   insert. We use a parent pointer to make it simpler and 
- *   to avoid recursion.
- *
- * Returns: item         if item inserted
- *          other_item   if same value already exists (item not inserted)
- */
-bnode *btree::insert(bnode *item, int compare(bnode *item1, bnode *item2))
-{
-   bnode *x, *y;
-   bnode *last = NULL;        /* last leaf if not found */
-   bnode *found = NULL;
-   int comp = 0;
-
-   /* Search */
-   x = head;
-   while (x && !found) {
-      last = x;
-      comp = compare(item, x);
-      if (comp < 0) {
-         x = x->left;
-      } else if (comp > 0) {
-         x = x->right;
-      } else {
-         found = x;
-      }
-   }
-
-   if (found) {                    /* found? */
-      return found;                /* yes, return item found */
-   }
-   /* Handle empty tree */
-   if (num_items == 0) {
-      head = item;
-      num_items++;
-      return item;
-   }
-   x = last;
-   /* Not found, so insert it on appropriate side of tree */
-   if (comp < 0) {
-      last->left = item;
-   } else {
-      last->right = item;
-   }
-   last->red = true;
-   item->parent = last;
-   num_items++;
-
-   /* Now we must walk up the tree balancing it */
-   x = last;
-   while (x != head && x->parent->red) {
-      if (x->parent == x->parent->parent->left) {
-         /* Look at the right side of our grandparent */
-         y = x->parent->parent->right;
-         if (y && y->red) {
-            /* our parent must be black */
-            x->parent->red = false;
-            y->red = false;
-            x->parent->parent->red = true;
-            x = x->parent->parent;       /* move up to grandpa */
-         } else {
-            if (x == x->parent->right) { /* right side of parent? */
-               x = x->parent;
-               left_rotate(x);
-            }
-            /* make parent black too */
-            x->parent->red = false;
-            x->parent->parent->red = true;
-            right_rotate(x->parent->parent);
-         }
-      } else {
-         /* Look at left side of our grandparent */
-         y = x->parent->parent->left;
-         if (y && y->red) {
-            x->parent->red = false;
-            y->red = false;
-            x->parent->parent->red = true;
-            x = x->parent->parent;       /* move up to grandpa */
-         } else {
-            if (x == x->parent->left) {
-               x = x->parent;
-               right_rotate(x);
-            }
-            /* make parent black too */
-            x->parent->red = false;
-            x->parent->parent->red = true;
-            left_rotate(x->parent->parent);
-         }
-      }
-   }
-   /* Make sure the head is always black */
-   head->red = false;
-   return item;
-}
-
-
-/*
- * Search for item
- */
-bnode *btree::search(bnode *item, int compare(bnode *item1, bnode *item2))
-{
-   bnode *found = NULL;
-   bnode *x;
-   int comp;
-
-   x = head;
-   while (x) {
-      comp = compare(item, x);
-      if (comp < 0) {
-         x = x->left;
-      } else if (comp > 0) {
-         x = x->right;
-      } else {
-         found = x;
-         break;
-      }
-   }
-   return found;
-}
-
-/* 
- * Get first item (i.e. lowest value) 
- */
-bnode *btree::first(void)
-{
-   bnode *x;
-
-   x = head;
-   down = true;
-   while (x) {
-      if (x->left) {
-         x = x->left;
-         continue;
-      }
-      return x;
-   }
-   /* Tree is empty */
-   return NULL;
-}
-
-/*
- * This is a non-recursive btree walk routine that returns
- *  the items one at a time in order. I've never seen a
- *  non-recursive tree walk routine published that returns
- *  one item at a time rather than doing a callback.
- *
- * Return the next item in sorted order.  We assume first()
- *  was called once before calling this routine.
- *  We always go down as far as we can to the left, then up, and
- *  down one to the right, and again down as far as we can to the
- *  left.  etc. 
- *
- * Returns: pointer to next larger item 
- *          NULL when no more items in tree
- */
-bnode *btree::next(bnode *item)
-{
-   bnode *x;
-
-   x = item;
-   if ((down && !x->left && x->right) || (!down && x->right)) {
-      /* Move down to right one */
-      down = true;
-      x = x->right;                       
-      /* Then all the way down left */
-      while (x->left)  {
-         x = x->left;
-      }
-      return x;
-   }
-
-   /* We have gone down all we can, so now go up */
-   for ( ;; ) {
-      /* If at head, we are done */
-      if (!x->parent) {
-         return NULL;
-      }
-      /* Move up in tree */
-      down = false;
-      /* if coming from right, continue up */
-      if (x->parent->right == x) {
-         x = x->parent;
-         continue;
-      }
-      /* Coming from left, go up one -- ie. return parent */
-      return x->parent;
-   }
-}
-
-/*
- * Similer to next(), but visits all right nodes when
- *  coming up the tree.
- */
-bnode *btree::any(bnode *item)
-{
-   bnode *x;
-
-   x = item;
-   if ((down && !x->left && x->right) || (!down && x->right)) {
-      /* Move down to right one */
-      down = true;
-      x = x->right;                       
-      /* Then all the way down left */
-      while (x->left)  {
-         x = x->left;
-      }
-      return x;
-   }
-
-   /* We have gone down all we can, so now go up */
-   for ( ;; ) {
-      /* If at head, we are done */
-      if (!x->parent) {
-         return NULL;
-      }
-      down = false;
-      /* Go up one and return parent */
-      return x->parent;
-   }
-}
-
-
-/* x is item, y is below and to right, then rotated to below left */
-void btree::left_rotate(bnode *item)
-{
-   bnode *y;
-   bnode *x;
-
-   x = item;
-   y = x->right;
-   x->right = y->left;
-   if (y->left) {
-      y->left->parent = x;
-   }
-   y->parent = x->parent;
-   /* if no parent then we have a new head */
-   if (!x->parent) {
-      head = y;
-   } else if (x == x->parent->left) {
-      x->parent->left = y;
-   } else {
-      x->parent->right = y;
-   }
-   y->left = x;
-   x->parent = y;
-}
-
-void btree::right_rotate(bnode *item)
-{
-   bnode *x, *y;
-
-   y = item;
-   x = y->left;
-   y->left = x->right;
-   if (x->right) {
-      x->right->parent = y;
-   }
-   x->parent = y->parent;
-   /* if no parent then we have a new head */
-   if (!y->parent) {
-      head = x;
-   } else if (y == y->parent->left) {
-      y->parent->left = x;
-   } else {
-      y->parent->right = x;
-   }
-   x->right = y;
-   y->parent = x;
-}
-
-
-void btree::remove(bnode *item)
-{
-}
-
-/* Destroy the tree contents.  Not totally working */
-void btree::destroy()
-{
-   bnode *x, *y = NULL;
-
-   x = first();
-// printf("head=%p first=%p left=%p right=%p\n", head, x, x->left, x->right);
-
-   for (  ; (y=any(x)); ) {
-      /* Prune the last item */
-      if (x->parent) {
-         if (x == x->parent->left) {
-            x->parent->left = NULL;
-         } else if (x == x->parent->right) {
-            x->parent->right = NULL;
-         }
-      }
-      if (!x->left && !x->right) {
-         if (head == x) {  
-            head = NULL;
-         }
-//       if (num_items<30) {
-//          printf("free nitems=%d item=%p left=%p right=%p\n", num_items, x, x->left, x->right);
-//       }   
-         free((void *)x);      /* free previous node */
-         num_items--;
-      }
-      x = y;                  /* save last node */
-   }
-   if (x) {
-      if (x == head) {
-         head = NULL;
-      }
-//    printf("free nitems=%d item=%p left=%p right=%p\n", num_items, x, x->left, x->right);
-      free((void *)x);
-      num_items--;
-   }
-   if (head) {
-//    printf("Free head\n");
-      free((void *)head);
-   }
-// printf("free nitems=%d\n", num_items);
-
-   head = NULL;
-}
-
-
-
-#ifdef TEST_PROGRAM
-
-struct MYJCR {
-   bnode link;
-   char *buf;
-};
-
-static int my_compare(bnode *item1, bnode *item2)
-{
-   MYJCR *jcr1, *jcr2;
-   int comp;
-   jcr1 = (MYJCR *)item1;
-   jcr2 = (MYJCR *)item2;
-   comp = strcmp(jcr1->buf, jcr2->buf);
- //Dmsg3(000, "compare=%d: %s to %s\n", comp, jcr1->buf, jcr2->buf);
-   return comp;
-}
-
-int main()
-{
-   char buf[30];
-   btree *jcr_chain;
-   MYJCR *jcr = NULL;
-   MYJCR *jcr1;
-
-
-   /* Now do a binary insert for the tree */
-   jcr_chain = New(btree());
-#define CNT 26
-   printf("append %d items\n", CNT*CNT*CNT);
-   strcpy(buf, "ZZZ");
-   int count = 0;
-   for (int i=0; i<CNT; i++) {
-      for (int j=0; j<CNT; j++) {
-         for (int k=0; k<CNT; k++) {
-            count++;
-            if ((count & 0x3FF) == 0) {
-               Dmsg1(000, "At %d\n", count);
-            }
-            jcr = (MYJCR *)malloc(sizeof(MYJCR));
-            memset(jcr, 0, sizeof(MYJCR));
-            jcr->buf = bstrdup(buf);
-//          printf("buf=%p %s\n", jcr, jcr->buf);
-            jcr1 = (MYJCR *)jcr_chain->insert((bnode *)jcr, my_compare);
-            if (jcr != jcr1) {
-               Dmsg2(000, "Insert of %s vs %s failed.\n", jcr->buf, jcr1->buf);
-            }
-            buf[1]--;
-         }
-         buf[1] = 'Z';
-         buf[2]--;
-      }
-      buf[2] = 'Z';
-      buf[0]--;
-   }
-   printf("%d items appended\n", CNT*CNT*CNT);
-   printf("num_items=%d\n", jcr_chain->size());
-
-   jcr = (MYJCR *)malloc(sizeof(MYJCR));
-   memset(jcr, 0, sizeof(MYJCR));
-
-   jcr->buf = bstrdup("a");
-   if ((jcr1=(MYJCR *)jcr_chain->search((bnode *)jcr, my_compare))) {
-      printf("One less failed!!!! Got: %s\n", jcr1->buf);
-   } else {
-      printf("One less: OK\n");
-   }
-   free(jcr->buf);
-
-   jcr->buf = bstrdup("ZZZZZZZZZZZZZZZZ");
-   if ((jcr1=(MYJCR *)jcr_chain->search((bnode *)jcr, my_compare))) {
-      printf("One greater failed!!!! Got:%s\n", jcr1->buf);
-   } else {
-      printf("One greater: OK\n");
-   }
-   free(jcr->buf);
-
-   jcr->buf = bstrdup("AAA");
-   if ((jcr1=(MYJCR *)jcr_chain->search((bnode *)jcr, my_compare))) {
-      printf("Search for AAA got %s\n", jcr1->buf);
-   } else {
-      printf("Search for AAA not found\n"); 
-   }
-   free(jcr->buf);
-
-   jcr->buf = bstrdup("ZZZ");
-   if ((jcr1 = (MYJCR *)jcr_chain->search((bnode *)jcr, my_compare))) {
-      printf("Search for ZZZ got %s\n", jcr1->buf);
-   } else {
-      printf("Search for ZZZ not found\n"); 
-   }
-   free(jcr->buf);
-   free(jcr);
-
-
-   printf("Find each of %d items in tree.\n", count);
-   for (jcr=(MYJCR *)jcr_chain->first(); jcr; (jcr=(MYJCR *)jcr_chain->next((bnode *)jcr)) ) {
-//    printf("Got: %s\n", jcr->buf);
-      if (!jcr_chain->search((bnode *)jcr, my_compare)) {
-         printf("btree binary_search item not found = %s\n", jcr->buf);
-      }
-   }
-   printf("Free each of %d items in tree.\n", count);
-   for (jcr=(MYJCR *)jcr_chain->first(); jcr; (jcr=(MYJCR *)jcr_chain->next((bnode *)jcr)) ) {
-//    printf("Free: %p %s\n", jcr, jcr->buf);
-      free(jcr->buf);
-      jcr->buf = NULL;
-   }
-   printf("num_items=%d\n", jcr_chain->size());
-   delete jcr_chain;
-
-
-   sm_dump(true);
-
-}
-#endif
 
+++ /dev/null
-/*
- *   Version $Id$
- */
-/*
-   Bacula® - The Network Backup Solution
-
-   Copyright (C) 2005-2006 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 plus additions
-   that are listed 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 John Walker.
-   The licensor of Bacula is the Free Software Foundation Europe
-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
-   Switzerland, email:ftf@fsfeurope.org.
-*/
-
-
-/* ========================================================================
- *
- *   red-black binary tree routines -- btree.h
- *
- *    Kern Sibbald, MMV
- *
- */
-
-#define M_ABORT 1
-
-/*
- * There is a lot of extra casting here to work around the fact
- * that some compilers (Sun and Visual C++) do not accept
- * (bnode *) as an lvalue on the left side of an equal.
- *
- * Loop var through each member of list
- */
-#define foreach_btree(var, tree) \
-    for(*((bnode **)&(var))=(tree)->first(); (*((bnode **)&(var))=(tree)->next((bnode *)var)); )
-
-#ifdef the_old_way
-#define foreach_btree(var, tree) \
-        for((var)=(tree)->first(); (((bnode *)(var))=(tree)->next((bnode *)var)); )
-#endif
-
-struct bnode;
-struct bnode {
-   bnode *left;
-   bnode *right;
-   bnode *parent;
-   bool red;
-};
-
-class btree : public SMARTALLOC {
-   bnode *head;
-   uint32_t num_items;
-   bool down;
-   void left_rotate(bnode *item);
-   void right_rotate(bnode *item);
-public:
-   btree(void);
-   ~btree() { destroy(); }
-   void init(void);
-   bnode *insert(bnode *item, int compare(bnode *item1, bnode *item2));
-   bnode *search(bnode *item, int compare(bnode *item1, bnode *item2));
-   bnode *first(void);
-   bnode *next(bnode *item);
-   bnode *any(bnode *item);
-   void remove(bnode *item);
-   int  size() const;
-   void destroy();
-};
-
-
-/*
- * This allows us to do explicit initialization,
- *   allowing us to mix C++ classes inside malloc'ed
- *   C structures. Define before called in constructor.
- */
-inline void btree::init()
-{
-   head = NULL;
-   num_items = 0;
-}
-
-
-/* Constructor with link at head of item */
-inline btree::btree(void) : head(0), num_items(0)
-{
-}
-
-inline int btree::size() const
-{
-   return num_items;
-}
 
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2007 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.
 #include "smartall.h"
 #include "alist.h"
 #include "dlist.h"
+#include "rblist.h"
 #include "base64.h"
 #include "bits.h"
 #include "btime.h"
 
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2007 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.
 
    dev->block(BST_DOING_ACQUIRE);
 
    if (dev->num_writers > 0) {
-      Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"), 
+      Jmsg2(jcr, M_FATAL, 0, _("Acquire read: num_writers=%d not zero. Job %d canceled.\n"), 
          dev->num_writers, jcr->JobId);
       goto get_out;
    }
    vol = jcr->VolList;
    if (!vol) {
       char ed1[50];
-      Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %s canceled.\n"), 
+      Jmsg(jcr, M_FATAL, 0, _("No volumes specified for reading. Job %s canceled.\n"), 
          edit_int64(jcr->JobId, ed1));
       goto get_out;
    }
       vol = vol->next;
    }
    if (!vol) {
-      Jmsg(jcr, M_FATAL, 0, _("Logic error: no next volume. Numvol=%d Curvol=%d\n"),
+      Jmsg(jcr, M_FATAL, 0, _("Logic error: no next volume to read. Numvol=%d Curvol=%d\n"),
          jcr->NumReadVolumes, jcr->CurReadVolume);
       goto get_out;                   /* should not happen */   
    }
       break;
    } /* end for loop */
    if (!ok) {
-      Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
+      Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s for reading.\n"),
             dev->print_name());
       goto get_out;
    }
     * With the reservation system, this should not happen
     */
    if (dev->can_read()) {
-      Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
-      Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
+      Jmsg1(jcr, M_FATAL, 0, _("Want to append, but device %s is busy reading.\n"), dev->print_name());
+      Dmsg1(200, "Want to append but device %s is busy reading.\n", dev->print_name());
       goto get_out;
    }
 
             free_unused_volume(dcr);
          }
          if (dev->num_writers != 0) {
-            Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"), 
+            Jmsg3(jcr, M_FATAL, 0, _("Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n"), 
                  dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
-            Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",  
+            Dmsg3(200, "Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n",  
                  dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
             goto get_out;
          }
 
  */
 
 #undef  VERSION
-#define VERSION "2.0.2"
-#define BDATE   "28 January 2007"
-#define LSMDATE "28Jan07"
+#define VERSION "2.0.3"
+#define BDATE   "06 February 2007"
+#define LSMDATE "06Feb07"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2007"       /* year for copyright messages in progs */
 
        $(OBJDIR)/bsys.o \
        $(OBJDIR)/btime.o \
        $(OBJDIR)/btimers.o \
-       $(OBJDIR)/btree.o \
        $(OBJDIR)/cram-md5.o \
        $(OBJDIR)/crc32.o \
        $(OBJDIR)/crypto.o \
        $(OBJDIR)/openssl.o \
        $(OBJDIR)/pythonlib.o \
        $(OBJDIR)/queue.o \
+       $(OBJDIR)/rblist.o \
        $(OBJDIR)/runscript.o \
        $(OBJDIR)/rwlock.o \
        $(OBJDIR)/scan.o \
 
 _Z17stop_thread_timerP10s_btimer_t
 _Z18start_thread_timerP10pthread_t_j
 
-; btree.c:
-
 ; cram-md5.c:
 _Z16cram_md5_respondP5BSOCKPcPiS2_
 _Z18cram_md5_challengeP5BSOCKPcii
 _Z7qdchainP7b_queue
 _Z7qinsertP7b_queueS0_
 
+; rblist.c:
+_ZN6rblist4nextEPv
+_ZN6rblist5firstEv
+_ZN6rblist6insertEPvPFiS0_S0_E
+_ZN6rblist6removeEPv
+_ZN6rblist6searchEPvPFiS0_S0_E
+_ZN6rblist7destroyEv
+
 ; runscript.c:
 _Z11run_scriptsP3JCRP5alistPKc
 _Z13new_runscriptv
 
        $(OBJDIR)/bsys.o \
        $(OBJDIR)/btime.o \
        $(OBJDIR)/btimers.o \
-       $(OBJDIR)/btree.o \
        $(OBJDIR)/cram-md5.o \
        $(OBJDIR)/crc32.o \
        $(OBJDIR)/crypto.o \
        $(OBJDIR)/parse_conf.o \
        $(OBJDIR)/pythonlib.o \
        $(OBJDIR)/queue.o \
+       $(OBJDIR)/rblist.o \
        $(OBJDIR)/res.o \
        $(OBJDIR)/runscript.o \
        $(OBJDIR)/rwlock.o \
 
               Technical notes on version 2.0
 
 General:
-Version 2.0.2 released: xx January 2007
+06Feb07
+kes  Delete src/lib/btree.c from win32 build, then add rblist.c
+     plus the entrypoints.
+kes  Apply patch supplied that corrects debug print
+     in canceling jobs for max run time.  Supplied as
+     part of bug #621, which was previously fixed.
 05Feb07
-ebl  Fixes bug #766 about RunsOnClient = Yes 
+kes  Test on job_canceled() and sd_msg_thread_done inside
+     loop starting the message thread to avoid a race condition.
+     Fixes bug #771.
+kes  Remove rl_catch_signal from console.c as it conflicted
+     with the header definition. Fixes bug #765.
+ebl  Fixes bug #766 about RunsOnClient = Yes
+04Feb07
+kes  Clarify some stored/acquire messages to indicate if the
+     problem is with read or append.
+02Feb07
+kes  Fix memory leak with storage ids in cats/sql_get.c
+kes  Terminate watchdog earlier to avoid reference to released
+     memory -- reported by Jason Austin.
+kes  Move closing the database from jobq.c to the director daemon
+     termination routine. This fixes memory leaks for shadow jobs
+     (i.e. migration jobs).
+kes  Free up the unique jobid chain items in migrate.c.  This fixes
+     a memory leak problem.
+kes  Convert some ugly looking for statements to use foreach_alist
+     in findlib/find.c.  This will facilitate converting the structures
+     to use dlist (for large include/exclude lists).
+kes  Fix a bug in the btree.c and btree.h routines, then rename them
+     rblist and add them to be built in src/lib.  Include some new
+     methods written by Rudolf Cejka that make the code more readable
+     (hides some of the ugly casting).
+
+Version 2.0.2 released: 30 January 2007
 28Jan08
 kes  Fix maxruntime bug #621.
 27Jan07