]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/bscan.c
Autochanger for read + 64 bit addrs + Session key, see kes14Sep02
[bacula/bacula] / bacula / src / stored / bscan.c
index 56f83ff40b3d35ace95f977d50a7b0b5c73c52ea..2a7aaf381451b4fc2e85c7f5546ee2851a829ebb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *
- *  Program to scan a Bacula tape and compare it with
+ *  Program to scan a Bacula Volume and compare it with
  *    the catalog and optionally synchronize the catalog
  *    with the tape.
  *
 #include "findlib/find.h"
 #include "cats/cats.h"
 
+/* Forward referenced functions */
 static void do_scan(char *fname);
-
-
+static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static void create_file_attributes_record(B_DB *db, char *fname, char *lname, int type,
+                              char *ap, DEV_RECORD *rec);
+static void create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl);
+static void create_pool_record(B_DB *db, POOL_DBR *pr);
+static void create_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *label);
+static void update_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *elabel, 
+                             DEV_RECORD *rec);
+static void create_client_record(B_DB *db, CLIENT_DBR *cr);
+static void create_fileset_record(B_DB *db, FILESET_DBR *fsr);
+static void create_jobmedia_record(B_DB *db, JOBMEDIA_DBR *jmr, SESSION_LABEL *elabel);
+
+
+/* Global variables */
 static DEVICE *dev = NULL;
 static B_DB *db;
 static JCR *jcr;
 static BSR *bsr;
+static struct stat statp;
+static int type;
+static long record_file_index;
+static POOLMEM *fname;                      /* original file name */
+static POOLMEM *ofile;                      /* output name with prefix */
+static POOLMEM *lname;                      /* link name */
+static MEDIA_DBR mr;
+static POOL_DBR pr;
+static JOB_DBR jr;
+static CLIENT_DBR cr;
+static JOBMEDIA_DBR jmr;
+static FILESET_DBR fsr;
+static ATTR_DBR ar;
+static SESSION_LABEL label;
+static SESSION_LABEL elabel;
+static uint32_t FirstIndex = 0;
+static uint32_t LastIndex = 0;
+
+static char *db_name = "bacula";
+static char *db_user = "bacula";
+static char *db_password = "";
+static char *wd = "/tmp";
+static int verbose = 0;
+static int update_db = 0;
 
 static void usage()
 {
    fprintf(stderr,
 "\nVersion: " VERSION " (" DATE ")\n\n"
 "Usage: bscan [-d debug_level] <bacula-archive>\n"
-"       -dnn            set debug level to nn\n"
-"       -?              print this message\n\n");
+"       -b bootstrap      specify a bootstrap file\n"
+"       -dnn              set debug level to nn\n"
+"       -n name           specify the database name (default bacula)\n"
+"       -u user           specify database user name (default bacula)\n"
+"       -p password       specify database password (default none)\n"
+"       -s                synchronize or store in database\n"
+"       -v                verbose\n"
+"       -w dir            specify working directory (default /tmp)\n"
+"       -?                print this message\n\n");
    exit(1);
 }
 
@@ -60,7 +104,7 @@ int main (int argc, char *argv[])
    init_msg(NULL, NULL);
 
 
-   while ((ch = getopt(argc, argv, "b:d:?")) != -1) {
+   while ((ch = getopt(argc, argv, "b:d:n:p:u:vw:?")) != -1) {
       switch (ch) {
          case 'b':
            bsr = parse_bsr(NULL, optarg);
@@ -71,6 +115,30 @@ int main (int argc, char *argv[])
               debug_level = 1; 
            break;
 
+         case 'n':
+           db_name = optarg;
+           break;
+
+         case 'u':
+           db_user = optarg;
+           break;
+
+         case 'p':
+           db_password = optarg;
+           break;
+
+         case 's':
+           update_db = 1;
+           break;
+
+         case 'v':
+           verbose++;
+           break;
+
+         case 'w':
+           wd = optarg;
+           break;
+
          case '?':
         default:
            usage();
@@ -85,10 +153,11 @@ int main (int argc, char *argv[])
       usage();
    }
 
+   working_directory = wd;
+
    jcr = setup_jcr("bscan", argv[0], bsr);
 
-   /* *** FIXME **** need to put in corect db, user, and password */
-   if ((db=db_init_database(NULL, "bacula", "bacula", "")) == NULL) {
+   if ((db=db_init_database(NULL, db_name, db_user, db_password)) == NULL) {
       Emsg0(M_ABORT, 0, "Could not init Bacula database\n");
    }
    if (!db_open_database(db)) {
@@ -106,17 +175,6 @@ int main (int argc, char *argv[])
 
 static void do_scan(char *devname)            
 {
-   struct stat statp;
-   int type;
-   long record_file_index;
-   DEV_RECORD *rec;
-   DEV_BLOCK *block;
-   POOLMEM *fname;                      /* original file name */
-   POOLMEM *ofile;                      /* output name with prefix */
-   POOLMEM *lname;                      /* link name */
-   MEDIA_DBR mr;
-   POOL_DBR pr;
-   JOB_DBR jr;
 
    dev = setup_to_read_device(jcr);
    if (!dev) { 
@@ -127,240 +185,378 @@ static void do_scan(char *devname)
    ofile = get_pool_memory(PM_FNAME);
    lname = get_pool_memory(PM_FNAME);
 
-   block = new_block(dev);
-   
-   rec = new_record();
-   free_pool_memory(rec->data);
-   rec->data = get_memory(70000);
-
+   memset(&ar, 0, sizeof(ar));
    memset(&mr, 0, sizeof(mr));
    memset(&pr, 0, sizeof(pr));
+   memset(&jr, 0, sizeof(jr));
+   memset(&cr, 0, sizeof(cr));
+   memset(&jmr, 0, sizeof(jmr));
+   memset(&fsr, 0, sizeof(fsr));
 
-   for ( ;; ) {
-      if (!read_block_from_device(dev, block)) {
-        uint32_t status;
-        if (dev->state & ST_EOT) {
-           if (!mount_next_read_volume(jcr, dev, block)) {
-              break;
-           }
-           continue;
-        }
-        if (dev->state & ST_EOF) {
-           continue;                 /* try again */
-        }
-        if (dev->state & ST_SHORT) {
-           continue;
-        }
-         Pmsg0(0, "Read Record got a bad record\n");
-        status_dev(dev, &status);
-         Dmsg1(20, "Device status: %x\n", status);
-        if (status & MT_EOD)
-            Emsg0(M_ABORT, 0, "Unexpected End of Data\n");
-        else if (status & MT_EOT)
-            Emsg0(M_ABORT, 0, "Unexpected End of Tape\n");
-        else if (status & MT_EOF)
-            Emsg0(M_ABORT, 0, "Unexpected End of File\n");
-        else if (status & MT_DR_OPEN)
-            Emsg0(M_ABORT, 0, "Tape Door is Open\n");
-        else if (!(status & MT_ONLINE))
-            Emsg0(M_ABORT, 0, "Unexpected Tape is Off-line\n");
-        else
-            Emsg3(M_ABORT, 0, "Read error %d on Record Header %s: %s\n", 
-              status, dev_name(dev), strerror(errno));
-      }
-
-      for (rec->state=0; !is_block_empty(rec); ) {
-           SESSION_LABEL label, elabel;
-        if (!read_record_from_block(block, rec)) {
-           break;
-        }
-
+   read_records(jcr, dev, record_cb, mount_next_read_volume);
+   release_device(jcr, dev);
 
-        /* This is no longer used */
-        if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
-            Emsg0(M_ERROR, 0, "Zero header record. This shouldn't happen.\n");
-           break;                       /* END OF FILE */
-        }
+   free_pool_memory(fname);
+   free_pool_memory(ofile);
+   free_pool_memory(lname);
+   term_dev(dev);
+}
 
-        /* 
-         * Check for Start or End of Session Record 
-         *
-         */
-        if (rec->FileIndex < 0) {
+static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+{
+   /* 
+    * Check for Start or End of Session Record 
+    *
+    */
+   if (rec->FileIndex < 0) {
+
+      if (verbose > 1) {
+        dump_label_record(dev, rec, 1);
+      }
+      switch (rec->FileIndex) {
+        case PRE_LABEL:
+            Pmsg0(000, "Volume is prelabeled. This tape cannot be scanned.\n");
+           return;
+           break;
+        case VOL_LABEL:
+           unser_volume_label(dev, rec);
+           /* Check Pool info */
+           strcpy(pr.Name, dev->VolHdr.PoolName);
+           strcpy(pr.PoolType, dev->VolHdr.PoolType);
+           if (!db_get_pool_record(db, &pr)) {
+               Pmsg1(000, "VOL_LABEL: Pool record not found for Pool: %s\n",
+                 pr.Name);
+              create_pool_record(db, &pr);
+              return;
+           } else if (verbose) {
+               Pmsg1(000, "Pool record for %s found in DB.\n", pr.Name);
+           }
+           if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) {
+               Pmsg2(000, "VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n",
+                 pr.PoolType, dev->VolHdr.PoolType);
+              return;
+           } else if (verbose) {
+               Pmsg1(000, "Pool type \"%s\" is OK.\n", pr.PoolType);
+           }
 
-           if (debug_level > 1) {
-              dump_label_record(dev, rec, 1);
+           /* Check Media Info */
+           strcpy(mr.VolumeName, dev->VolHdr.VolName);
+           mr.PoolId = pr.PoolId;
+           if (!db_get_media_record(db, &mr)) {
+               Pmsg1(000, "VOL_LABEL: Media record not found for Volume: %s\n",
+                 mr.VolumeName);
+              strcpy(mr.MediaType, dev->VolHdr.MediaType);
+              create_media_record(db, &mr, &dev->VolHdr);
+              return;
+           } else if (verbose) {
+               Pmsg1(000, "Media record for %s found in DB.\n", mr.VolumeName);
            }
-           switch (rec->FileIndex) {
-              case PRE_LABEL:
-                  Pmsg0(000, "Volume is prelabeled. This tape cannot be scanned.\n");
-                 return;
-                 break;
-              case VOL_LABEL:
-                 unser_volume_label(dev, rec);
-                 strcpy(mr.VolumeName, dev->VolHdr.VolName);
-                 if (!db_get_media_record(db, &mr)) {
-                     Pmsg1(000, "VOL_LABEL: Media record not found for Volume: %s\n",
-                       mr.VolumeName);
-                    continue;
-                 }
-                 if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
-                     Pmsg2(000, "VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n",
-                       mr.MediaType, dev->VolHdr.MediaType);
-                    continue;
-                 }
-                 strcpy(pr.Name, dev->VolHdr.PoolName);
-                 if (!db_get_pool_record(db, &pr)) {
-                     Pmsg1(000, "VOL_LABEL: Pool record not found for Pool: %s\n",
-                       pr.Name);
-                    continue;
-                 }
-                 if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) {
-                     Pmsg2(000, "VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n",
-                       pr.PoolType, dev->VolHdr.PoolType);
-                    continue;
-                 }
-                  Pmsg1(000, "VOL_LABEL: OK for Volume: %s\n", mr.VolumeName);
-                 break;
-              case SOS_LABEL:
-                 unser_session_label(&label, rec);
-                 memset(&jr, 0, sizeof(jr));
-                 jr.JobId = label.JobId;
-                 if (!db_get_job_record(db, &jr)) {
-                     Pmsg1(000, "SOS_LABEL: Job record not found for JobId: %d\n",
-                       jr.JobId);
-                    continue;
-                 }
-                 if (rec->VolSessionId != jr.VolSessionId) {
-                     Pmsg2(000, "SOS_LABEL: VolSessId mismatch. DB=%d Vol=%d\n",
-                       jr.VolSessionId, rec->VolSessionId);
-                    continue;
-                 }
-                 if (rec->VolSessionTime != jr.VolSessionTime) {
-                     Pmsg2(000, "SOS_LABEL: VolSessTime mismatch. DB=%d Vol=%d\n",
-                       jr.VolSessionTime, rec->VolSessionTime);
-                    continue;
-                 }
-                 if (jr.PoolId != pr.PoolId) {
-                     Pmsg2(000, "SOS_LABEL: PoolId mismatch. DB=%d Vol=%d\n",
-                       jr.PoolId, pr.PoolId);
-                    continue;
-                 }
-                 break;
-              case EOS_LABEL:
-                 unser_session_label(&elabel, rec);
-                 if (elabel.JobId != label.JobId) {
-                     Pmsg2(000, "EOS_LABEL: Start/End JobId mismatch. Start=%d End=%d\n",
-                       label.JobId, elabel.JobId);
-                    continue;
-                 }
-                 if (elabel.JobFiles != jr.JobFiles) {
-                     Pmsg2(000, "EOS_LABEL: JobFiles mismatch. DB=%d EOS=%d\n",
-                       jr.JobFiles, elabel.JobFiles);
-                    continue;
-                 }                                 
-                 if (elabel.JobBytes != jr.JobBytes) {
-                     Pmsg2(000, "EOS_LABEL: JobBytes mismatch. DB=%d EOS=%d\n",
-                       jr.JobBytes, elabel.JobBytes);
-                    continue;
-                 }                                 
-                  Pmsg1(000, "EOS_LABEL: OK for JobId=%d\n", elabel.JobId);
-                 break;
-              case EOM_LABEL:
-                 break;
-              default:
-                 break;
+           if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
+               Pmsg2(000, "VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n",
+                 mr.MediaType, dev->VolHdr.MediaType);
+              return;
+           } else if (verbose) {
+               Pmsg1(000, "Media type \"%s\" is OK.\n", mr.MediaType);
            }
-           continue;
-        }
-
-        /* Is this the file we want? */
-        if (bsr && !match_bsr(bsr, rec, &dev->VolHdr, &label)) {
-           rec->remainder = 0;
-           continue;
-        }
-        if (is_partial_record(rec)) {
+            Pmsg1(000, "VOL_LABEL: OK for Volume: %s\n", mr.VolumeName);
            break;
-        }
-
-        /* File Attributes stream */
-        if (rec->Stream == STREAM_UNIX_ATTRIBUTES) {
-           char *ap, *lp, *fp;
-
-           if (sizeof_pool_memory(fname) < rec->data_len) {
-              fname = realloc_pool_memory(fname, rec->data_len + 1);
+        case SOS_LABEL:
+           unser_session_label(&label, rec);
+           FirstIndex = LastIndex = 0;
+           memset(&jr, 0, sizeof(jr));
+           jr.JobId = label.JobId;
+           if (!db_get_job_record(db, &jr)) {
+               Pmsg1(000, "SOS_LABEL: Job record not found for JobId: %d\n",
+                 jr.JobId);
+              create_job_record(db, &jr, &label);
+              jr.PoolId = pr.PoolId;
+              jr.VolSessionId = rec->VolSessionId;
+              jr.VolSessionTime = rec->VolSessionTime;
+              return;
            }
-           if (sizeof_pool_memory(lname) < rec->data_len) {
-              lname = realloc_pool_memory(lname, rec->data_len + 1);
+           if (rec->VolSessionId != jr.VolSessionId) {
+               Pmsg3(000, "SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n",
+                 jr.JobId,
+                 jr.VolSessionId, rec->VolSessionId);
+              return;
            }
-           *fname = 0;
-           *lname = 0;
-
-           /*              
-            * An Attributes record consists of:
-            *    File_index
-            *    Type   (FT_types)
-            *    Filename
-            *    Attributes
-            *    Link name (if file linked i.e. FT_LNK)
-            *
-            */
-            sscanf(rec->data, "%ld %d", &record_file_index, &type);
-           if (record_file_index != rec->FileIndex)
-               Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
-                 rec->FileIndex, record_file_index);
-           ap = rec->data;
-            while (*ap++ != ' ')         /* skip record file index */
-              ;
-            while (*ap++ != ' ')         /* skip type */
-              ;
-           /* Save filename and position to attributes */
-           fp = fname;
-           while (*ap != 0) {
-              *fp++  = *ap++;
+           if (rec->VolSessionTime != jr.VolSessionTime) {
+               Pmsg3(000, "SOS_LABEL: VolSessTime mismatch for JobId=%u. DB=%d Vol=%d\n",
+                 jr.JobId,
+                 jr.VolSessionTime, rec->VolSessionTime);
+              return;
            }
-           *fp = *ap++;                 /* terminate filename & point to attribs */
-
-           /* Skip through attributes to link name */
-           if (type == FT_LNK) {
-              lp = ap;
-              while (*lp++ != 0) {
-                 ;
-              }
-               strcat(lname, lp);        /* "save" link name */
-           } else {
-              *lname = 0;
+           if (jr.PoolId != pr.PoolId) {
+               Pmsg3(000, "SOS_LABEL: PoolId mismatch for JobId=%u. DB=%d Vol=%d\n",
+                 jr.JobId,
+                 jr.PoolId, pr.PoolId);
+              return;
            }
+           break;
+        case EOS_LABEL:
+           unser_session_label(&elabel, rec);
+
+           /* Create Client record */
+           strcpy(cr.Name, label.ClientName);
+           create_client_record(db, &cr);
+           jr.ClientId = cr.ClientId;
+
+           /* Create FileSet record */
+           strcpy(fsr.FileSet, label.FileSetName);
+           create_fileset_record(db, &fsr);
+           jr.FileSetId = fsr.FileSetId;
+
+           /* Update Job record */
+           update_job_record(db, &jr, &elabel, rec);
+
+           /* Create JobMedia record */
+           jmr.JobId = jr.JobId;
+           jmr.MediaId = mr.MediaId;
+           create_jobmedia_record(db, &jmr, &elabel);
+           if (elabel.JobId != label.JobId) {
+               Pmsg2(000, "EOS_LABEL: Start/End JobId mismatch. Start=%d End=%d\n",
+                 label.JobId, elabel.JobId);
+              return;
+           }
+           if (elabel.JobFiles != jr.JobFiles) {
+               Pmsg3(000, "EOS_LABEL: JobFiles mismatch for JobId=%u. DB=%d EOS=%d\n",
+                 elabel.JobId,
+                 jr.JobFiles, elabel.JobFiles);
+              return;
+           }                                 
+           if (elabel.JobBytes != jr.JobBytes) {
+               Pmsg3(000, "EOS_LABEL: JobBytes mismatch for JobId=%u. DB=%d EOS=%d\n",
+                 elabel.JobId,
+                 jr.JobBytes, elabel.JobBytes);
+              return;
+           }                                 
+            Pmsg1(000, "EOS_LABEL: OK for JobId=%d\n", elabel.JobId);
+           break;
+        case EOM_LABEL:
+           break;
+        default:
+           break;
+      }
+      return;
+   }
 
-           decode_stat(ap, &statp);
 
-           if (debug_level > 1) {
-              print_ls_output(fname, lname, type, &statp);   
-           }
+   /* File Attributes stream */
+   if (rec->Stream == STREAM_UNIX_ATTRIBUTES) {
+      char *ap, *lp, *fp;
 
-        /* Data stream and extracting */
-        } else if (rec->Stream == STREAM_FILE_DATA) {
+      if (sizeof_pool_memory(fname) < rec->data_len) {
+        fname = realloc_pool_memory(fname, rec->data_len + 1);
+      }
+      if (sizeof_pool_memory(lname) < rec->data_len) {
+        lname = realloc_pool_memory(lname, rec->data_len + 1);
+      }
+      *fname = 0;
+      *lname = 0;
+
+      /*             
+       * An Attributes record consists of:
+       *    File_index
+       *    Type   (FT_types)
+       *    Filename
+       *    Attributes
+       *    Link name (if file linked i.e. FT_LNK)
+       *
+       */
+      sscanf(rec->data, "%ld %d", &record_file_index, &type);
+      if (record_file_index != rec->FileIndex)
+         Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
+           rec->FileIndex, record_file_index);
+      ap = rec->data;
+      while (*ap++ != ' ')         /* skip record file index */
+        ;
+      while (*ap++ != ' ')         /* skip type */
+        ;
+      /* Save filename and position to attributes */
+      fp = fname;
+      while (*ap != 0) {
+        *fp++  = *ap++;
+      }
+      *fp = *ap++;                /* terminate filename & point to attribs */
 
-        } else if (rec->Stream != STREAM_MD5_SIGNATURE) {
-            Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data);
-        }
+      /* Skip through attributes to link name */
+      lp = ap;
+      while (*lp++ != 0) {
+        ;
       }
-   }
+      strcat(lname, lp);        /* "save" link name */
 
-   release_device(jcr, dev);
 
-   free_pool_memory(fname);
-   free_pool_memory(ofile);
-   free_pool_memory(lname);
-   term_dev(dev);
-   free_block(block);
-   free_record(rec);
+      if (verbose > 1) {
+        decode_stat(ap, &statp);
+        print_ls_output(fname, lname, type, &statp);   
+      }
+      create_file_attributes_record(db, fname, lname, type, ap, rec);
+      if (FirstIndex == 0) {
+        FirstIndex = rec->FileIndex;
+      }
+      LastIndex = rec->FileIndex;
+
+   /* Data stream and extracting */
+   } else if (rec->Stream == STREAM_FILE_DATA) {
+
+   } else if (rec->Stream != STREAM_MD5_SIGNATURE) {
+      Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data);
+   }
+   
    return;
 }
 
+static void create_file_attributes_record(B_DB *db, char *fname, char *lname, int type,
+                              char *ap, DEV_RECORD *rec)
+{
+   if (!update_db) {
+      return;
+   }
+   ar.fname = fname;
+   ar.link = lname;
+   ar.ClientId = cr.ClientId;
+   ar.JobId = jr.JobId;
+   ar.Stream = rec->Stream;
+   ar.FileIndex = rec->FileIndex;
+   ar.attr = ap;
+   if (!db_create_file_attributes_record(db, &ar)) {
+      Pmsg1(0, _("Could not create File Attributes record. ERR=%s\n"), db_strerror(db));
+   }
+
+}
+
+static void create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl)
+{
+   struct date_time dt;
+   struct tm tm;
+   if (!update_db) {
+      return;
+   }
+   strcpy(mr->VolStatus, "Full");
+   mr->VolRetention = 355 * 3600 * 24; /* 1 year */
+   dt.julian_day_number = vl->write_date;
+   dt.julian_day_fraction = vl->write_time;
+   tm_decode(&dt, &tm);
+   mr->FirstWritten = mktime(&tm);
+   dt.julian_day_number = vl->label_date;
+   dt.julian_day_fraction = vl->label_time;
+   tm_decode(&dt, &tm);
+   mr->LabelDate = mktime(&tm);
+   if (!db_create_media_record(db, mr)) {
+      Pmsg1(0, _("Could not create media record. ERR=%s\n"), db_strerror(db));
+   }
+   if (!db_update_media_record(db, mr)) {
+      Pmsg1(0, _("Could not update media record. ERR=%s\n"), db_strerror(db));
+   }
+
+}
+
+static void create_pool_record(B_DB *db, POOL_DBR *pr)
+{
+   if (!update_db) {
+      return;
+   }
+   pr->NumVols++;
+   pr->UseCatalog = 1;
+   pr->VolRetention = 355 * 3600 * 24; /* 1 year */
+   if (!db_create_pool_record(db, pr)) {
+      Pmsg1(0, _("Could not create pool record. ERR=%s\n"), db_strerror(db));
+   }
+
+}
+
+
+static void create_client_record(B_DB *db, CLIENT_DBR *cr)
+{
+   if (!update_db) {
+      return;
+   }
+   if (!db_create_client_record(db, cr)) {
+      Pmsg1(0, _("Could not create Client record. ERR=%s\n"), db_strerror(db));
+   }
+}
+
+static void create_fileset_record(B_DB *db, FILESET_DBR *fsr)
+{
+   if (!update_db) {
+      return;
+   }
+   if (!db_create_fileset_record(db, fsr)) {
+      Pmsg1(0, _("Could not create FileSet record. ERR=%s\n"), db_strerror(db));
+   }
+}
+
+static void create_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *label)
+{
+   struct date_time dt;
+   struct tm tm;
+
+   if (!update_db) {
+      return;
+   }
+   jr->JobId = label->JobId;
+   jr->Type = label->JobType;
+   jr->Level = label->JobLevel;
+   strcpy(jr->Name, label->JobName);
+   strcpy(jr->Job, label->Job);
+   dt.julian_day_number = label->write_date;
+   dt.julian_day_fraction = label->write_time;
+   tm_decode(&dt, &tm);
+   jr->SchedTime = mktime(&tm);
+   jr->StartTime = jr->SchedTime;
+   jr->JobTDate = (btime_t)jr->SchedTime;
+   if (!db_create_job_record(db, jr)) {
+      Pmsg1(0, _("Could not create job record. ERR=%s\n"), db_strerror(db));
+   }
+
+}
+
+static void update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel,
+                             DEV_RECORD *rec)
+{
+   struct date_time dt;
+   struct tm tm;
+
+   if (!update_db) {
+      return;
+   }
+   dt.julian_day_number = elabel->write_date;
+   dt.julian_day_fraction = elabel->write_time;
+   tm_decode(&dt, &tm);
+   jr->JobStatus = JS_Terminated;
+   jr->EndTime = mktime(&tm);
+   jr->JobFiles = elabel->JobFiles;
+   jr->JobBytes = elabel->JobBytes;
+   jr->VolSessionId = rec->VolSessionId;
+   jr->VolSessionTime = rec->VolSessionTime;
+   if (!db_create_job_record(db, jr)) {
+      Pmsg1(0, _("Could not create job record. ERR=%s\n"), db_strerror(db));
+   }
+
+}
+
+static void create_jobmedia_record(B_DB *db, JOBMEDIA_DBR *jmr, SESSION_LABEL *elabel)
+{
+   if (!update_db) {
+      return;
+   }
+   jmr->FirstIndex = FirstIndex;
+   jmr->LastIndex = LastIndex;
+   jmr->StartFile = elabel->start_file;
+   jmr->EndFile = elabel->end_file;
+   jmr->StartBlock = elabel->start_block;
+   jmr->EndBlock = elabel->end_block;
+   if (!db_create_jobmedia_record(db, jmr)) {
+      Pmsg1(0, _("Could not create JobMedia record. ERR=%s\n"), db_strerror(db));
+   }
+
+}
+
 
 /* Dummies to replace askdir.c */
-int    dir_get_volume_info(JCR *jcr) { return 1;}
+int    dir_get_volume_info(JCR *jcr, int writing) { return 1;}
 int    dir_find_next_appendable_volume(JCR *jcr) { return 1;}
 int    dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
 int    dir_create_jobmedia_record(JCR *jcr) { return 1; }