]> git.sur5r.net Git - bacula/bacula/commitdiff
Vacation updates -- see kes06Oct02
authorKern Sibbald <kern@sibbald.com>
Sun, 6 Oct 2002 10:20:03 +0000 (10:20 +0000)
committerKern Sibbald <kern@sibbald.com>
Sun, 6 Oct 2002 10:20:03 +0000 (10:20 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@164 91ce42f0-d328-0410-95d8-f526ca767f89

27 files changed:
bacula/README
bacula/kernstodo
bacula/src/baconfig.h
bacula/src/cats/drop_bacula_tables.in
bacula/src/cats/make_bacula_tables.in
bacula/src/cats/sql_get.c
bacula/src/jcr.h
bacula/src/lib/btime.c
bacula/src/lib/btime.h
bacula/src/lib/message.c
bacula/src/lib/serial.c
bacula/src/lib/serial.h
bacula/src/lib/util.c
bacula/src/stored/append.c
bacula/src/stored/askdir.c
bacula/src/stored/block.c
bacula/src/stored/block.h
bacula/src/stored/bls.c
bacula/src/stored/bscan.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/label.c
bacula/src/stored/read_record.c
bacula/src/stored/record.c
bacula/src/stored/record.h
bacula/src/version.h

index d028fe86f65cdff32bf8358d58c129a44bda0c2e..5c5d9b113cc32dacd6ca6e8734ef9f79c61742b2 100644 (file)
@@ -15,7 +15,8 @@ the manual, which can be found in
 Barring reading the manual, you might try the
 following:
 
-CFLAGS="-g -Wall" \
+To Configure it:
+
   ./configure \
     --sbindir=$HOME/bacula/bin \
     --sysconfdir=$HOME/bacula/bin \
@@ -26,11 +27,10 @@ CFLAGS="-g -Wall" \
     --with-working-dir=$HOME/bacula/bin/working \
     --with-dump-email=YOUR_EMAIL_ADDRESS \
     --with-job-email=YOUR_EMAIL_ADDRESS \
-    --with-smtp-host=YOUR_SMTP_SERVER_ADDRESS \
-    --with-baseport=9101
+    --with-smtp-host=YOUR_SMTP_SERVER_ADDRESS
 
 
-Build Bacula
+Build Bacula:
 
    make
 
@@ -39,3 +39,19 @@ Build Bacula
    directory in time.c or dev.c.  There may also be problems in
    lib/signal.c as I currently pull in all Linux signals, some of
    which may not be available on your system.
+
+To creat the database:
+
+   src/make_bacula_tables
+
+To start it:
+
+   ./startit
+   ./console (or ./gnome-console)
+
+To stop it:
+
+  ./stopit
+
+Well, it is all just a bit more complicated than that,
+but you should have the idea.
index fb7a6ed653a7088d17c14a3ef2e65f439522fd61..b1cdb068c462dc5382dcd35cd46c7770ade426a3 100644 (file)
@@ -27,6 +27,7 @@ From Chuck:
   I tried this and it didn't find sqlite.h
 =======
 
+- Check if GZIP1 is working -- check speed.
 - Put MaximumVolumeSize in Director.
 - Document how to cancel a job that is waiting on a Volume. 
   Must "cancel" then "mount".
@@ -609,4 +610,3 @@ Done: (see kernsdone for more)
      
   Another try with tape mounted and Job hung in Director.
 - Write updated bootstrap after every Job.
-
index d7d61ed4c179abd3ab38b5daa01a69e6683131f1..a76333b92feb3771ca74d753ded06a398cd11430 100644 (file)
@@ -240,6 +240,7 @@ extern void _v(char *file, int line, pthread_mutex_t *m);
 #define Pmsg11(lvl,msg,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) d_msg(__FILE__,__LINE__,lvl,msg,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
 #define Pmsg12(lvl,msg,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) d_msg(__FILE__,__LINE__,lvl,msg,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
 #define Pmsg13(lvl,msg,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13) d_msg(__FILE__,__LINE__,lvl,msg,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)
+#define Pmsg14(lvl,msg,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14) d_msg(__FILE__,__LINE__,lvl,msg,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)
 
        
 /* Daemon Error Messages that are delivered according to the message resource */
index 658d290940ce1706ca350b6498f167bc67b23732..ebfb0be8a16d7473bd6f7031e3b285f5aef5cf07 100755 (executable)
@@ -5,6 +5,8 @@
 #
 if test xsqlite = x@DB_NAME@ ; then
   source ./drop_sqlite_tables
+  echo "Dropped SQLite tables"
 else
   source ./drop_mysql_tables
+  echo "Dropped MySQL tables"
 fi
index 726c8ff58a972e9e68d81d8153b5c9944bc731fb..b4f5d19ad6abef1d9edee83e41f5d5acc43651a1 100755 (executable)
@@ -4,7 +4,9 @@
 #  Bacula tables for either MySQL or SQLite
 #
 if test xsqlite = x@DB_NAME@ ; then
+  echo "Making SQLite tables"
   source ./make_sqlite_tables
 else
+  echo "Making MySQL tables"
   source ./make_mysql_tables
 fi
index af4690131ff868e9c4ff1181ad5928bf1f204e1b..66e63aea3a7b2671adc3e58862f3b4df70c99388 100644 (file)
@@ -314,11 +314,13 @@ int db_get_job_record(B_DB *mdb, JOB_DBR *jr)
    db_lock(mdb);
    if (jr->JobId == 0) {
       Mmsg(&mdb->cmd, "SELECT VolSessionId,VolSessionTime,\
-PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus \
+PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,\
+Type,Level \
 FROM Job WHERE Job='%s'", jr->Job);
     } else {
       Mmsg(&mdb->cmd, "SELECT VolSessionId,VolSessionTime,\
-PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus \
+PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,\
+Type,Level \
 FROM Job WHERE JobId=%u", jr->JobId);
     }
 
@@ -343,6 +345,8 @@ FROM Job WHERE JobId=%u", jr->JobId);
    jr->JobTDate = (btime_t)strtod(row[7], NULL);
    strcpy(jr->Job, row[8]);
    jr->JobStatus = (int)*row[9];
+   jr->Type = (int)*row[10];
+   jr->Level = (int)*row[11];
    sql_free_result(mdb);
 
    db_unlock(mdb);
index dc4d775ba1a5d9c685c381b98c359b1684f6808f..fd5c4723633fea6dc1f46c108a962ace76f3d01a 100644 (file)
@@ -192,10 +192,11 @@ struct s_jcr {
    long Ticket;                       /* ticket for this job */
    uint32_t VolFirstFile;             /* First file index this Volume */
    uint32_t FileIndex;                /* Current File Index */
-   uint32_t start_block;              /* Start write block */
-   uint32_t start_file;               /* Start write file */
-   uint32_t end_block;                /* Ending block written */
-   uint32_t end_file;                 /* End file written */
+   uint32_t EndFile;                  /* End file written */
+   uint32_t StartFile;                /* Start write file */
+   uint32_t StartBlock;               /* Start write block */
+   uint32_t EndBlock;                 /* Ending block written */
+   uint32_t FileId;                   /* Last file id inserted */
 
    /* Parmaters for Open Read Session */
    BSR *bsr;                          /* Bootstrap record -- has everything */
index dbd7cd8e1a7401d3c01b9614d0d4722d99d54806..3ad074a8b1dfd915b25620544fe1a0af18eb334c 100644 (file)
@@ -55,6 +55,11 @@ void get_current_time(struct date_time *dt)
 #endif
 }
 
+btime_t get_current_btime()
+{
+   return (btime_t)time(NULL);
+}
+
 
 /*  date_encode  --  Encode civil date as a Julian day number. */
 
index 3a324d1881ee4015fd984a1bd0467b8778b419c1..ced7cae2cc6bcdbae4376074277852f9d82d8446 100644 (file)
@@ -83,4 +83,6 @@ extern void tm_encode(struct date_time *dt, struct tm *tm);
 extern void tm_decode(struct date_time *dt, struct tm *tm);
 extern void get_current_time(struct date_time *dt);
 
+extern btime_t get_current_btime(void);
+
 #endif /* __btime_INCLUDED */
index 911a7a2e472859dac363554f9d62819cb27c5058..1f746a32d79992fc016a78f8d3ba8c1bcbbc52d3 100755 (executable)
@@ -739,7 +739,7 @@ void dispatch_message(void *vjcr, int type, int level, char *msg)
 void 
 d_msg(char *file, int line, int level, char *fmt,...)
 {
-    char      buf[MAXSTRING];
+    char      buf[2000];
     int       i;
     va_list   arg_ptr;
     int       details = TRUE;
index 1b2b0219377b6345c4fa300c1bc4124bf3619554..b11e5a50a3ec28aa9622adfccd0cc477e079d40a 100644 (file)
@@ -120,6 +120,27 @@ void serial_uint64(uint8_t * * const ptr, const uint64_t v)
 }
 
 
+/*  serial_btime  --  Serialise an btime_t 64 bit integer.  */
+
+void serial_btime(uint8_t * * const ptr, const btime_t v)
+{
+    if (htonl(1) == 1L) {
+       memcpy(*ptr, &v, sizeof(btime_t));
+    } else {
+       int i;
+       uint8_t rv[sizeof(btime_t)];
+       uint8_t *pv = (uint8_t *) &v;
+
+       for (i = 0; i < 8; i++) {
+           rv[i] = pv[7 - i];
+       }
+       memcpy(*ptr, &rv, sizeof(btime_t));
+    }
+    *ptr += sizeof(btime_t);
+}
+
+
+
 /*  serial_float64  -- Serialise a 64 bit IEEE floating point number.
                        This code assumes that the host floating point
                        format is IEEE and that floating point quantities
@@ -196,53 +217,54 @@ uint32_t unserial_uint32(uint8_t * * const ptr)
     return ntohl(vo);
 }
 
-/*  unserial_int64  -- Unserialise a signed 64 bit integer.  */
+/*  unserial_uint64  --  Unserialise an unsigned 64 bit integer.  */
 
-int64_t unserial_int64(uint8_t * * const ptr)
+uint64_t unserial_uint64(uint8_t * * const ptr)
 {
-    int64_t v;
+    uint64_t v;
 
     if (htonl(1) == 1L) {
-       memcpy(&v, *ptr, sizeof(int64_t));
+       memcpy(&v, *ptr, sizeof(uint64_t));
     } else {
        int i;
-       uint8_t rv[sizeof(int64_t)];
+       uint8_t rv[sizeof(uint64_t)];
        uint8_t *pv = (uint8_t *) &v;
 
-       memcpy(&v, *ptr, sizeof(int64_t));
+       memcpy(&v, *ptr, sizeof(uint64_t));
        for (i = 0; i < 8; i++) {
            rv[i] = pv[7 - i];
        }
-       memcpy(&v, &rv, sizeof(int64_t));
+       memcpy(&v, &rv, sizeof(uint64_t));
     }
-    *ptr += sizeof(int64_t);
+    *ptr += sizeof(uint64_t);
     return v;
 }
 
-/*  unserial_uint64  --  Unserialise an unsigned 64 bit integer.  */
+/*  unserial_btime  -- Unserialise a btime_t 64 bit integer.  */
 
-uint64_t unserial_uint64(uint8_t * * const ptr)
+uint64_t unserial_btime(uint8_t * * const ptr)
 {
-    uint64_t v;
+    btime_t v;
 
     if (htonl(1) == 1L) {
-       memcpy(&v, *ptr, sizeof(uint64_t));
+       memcpy(&v, *ptr, sizeof(btime_t));
     } else {
        int i;
-       uint8_t rv[sizeof(uint64_t)];
+       uint8_t rv[sizeof(btime_t)];
        uint8_t *pv = (uint8_t *) &v;
 
-       memcpy(&v, *ptr, sizeof(uint64_t));
+       memcpy(&v, *ptr, sizeof(btime_t));
        for (i = 0; i < 8; i++) {
            rv[i] = pv[7 - i];
        }
-       memcpy(&v, &rv, sizeof(uint64_t));
+       memcpy(&v, &rv, sizeof(btime_t));
     }
-    *ptr += sizeof(uint64_t);
+    *ptr += sizeof(btime_t);
     return v;
 }
 
 
+
 /*  unserial_float64  --  Unserialise a 64 bit IEEE floating point number.
                         This code assumes that the host floating point
                         format is IEEE and that floating point quantities
index f3adaab0d890921efba1e0c7f074f5b2f63bcce9..a7a5c525721ee3c1a157669b952c46c563b40ac8 100644 (file)
@@ -31,6 +31,7 @@ extern void serial_int32(uint8_t * * ptr, int32_t v);
 extern void serial_uint32(uint8_t * * ptr, uint32_t v);
 extern void serial_int64(uint8_t * * ptr, int64_t v);
 extern void serial_uint64(uint8_t * * ptr, uint64_t v);
+extern void serial_btime(uint8_t * * ptr, btime_t v);
 extern void serial_float64(uint8_t * * ptr, float64_t v);
 extern int  serial_string(uint8_t * ptr, char * str);
 extern int16_t unserial_int16(uint8_t * * ptr);
@@ -39,6 +40,7 @@ extern int32_t unserial_int32(uint8_t * * ptr);
 extern uint32_t unserial_uint32(uint8_t * * ptr);
 extern int64_t unserial_int64(uint8_t * * ptr);
 extern uint64_t unserial_uint64(uint8_t * * ptr);
+extern btime_t unserial_btime(uint8_t * * ptr);
 extern float64_t unserial_float64(uint8_t * * ptr);
 extern int unserial_string(uint8_t * ptr, char * str);
 
@@ -97,6 +99,9 @@ extern int unserial_string(uint8_t * ptr, char * str);
 /*  64 bit unsigned integer  */
 #define ser_uint64(x)  serial_uint64(&ser_ptr, x)
 
+/* btime -- 64 bit unsigned integer */
+#define ser_btime(x)    serial_btime(&ser_ptr, x)
+
 
 /*  64 bit IEEE floating point number  */
 #define ser_float64(x) serial_float64(&ser_ptr, x)
@@ -135,6 +140,9 @@ extern int unserial_string(uint8_t * ptr, char * str);
 /*  64 bit unsigned integer  */
 #define unser_uint64(x) (x) = unserial_uint64(&ser_ptr)
 
+/* btime -- 64 bit unsigned integer */
+#define unser_btime(x) (x) = unserial_btime(&ser_ptr)
+
 /*  64 bit IEEE floating point number  */
 #define unser_float64(x)(x) = unserial_float64(&ser_ptr)
 
index 92ba70d363936279b1ff8a4d171a6b7c7db43682..4c9e03e6b3195d96c12b0df9d275d302a9291fd4 100644 (file)
@@ -36,7 +36,7 @@
  */
 
 /*
- * Convert a string to btime_t (64 bit seconds)
+ * Convert a string duration to btime_t (64 bit seconds)
  * Returns 0: if error
           1: if OK, and value stored in value
  */
@@ -76,6 +76,9 @@ int string_to_btime(char *str, btime_t *value)
 
 }
 
+/*
+ * Edit a btime "duration" into ASCII
+ */
 char *edit_btime(btime_t val, char *buf)
 {
    char mybuf[30];
index a9152b9380c4bf1105b22da46ef483416f698ee9..70e97574d9f064f40c6843a091c4769f6589be1c 100644 (file)
@@ -27,9 +27,6 @@
 #include "bacula.h"
 #include "stored.h"
 
-extern int  FiledDataChan;           /* File daemon data channel (port) */
-extern int BaculaTapeVersion;        /* Version number */
-extern char BaculaId[];              /* Id string */
 
 /* Responses sent to the File daemon */
 static char OK_data[]    = "3000 OK data\n";
@@ -211,14 +208,17 @@ int do_append_data(JCR *jcr)
       }
    }
    /* 
-    *******FIXME***** we should put the ok status in the End of
-    * session label 
-    *
     *   We probably need a new flag that says "Do not attempt
     *   to write because there is no tape".
     */
    sm_check(__FILE__, __LINE__, False);
    Dmsg0(90, "Write_end_session_label()\n");
+   /* Create Job status for end of session label */
+   if (!job_cancelled(jcr) && ok) {
+      jcr->JobStatus = JS_Terminated;
+   } else if (!ok) {
+      jcr->JobStatus = JS_ErrorTerminated;
+   }
    if (!write_session_label(jcr, block, EOS_LABEL)) {
       Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
          strerror_dev(dev));
index c7eb7e43ab32856e12f2ed08702b444e6bb20c0b..73120bf44b4937afd4c98e6e7ca2bb738b13df4c 100644 (file)
@@ -183,8 +183,8 @@ int dir_create_jobmedia_record(JCR *jcr)
 
    bnet_fsend(dir, Create_job_media, jcr->Job, 
       jcr->VolFirstFile, jcr->JobFiles,
-      jcr->start_file, jcr->end_file,
-      jcr->start_block, jcr->end_block);
+      jcr->StartFile, jcr->EndFile,
+      jcr->StartBlock, jcr->EndBlock);
    Dmsg1(100, "create_jobmedia(): %s", dir->msg);
    if (bnet_recv(dir) <= 0) {
       Dmsg0(190, "create_jobmedia error bnet_recv\n");
index ea1335509cb556bc439dfa03eed6153168d22ee5..cd6a0a10641a1898eeafe94ed250f77e9ef39d78 100644 (file)
@@ -48,14 +48,25 @@ void dump_block(DEV_BLOCK *b, char *msg)
    uint32_t VolSessionId, VolSessionTime, data_len;
    int32_t  FileIndex;
    int32_t  Stream;
+   int bhl, rhl;
 
-   unser_begin(b->buf, BLKHDR_LENGTH);
+   unser_begin(b->buf, BLKHDR1_LENGTH);
    unser_uint32(CheckSum);
    unser_uint32(block_len);
    unser_uint32(BlockNumber);
    unser_bytes(Id, BLKHDR_ID_LENGTH);
-   ASSERT(unser_length(b->buf) == BLKHDR_LENGTH);
+   ASSERT(unser_length(b->buf) == BLKHDR1_LENGTH);
    Id[BLKHDR_ID_LENGTH] = 0;
+   if (Id[3] == '2') {
+      unser_uint32(VolSessionId);
+      unser_uint32(VolSessionTime);
+      bhl = BLKHDR2_LENGTH;
+      rhl = RECHDR2_LENGTH;
+   } else {
+      VolSessionId = VolSessionTime = 0;
+      bhl = BLKHDR1_LENGTH;
+      rhl = RECHDR1_LENGTH;
+   }
 
    if (block_len > 100000) {
       Dmsg3(20, "Dump block %s %s blocksize too big %d\n", msg, b, block_len);
@@ -67,20 +78,21 @@ void dump_block(DEV_BLOCK *b, char *msg)
    Dmsg6(10, "Dump block %s %x: size=%d BlkNum=%d\n\
                Hdrcksum=%x cksum=%x\n",
       msg, b, block_len, BlockNumber, CheckSum, BlockCheckSum);
-   p = b->buf + BLKHDR_LENGTH;
-   while (p < (b->buf + block_len+RECHDR_LENGTH)) { 
-      unser_begin(p, RECHDR_LENGTH);
+   p = b->buf + bhl;
+   while (p < (b->buf + block_len+WRITE_RECHDR_LENGTH)) { 
+      unser_begin(p, WRITE_RECHDR_LENGTH);
+      if (rhl == RECHDR1_LENGTH) {
       unser_uint32(VolSessionId);
       unser_uint32(VolSessionTime);
+      }
       unser_int32(FileIndex);
       unser_int32(Stream);
       unser_uint32(data_len);
-      Dmsg6(10, "Rec: VId=%d VT=%d FI=%s Strm=%s len=%d p=%x\n",
+      Dmsg6(10, "   Rec: VId=%d VT=%d FI=%s Strm=%s len=%d p=%x\n",
           VolSessionId, VolSessionTime, FI_to_ascii(FileIndex), stream_to_ascii(Stream),
           data_len, p);
-      p += data_len + RECHDR_LENGTH;
+      p += data_len + rhl;
   }
-
 }
     
 /*
@@ -113,6 +125,7 @@ DEV_BLOCK *new_block(DEVICE *dev)
       return NULL;
    }
    empty_block(block);
+   block->BlockVer = BLOCK_VER;       /* default write version */
    Dmsg1(90, "Returning new block=%x\n", block);
    return block;
 }
@@ -131,7 +144,7 @@ void free_block(DEV_BLOCK *block)
 /* Empty the block -- for writing */
 void empty_block(DEV_BLOCK *block)
 {
-   block->binbuf = BLKHDR_LENGTH;
+   block->binbuf = WRITE_BLKHDR_LENGTH;
    block->bufp = block->buf + block->binbuf;
    block->read_len = 0;
    block->failed_write = FALSE;
@@ -149,19 +162,22 @@ static void ser_block_header(DEV_BLOCK *block)
    uint32_t block_len = block->binbuf;
    
    Dmsg1(190, "ser_block_header: block_len=%d\n", block_len);
-   ser_begin(block->buf, BLKHDR_LENGTH);
+   ser_begin(block->buf, BLKHDR2_LENGTH);
    ser_uint32(CheckSum);
    ser_uint32(block_len);
    ser_uint32(block->BlockNumber);
-   ser_bytes(BLKHDR_ID, BLKHDR_ID_LENGTH);
-   ASSERT(ser_length(block->buf) == BLKHDR_LENGTH);
+   ser_bytes(WRITE_BLKHDR_ID, BLKHDR_ID_LENGTH);
+   if (BLOCK_VER >= 2) {
+      ser_uint32(block->VolSessionId);
+      ser_uint32(block->VolSessionTime);
+   }
 
    /* Checksum whole block except for the checksum */
    CheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH, 
                 block_len-BLKHDR_CS_LENGTH);
    Dmsg1(190, "ser_bloc_header: checksum=%x\n", CheckSum);
-   ser_begin(block->buf, BLKHDR_LENGTH);
-   ser_uint32(CheckSum);
+   ser_begin(block->buf, BLKHDR2_LENGTH);
+   ser_uint32(CheckSum);             /* now add checksum to block header */
 }
 
 /*
@@ -179,22 +195,39 @@ static int unser_block_header(DEVICE *dev, DEV_BLOCK *block)
    uint32_t block_len;
    uint32_t EndBlock;
    uint32_t BlockNumber;
+   int bhl;
 
    unser_begin(block->buf, BLKHDR_LENGTH);
    unser_uint32(CheckSum);
    unser_uint32(block_len);
    unser_uint32(BlockNumber);
    unser_bytes(Id, BLKHDR_ID_LENGTH);
-   ASSERT(unser_length(block->buf) == BLKHDR_LENGTH);
+   ASSERT(unser_length(block->buf) == BLKHDR1_LENGTH);
 
    Id[BLKHDR_ID_LENGTH] = 0;
-   block->bufp = block->buf + BLKHDR_LENGTH;
-   if (strncmp(Id, BLKHDR_ID, BLKHDR_ID_LENGTH) != 0) {
+   if (Id[3] == '1') {
+      bhl = BLKHDR1_LENGTH;
+      block->BlockVer = 1;
+      block->bufp = block->buf + bhl;
+      if (strncmp(Id, BLKHDR1_ID, BLKHDR_ID_LENGTH) != 0) {
       Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"),
-        BLKHDR_ID, Id);
+           BLKHDR1_ID, Id);
       Emsg0(M_ERROR, 0, dev->errmsg);
       return 0;
    }
+   } else {
+      unser_uint32(block->VolSessionId);
+      unser_uint32(block->VolSessionTime);
+      bhl = BLKHDR2_LENGTH;
+      block->BlockVer = 2;
+      block->bufp = block->buf + bhl;
+      if (strncmp(Id, BLKHDR2_ID, BLKHDR_ID_LENGTH) != 0) {
+         Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"),
+           BLKHDR2_ID, Id);
+        Emsg0(M_ERROR, 0, dev->errmsg);
+        return 0;
+      }
+   }
 
    ASSERT(block_len < MAX_BLOCK_LENGTH);    /* temp sanity check */
 
@@ -205,13 +238,13 @@ static int unser_block_header(DEVICE *dev, DEV_BLOCK *block)
    } else {
       EndBlock = block_len;
    }
-   block->binbuf = EndBlock - BLKHDR_LENGTH;
+   block->binbuf = EndBlock - bhl;
    block->block_len = block_len;
    block->BlockNumber = BlockNumber;
    Dmsg3(190, "Read binbuf = %d %d block_len=%d\n", block->binbuf,
-      BLKHDR_LENGTH, block_len);
+      bhl, block_len);
    if (block_len > block->buf_len) {
-      Mmsg2(&dev->errmsg,  _("Block length %d is greater than buffer %d\n"),
+      Mmsg2(&dev->errmsg,  _("Block length %u is greater than buffer %u\n"),
         block_len, block->buf_len);
       Emsg0(M_ERROR, 0, dev->errmsg);
       return 0;
@@ -256,7 +289,7 @@ int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
  */
 int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block)
 {
-   int stat = 0;
+   size_t stat = 0;
    uint32_t wlen;                    /* length to write */
 
 #ifdef NO_TAPE_WRITE_TEST
@@ -267,12 +300,12 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block)
 
    /* dump_block(block, "before write"); */
    if (dev->state & ST_WEOT) {
-      Dmsg0(90, "return write_block_to_dev with ST_WEOT\n");
+      Dmsg0(100, "return write_block_to_dev with ST_WEOT\n");
       return 0;
    }
    wlen = block->binbuf;
-   if (wlen <= BLKHDR_LENGTH) {       /* Does block have data in it? */
-      Dmsg0(190, "return write_block_to_dev no data to write\n");
+   if (wlen <= WRITE_BLKHDR_LENGTH) {  /* Does block have data in it? */
+      Dmsg0(100, "return write_block_to_dev no data to write\n");
       return 1;
    }
    /* 
@@ -318,7 +351,8 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block)
    }
 
    dev->VolCatInfo.VolCatWrites++;
-   if ((uint32_t) (stat=write(dev->fd, block->buf, wlen)) != wlen) {
+// Dmsg1(000, "Pos before write=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR));
+   if ((uint32_t) (stat=write(dev->fd, block->buf, (size_t)wlen)) != wlen) {
       /* We should check for errno == ENOSPC, BUT many 
        * devices simply report EIO when it is full.
        * with a little more thought we may be able to check
@@ -344,15 +378,17 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block)
       weof_dev(dev, 1);              /* write second eof */
       return 0;
    }
+// Dmsg1(000, "Pos after write=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR));
    dev->VolCatInfo.VolCatBytes += block->binbuf;
    dev->VolCatInfo.VolCatBlocks++;   
    dev->file_bytes += block->binbuf;
 
    /* Limit maximum File size on volume to user specified value */
-   if ((dev->max_file_size > 0) &&
-       dev->file_bytes >= dev->max_file_size) {
+   if (dev->state & ST_TAPE) {
+      if ((dev->max_file_size > 0) && dev->file_bytes >= dev->max_file_size) {
       weof_dev(dev, 1);              /* write eof */
    }
+   }
 
    Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num,
       wlen);
@@ -368,10 +404,8 @@ int read_block_from_device(DEVICE *dev, DEV_BLOCK *block)
 {
    int stat;
    Dmsg0(90, "Enter read_block_from_device\n");
-   new_lock_device(dev);
    lock_device(dev);
    stat = read_block_from_dev(dev, block);
-   new_unlock_device(dev);
    unlock_device(dev);
    Dmsg0(90, "Leave read_block_from_device\n");
    return stat;
@@ -384,10 +418,12 @@ int read_block_from_device(DEVICE *dev, DEV_BLOCK *block)
  */
 int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block)
 {
-   int stat;
+   size_t stat;
 
-   Dmsg0(90, "Full read() in read_block_from_device()\n");
-   if ((stat=read(dev->fd, block->buf, block->buf_len)) < 0) {
+   Dmsg1(100, "Full read() in read_block_from_device() len=%d\n",
+        block->buf_len);
+// Dmsg1(000, "Pos before read=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR));
+   if ((stat=read(dev->fd, block->buf, (size_t)block->buf_len)) < 0) {
 
 /* ***FIXME****  add code to detect buffer too small, and
    reallocate buffer, backspace, and reread.
@@ -401,6 +437,7 @@ int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block)
         dev->dev_name, strerror(dev->dev_errno));
       return 0;
    }
+// Dmsg1(000, "Pos after read=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR));
    Dmsg1(90, "Read device got %d bytes\n", stat);
    if (stat == 0) {            /* Got EOF ! */
       dev->block_num = block->read_len = 0;
@@ -415,7 +452,7 @@ int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block)
    }
    /* Continue here for successful read */
    block->read_len = stat;     /* save length read */
-   if (block->read_len < BLKHDR_LENGTH) {
+   if (block->read_len < BLKHDR2_LENGTH) {
       Mmsg2(&dev->errmsg, _("Very short block of %d bytes on device %s discarded.\n"), 
         block->read_len, dev->dev_name);
       dev->state |= ST_SHORT;  /* set short block */
@@ -448,14 +485,19 @@ int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block)
     * from shuffling blocks around in the buffer. Take a
     * look at this from an efficiency stand point later, but
     * it should only happen once at the end of each job.
+    *
+    * I've been lseek()ing negative relative to SEEK_CUR for 30
+    *  years now. However, it seems that with the new off_t definition,
+    *  it is not possible to seek negative amounts, so we use two
+    *  lseek(). One to get the position, then the second to do an
+    *  absolute positioning -- so much for efficiency.  KES Sep 02.
     */
    Dmsg0(200, "At end of read block\n");
    if (block->read_len > block->block_len && !(dev->state & ST_TAPE)) {
-
-      Dmsg3(200, "Block: %d read_len %d > %d block_len\n", dev->block_num,
-block->read_len, block->block_len);
-      lseek(dev->fd, block->block_len-block->read_len, SEEK_CUR);   
-      Dmsg2(90, "Did lseek blk_size=%d rdlen=%d\n", block->block_len,
+      off_t pos = lseek(dev->fd, (off_t)0, SEEK_CUR); /* get curr pos */
+      pos -= (block->read_len - block->block_len);
+      lseek(dev->fd, pos, SEEK_SET);   
+      Dmsg2(100, "Did lseek blk_size=%d rdlen=%d\n", block->block_len,
            block->read_len);
    }
    Dmsg2(200, "Exit read_block read_len=%d block_len=%d\n",
index b6b620689f907b7fcbde4e95f3f19844c90697aa..ca265dea7c41f642784abd05ac25ecf5e7206dd3 100644 (file)
 #define DEFAULT_BLOCK_SIZE (512 * 126)  /* 64,512 N.B. do not use 65,636 here */
 
 /* Block Header definitions. */
-#define BLKHDR_ID        "BB01"
+#define BLKHDR1_ID       "BB01"
+#define BLKHDR2_ID       "BB02"
 #define BLKHDR_ID_LENGTH  4
 #define BLKHDR_CS_LENGTH  4             /* checksum length */
-#define BLKHDR_LENGTH    16             /* Total length */
+#define BLKHDR1_LENGTH   16             /* Total length */
+#define BLKHDR2_LENGTH   24             /* Total length */
+
+#define WRITE_BLKHDR_ID     BLKHDR1_ID
+#define WRITE_BLKHDR_LENGTH BLKHDR1_LENGTH
+#define BLOCK_VER               1
+
+/* Record header definitions */
+#define RECHDR1_LENGTH      20
+#define RECHDR2_LENGTH      12
+#define WRITE_RECHDR_LENGTH RECHDR1_LENGTH
+
+/* Tape label and version definitions */
+#define BaculaId "Bacula 0.9 mortal\n"
+#define BaculaTapeVersion 10
+#define OldCompatibleBaculaTapeVersion1  10
+#define OldCompatibleBaculaTapeVersion2   9
+
 
 /*
  * This is the Media structure for a block header
  *  Note, when written, it is serialized.
- */
-typedef struct s_block_hdr {
+
    uint32_t CheckSum;
-   uint32_t block_size;
+   uint32_t block_len; 
    uint32_t BlockNumber;
-   char     Id[BLKHDR_ID_LENGTH+1];
-} BLOCK_HDR;
+   char     Id[BLKHDR_ID_LENGTH];
+
+ * for BB02 block, we also have
+
+   uint32_t VolSessionId;
+   uint32_t VolSessionTime;
+ */
 
 /*
  * DEV_BLOCK for reading and writing blocks.
@@ -70,6 +92,9 @@ typedef struct s_dev_block {
    uint32_t buf_len;                  /* max/default block length */
    uint32_t BlockNumber;              /* sequential block number */
    uint32_t read_len;                 /* bytes read into buffer */  
+   uint32_t VolSessionId;             /* */
+   uint32_t VolSessionTime;           /* */
+   int      BlockVer;                 /* block version 1 or 2 */
    int failed_write;                  /* set if write failed */
    char *bufp;                        /* pointer into buffer */
    POOLMEM *buf;                      /* actual data buffer. This is a 
index aa2bc563dc1395823d5b55979ddd89a0ffb1f4f2..61da289ae277a4c388f19494c95842d4529c5b75 100644 (file)
@@ -48,8 +48,6 @@ static SESSION_LABEL sessrec;
 static uint32_t num_files = 0;
 static long record_file_index;
 
-extern char BaculaId[];
-
 static FF_PKT ff;
 
 static BSR *bsr = NULL;
@@ -60,6 +58,7 @@ static void usage()
 "\nVersion: " VERSION " (" DATE ")\n\n"
 "Usage: bls [-d debug_level] <physical-device-name>\n"
 "       -b <file>       specify a bootstrap file\n"
+"       -d <level>      specify debug level\n"
 "       -e <file>       exclude list\n"
 "       -i <file>       include list\n"
 "       -j              list jobs\n"
@@ -225,7 +224,7 @@ static void do_blocks(char *infname)
    }
    for ( ;; ) {
       if (!read_block_from_device(dev, block)) {
-         Dmsg0(20, "!read_block()\n");
+         Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev));
         if (dev->state & ST_EOT) {
            if (!mount_next_read_volume(jcr, dev, block)) {
                printf("End of File on device\n");
@@ -252,14 +251,18 @@ static void do_blocks(char *infname)
         display_error_status(dev);
         break;
       }
-
-      if (verbose) {
+      Dmsg5(100, "Blk=%u blen=%u bVer=%d SessId=%d SessTim=%d\n",
+        block->BlockNumber, block->block_len, block->BlockVer,
+        block->VolSessionId, block->VolSessionTime);
+      if (verbose == 1) {
         read_record_from_block(block, rec);
-         Pmsg6(-1, "Block: %d blen=%d First rec FI=%s SessId=%d Strm=%s rlen=%d\n",
+         Pmsg6(-1, "Block: %u blen=%u First rec FI=%s SessId=%d Strm=%s rlen=%d\n",
              block->BlockNumber, block->block_len,
              FI_to_ascii(rec->FileIndex), rec->VolSessionId, 
              stream_to_ascii(rec->Stream), rec->data_len);
         rec->remainder = 0;
+      } else if (verbose > 1) {
+         dump_block(block, "");
       } else {
          printf("Block: %d size=%d\n", block->BlockNumber, block->block_len);
       }
index de17a011c080e409ef94f4a058e1c863c3fba993..678718ae74fe343d301b33426fb911181e1cb117 100644 (file)
 /* Forward referenced functions */
 static void do_scan(char *fname);
 static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
-static int  create_file_attributes_record(B_DB *db, char *fname, char *lname, int type,
+static int  create_file_attributes_record(B_DB *db, JCR *mjcr, 
+                              char *fname, char *lname, int type,
                               char *ap, DEV_RECORD *rec);
 static int  create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl);
+static int  update_media_record(B_DB *db, MEDIA_DBR *mr);
 static int  create_pool_record(B_DB *db, POOL_DBR *pr);
-static int  create_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *label, DEV_RECORD *rec);
+static JCR *create_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *label, DEV_RECORD *rec);
 static int  update_job_record(B_DB *db, JOB_DBR *mr, SESSION_LABEL *elabel, 
                              DEV_RECORD *rec);
 static int  create_client_record(B_DB *db, CLIENT_DBR *cr);
 static int  create_fileset_record(B_DB *db, FILESET_DBR *fsr);
 static int  create_jobmedia_record(B_DB *db, JCR *jcr);
-static void create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId);
+static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId);
+static int update_MD5_record(B_DB *db, char *MD5buf, DEV_RECORD *rec);
 
 
 /* Global variables */
 static DEVICE *dev = NULL;
 static B_DB *db;
-static JCR *jcr;                     /* jcr for bscan */
-static JCR *jobjcr;                  /* jcr for simulating running job */
+static JCR *bjcr;                    /* jcr for bscan */
 static BSR *bsr;
 static struct stat statp;
 static int type;
@@ -68,6 +70,7 @@ static JOB_DBR jr;
 static CLIENT_DBR cr;
 static FILESET_DBR fsr;
 static ATTR_DBR ar;
+static FILE_DBR fr;
 static SESSION_LABEL label;
 static SESSION_LABEL elabel;
 
@@ -77,6 +80,8 @@ static char *db_password = "";
 static char *wd = "/tmp";
 static int verbose = 0;
 static int update_db = 0;
+static int update_vol_info = 0;
+static int list_records = 0;
 
 static void usage()
 {
@@ -85,9 +90,11 @@ static void usage()
 "Usage: bscan [-d debug_level] <bacula-archive>\n"
 "       -b bootstrap      specify a bootstrap file\n"
 "       -dnn              set debug level to nn\n"
+"       -m                update media info in database\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"
+"       -r                list records\n"
 "       -s                synchronize or store in database\n"
 "       -v                verbose\n"
 "       -w dir            specify working directory (default /tmp)\n"
@@ -103,7 +110,7 @@ int main (int argc, char *argv[])
    init_msg(NULL, NULL);
 
 
-   while ((ch = getopt(argc, argv, "b:d:n:p:su:vw:?")) != -1) {
+   while ((ch = getopt(argc, argv, "b:d:mn:p:rsu:vw:?")) != -1) {
       switch (ch) {
          case 'b':
            bsr = parse_bsr(NULL, optarg);
@@ -114,6 +121,10 @@ int main (int argc, char *argv[])
               debug_level = 1; 
            break;
 
+         case 'm':
+           update_vol_info = 1;
+           break;
+
          case 'n':
            db_name = optarg;
            break;
@@ -126,6 +137,10 @@ int main (int argc, char *argv[])
            db_password = optarg;
            break;
 
+         case 'r':
+           list_records = 1;
+           break;
+
          case 's':
            update_db = 1;
            break;
@@ -154,7 +169,7 @@ int main (int argc, char *argv[])
 
    working_directory = wd;
 
-   jcr = setup_jcr("bscan", argv[0], bsr);
+   bjcr = setup_jcr("bscan", argv[0], bsr);
 
    if ((db=db_init_database(NULL, db_name, db_user, db_password)) == NULL) {
       Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n"));
@@ -169,7 +184,7 @@ int main (int argc, char *argv[])
 
    do_scan(argv[0]);
 
-   free_jcr(jcr);
+   free_jcr(bjcr);
    return 0;
 }
   
@@ -177,7 +192,7 @@ int main (int argc, char *argv[])
 static void do_scan(char *devname)            
 {
 
-   dev = setup_to_read_device(jcr);
+   dev = setup_to_read_device(bjcr);
    if (!dev) { 
       exit(1);
    }
@@ -191,11 +206,12 @@ static void do_scan(char *devname)
    memset(&jr, 0, sizeof(jr));
    memset(&cr, 0, sizeof(cr));
    memset(&fsr, 0, sizeof(fsr));
+   memset(&fr, 0, sizeof(fr));
 
-   detach_jcr_from_device(dev, jcr);
+   detach_jcr_from_device(dev, bjcr);
 
-   read_records(jcr, dev, record_cb, mount_next_read_volume);
-   release_device(jcr, dev);
+   read_records(bjcr, dev, record_cb, mount_next_read_volume);
+   release_device(bjcr, dev);
 
    free_pool_memory(fname);
    free_pool_memory(ofile);
@@ -203,13 +219,26 @@ static void do_scan(char *devname)
    term_dev(dev);
 }
 
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 {
+   JCR *mjcr;
+   char ec1[30];
+
+   if (rec->data_len > 0) {
+      mr.VolBytes += rec->data_len + WRITE_RECHDR_LENGTH; /* Accumulate Volume bytes */
+   }
+   if (list_records) {
+      Pmsg5(000, _("Record: SessId=%u SessTim=%u FileIndex=%d Stream=%d len=%u\n"),
+           rec->VolSessionId, rec->VolSessionTime, rec->FileIndex, 
+           rec->Stream, rec->data_len);
+   }
+Dmsg1(000, "record_cb block=%u\n", rec->Block);
    /* 
     * Check for Start or End of Session Record 
     *
     */
    if (rec->FileIndex < 0) {
+      int save_update_db = update_db;
 
       if (verbose > 1) {
         dump_label_record(dev, rec, 1);
@@ -249,6 +278,9 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
               if (verbose) {
                   Pmsg1(000, "Media record for %s found in DB.\n", mr.VolumeName);
               }
+              /* Clear out some volume statistics that will be updated */
+              mr.VolJobs = mr.VolFiles = mr.VolBlocks = 0;
+              mr.VolBytes = rec->data_len + 20;
            } else {
                Pmsg1(000, "VOL_LABEL: Media record not found for Volume: %s\n",
                  mr.VolumeName);
@@ -263,42 +295,56 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
                Pmsg1(000, "Media type \"%s\" is OK.\n", mr.MediaType);
            }
            /* Reset some JCR variables */
-           for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+           for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
               mjcr->VolFirstFile = mjcr->FileIndex = 0;
-              mjcr->start_block = mjcr->end_block = 0;
-              mjcr->start_file = mjcr->end_file = 0;
+              mjcr->StartBlock = mjcr->EndBlock = 0;
+              mjcr->StartFile = mjcr->EndFile = 0;
            }
 
             Pmsg1(000, "VOL_LABEL: OK for Volume: %s\n", mr.VolumeName);
            break;
         case SOS_LABEL:
+
+           mr.VolJobs++;
            unser_session_label(&label, rec);
            memset(&jr, 0, sizeof(jr));
            jr.JobId = label.JobId;
            if (db_get_job_record(db, &jr)) {
               /* Job record already exists in DB */
-              create_jcr(&jr, rec, jr.JobId);
-              attach_jcr_to_device(dev, jobjcr);
+               update_db = 0;  /* don't change db in create_job_record */
               if (verbose) {
                   Pmsg1(000, _("SOS_LABEL: Found Job record for JobId: %d\n"), jr.JobId);
               }
            } else {
-            
               /* Must create a Job record in DB */
                Pmsg1(000, "SOS_LABEL: Job record not found for JobId: %d\n",
                  jr.JobId);
-
-              /* Create Client record */
+           }
+           /* Create Client record if not already there */
               strcpy(cr.Name, label.ClientName);
               create_client_record(db, &cr);
               jr.ClientId = cr.ClientId;
 
-              create_job_record(db, &jr, &label, rec);
+            /* process label, if Job record exists don't update db */
+           mjcr = create_job_record(db, &jr, &label, rec);
+           update_db = save_update_db;
+
               jr.PoolId = pr.PoolId;
               /* Set start positions into JCR */
-              jobjcr->start_block = dev->block_num;
-              jobjcr->start_file = dev->file;
-           }
+           mjcr->StartBlock = dev->block_num;
+           mjcr->StartFile = dev->file;
+           mjcr->start_time = jr.StartTime;
+           mjcr->JobLevel = jr.Level;
+
+           mjcr->client_name = get_pool_memory(PM_FNAME);
+           pm_strcpy(&mjcr->client_name, label.ClientName);
+           mjcr->pool_type = get_pool_memory(PM_FNAME);
+           pm_strcpy(&mjcr->pool_type, label.PoolType);
+           mjcr->fileset_name = get_pool_memory(PM_FNAME);
+           pm_strcpy(&mjcr->fileset_name, label.FileSetName);
+           mjcr->pool_name = get_pool_memory(PM_FNAME);
+           pm_strcpy(&mjcr->pool_name, label.PoolName);
+
            if (rec->VolSessionId != jr.VolSessionId) {
                Pmsg3(000, "SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n",
                  jr.JobId,
@@ -326,27 +372,57 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            create_fileset_record(db, &fsr);
            jr.FileSetId = fsr.FileSetId;
 
-           /* Do the final update to the Job record */
-           update_job_record(db, &jr, &elabel, rec);
 
-           /* Create JobMedia record */
-           jobjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-           if (!jobjcr) {
+           mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+           if (!mjcr) {
                Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
                   rec->VolSessionId, rec->VolSessionTime);
               break;
            }
 
-           jobjcr->end_block = dev->block_num;
-           jobjcr->end_file = dev->file;
-           create_jobmedia_record(db, jobjcr);
-           detach_jcr_from_device(dev, jobjcr);
-           free_jcr(jobjcr);
+           /* Do the final update to the Job record */
+           update_job_record(db, &jr, &elabel, rec);
+
+           mjcr->end_time = jr.EndTime;
+           mjcr->JobStatus = JS_Terminated;
+
+           /* Create JobMedia record */
+           create_jobmedia_record(db, mjcr);
+           detach_jcr_from_device(dev, mjcr);
+           free_jcr(mjcr);
 
-            Pmsg1(000, "EOS_LABEL: OK for JobId=%d\n", elabel.JobId);
            break;
         case EOM_LABEL:
            break;
+        case EOT_LABEL:              /* end of all tapes */
+           /* 
+            * Wiffle through all jobs still open and close
+            *   them.
+            */
+           if (update_db) {
+              for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+                 jr.JobId = mjcr->JobId;
+                 jr.JobStatus = JS_ErrorTerminated;
+                 jr.JobFiles = mjcr->JobFiles;
+                 jr.JobBytes = mjcr->JobBytes;
+                 jr.VolSessionId = mjcr->VolSessionId;
+                 jr.VolSessionTime = mjcr->VolSessionTime;
+                 jr.JobTDate = (btime_t)mjcr->start_time;
+                 jr.ClientId = mjcr->ClientId;
+                 free_jcr(mjcr);
+                 if (!db_update_job_end_record(db, &jr)) {
+                     Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
+                 }
+              }
+           }
+           mr.VolFiles = rec->File;
+           mr.VolBlocks = rec->Block;
+           mr.VolBytes += mr.VolBlocks * WRITE_BLKHDR_LENGTH; /* approx. */
+           mr.VolMounts++;
+           update_media_record(db, &mr);
+            Pmsg3(0, _("End of Volume. VolFiles=%u VolBlocks=%u VolBytes=%s\n"), mr.VolFiles,
+                      mr.VolBlocks, edit_uint64_with_commas(mr.VolBytes, ec1));
+           break;
         default:
            break;
       }
@@ -404,18 +480,51 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         decode_stat(ap, &statp);
         print_ls_output(fname, lname, type, &statp);   
       }
-      create_file_attributes_record(db, fname, lname, type, ap, rec);
+      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+      if (!mjcr) {
+         Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
+                     rec->VolSessionId, rec->VolSessionTime);
+        return;
+      }
+      fr.JobId = mjcr->JobId;
+      fr.FileId = 0;
+      if (db_get_file_attributes_record(db, fname, &fr)) {
+        if (verbose > 1) {
+            Pmsg1(000, _("File record already exists for: %s\n"), fname);
+        }
+      } else {
+        create_file_attributes_record(db, mjcr, fname, lname, type, ap, rec);
+      }
+      free_jcr(mjcr);
 
    /* Data stream and extracting */
    } else if (rec->Stream == STREAM_FILE_DATA) {
+      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+      if (!mjcr) {
+         Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
+                     rec->VolSessionId, rec->VolSessionTime);
+        return;
+      }
+      mjcr->JobBytes += rec->data_len;
+      free_jcr(mjcr);                /* done using JCR */
 
    } else if (rec->Stream == STREAM_GZIP_DATA) {
+      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+      if (!mjcr) {
+         Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
+                     rec->VolSessionId, rec->VolSessionTime);
+        return;
+      }
+      mjcr->JobBytes += rec->data_len;
+      free_jcr(mjcr);                /* done using JCR */
 
    } else if (rec->Stream == STREAM_MD5_SIGNATURE) {
+      char MD5buf[30];
+      bin_to_base64(MD5buf, (char *)rec->data, 16); /* encode 16 bytes */
       if (verbose > 1) {
-         Pmsg0(000, _("Got MD5 record.\n"));
+         Pmsg1(000, _("Got MD5 record: %s\n"), MD5buf);
       }
-      /* ****FIXME**** implement db_update_md5_record */
+      update_MD5_record(db, MD5buf, rec);
    } else {
       Pmsg2(0, _("Unknown stream type!!! stream=%d data=%s\n"), rec->Stream, rec->data);
    }
@@ -449,21 +558,11 @@ static void dird_free_jcr(JCR *jcr)
  * We got a File Attributes record on the tape.  Now, lookup the Job
  *   record, and then create the attributes record.
  */
-static int create_file_attributes_record(B_DB *db, char *fname, char *lname, int type,
+static int create_file_attributes_record(B_DB *db, JCR *mjcr,
+                              char *fname, char *lname, int type,
                               char *ap, DEV_RECORD *rec)
 {
-   JCR *mjcr;
 
-   if (!update_db) {
-      return 1;
-   }
-
-   mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-   if (!mjcr) {
-      Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
-                  rec->VolSessionId, rec->VolSessionTime);
-      return 0;
-   }
    ar.fname = fname;
    ar.link = lname;
    ar.ClientId = mjcr->ClientId;
@@ -475,12 +574,18 @@ static int create_file_attributes_record(B_DB *db, char *fname, char *lname, int
       mjcr->VolFirstFile = rec->FileIndex;
    }
    mjcr->FileIndex = rec->FileIndex;
-   free_jcr(mjcr);                   /* done using JCR */
+   mjcr->JobFiles++;
+
+   if (!update_db) {
+      return 1;
+   }
 
    if (!db_create_file_attributes_record(db, &ar)) {
       Pmsg1(0, _("Could not create File Attributes record. ERR=%s\n"), db_strerror(db));
       return 0;
    }
+   mjcr->FileId = ar.FileId;
+
    if (verbose > 1) {
       Pmsg1(000, _("Created File record: %s\n"), fname);   
    }
@@ -494,9 +599,7 @@ static int create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl)
 {
    struct date_time dt;
    struct tm tm;
-   if (!update_db) {
-      return 1;
-   }
+
    strcpy(mr->VolStatus, "Full");
    mr->VolRetention = 355 * 3600 * 24; /* 1 year */
    dt.julian_day_number = vl->write_date;
@@ -507,6 +610,11 @@ static int create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl)
    dt.julian_day_fraction = vl->label_time;
    tm_decode(&dt, &tm);
    mr->LabelDate = mktime(&tm);
+
+   if (!update_db) {
+      return 1;
+   }
+
    if (!db_create_media_record(db, mr)) {
       Pmsg1(0, _("Could not create media record. ERR=%s\n"), db_strerror(db));
       return 0;
@@ -516,21 +624,42 @@ static int create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl)
       return 0;
    }
    if (verbose) {
-      Pmsg2(000, _("Created Media record for Volume: %s, JobId: %d\n"), 
-                  mr->VolumeName, jr.JobId);
+      Pmsg1(000, _("Created Media record for Volume: %s\n"), mr->VolumeName);
    }
    return 1;
 
 }
 
-static int create_pool_record(B_DB *db, POOL_DBR *pr)
+/*
+ * Called at end of media to update it
+ */
+static int update_media_record(B_DB *db, MEDIA_DBR *mr)
 {
-   if (!update_db) {
+   if (!update_db && !update_vol_info) {
       return 1;
    }
+
+   if (!db_update_media_record(db, mr)) {
+      Pmsg1(0, _("Could not update media record. ERR=%s\n"), db_strerror(db));
+      return 0;
+   }
+   if (verbose) {
+      Pmsg1(000, _("Updated Media record at end of Volume: %s\n"), mr->VolumeName);
+   }
+   return 1;
+
+}
+
+
+static int create_pool_record(B_DB *db, POOL_DBR *pr)
+{
    pr->NumVols++;
    pr->UseCatalog = 1;
    pr->VolRetention = 355 * 3600 * 24; /* 1 year */
+
+   if (!update_db) {
+      return 1;
+   }
    if (!db_create_pool_record(db, pr)) {
       Pmsg1(0, _("Could not create pool record. ERR=%s\n"), db_strerror(db));
       return 0;
@@ -566,12 +695,19 @@ static int create_fileset_record(B_DB *db, FILESET_DBR *fsr)
    if (!update_db) {
       return 1;
    }
+   fsr->FileSetId = 0;
+   if (db_get_fileset_record(db, fsr)) {
+      if (verbose) {
+         Pmsg1(000, _("Fileset \"%s\" already exists.\n"), fsr->FileSet);
+      }
+   } else {
    if (!db_create_fileset_record(db, fsr)) {
       Pmsg1(0, _("Could not create FileSet record. ERR=%s\n"), db_strerror(db));
       return 0;
    }
    if (verbose) {
-      Pmsg1(000, _("Created FileSet record %s\n"), fsr->FileSet);
+         Pmsg1(000, _("Created FileSet record \"%s\"\n"), fsr->FileSet);
+      }
    }
    return 1;
 }
@@ -581,17 +717,13 @@ static int create_fileset_record(B_DB *db, FILESET_DBR *fsr)
  *  the Job record and to update it when the Job actually
  *  begins running.
  */
-static int create_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *label, 
+static JCR *create_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *label, 
                             DEV_RECORD *rec)
 {
+   JCR *mjcr;
    struct date_time dt;
    struct tm tm;
 
-   if (!update_db) {
-      return 1;
-   }
-   Pmsg1(000, _("Creating Job record for JobId: %d\n"), jr->JobId);
-
    jr->JobId = label->JobId;
    jr->Type = label->JobType;
    jr->Level = label->JobLevel;
@@ -607,24 +739,28 @@ static int create_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *label,
    jr->VolSessionId = rec->VolSessionId;
    jr->VolSessionTime = rec->VolSessionTime;
 
+   /* Now create a JCR as if starting the Job */
+   mjcr = create_jcr(jr, rec, label->JobId);
+
+   if (!update_db) {
+      return mjcr;
+   }
+
    /* This creates the bare essentials */
    if (!db_create_job_record(db, jr)) {
       Pmsg1(0, _("Could not create job record. ERR=%s\n"), db_strerror(db));
-      return 0;
+      return mjcr;
    }
 
-   /* Now create a JCR as if starting the Job */
-   create_jcr(jr, rec, label->JobId);
-
    /* This adds the client, StartTime, JobTDate, ... */
    if (!db_update_job_start_record(db, jr)) {
       Pmsg1(0, _("Could not update job start record. ERR=%s\n"), db_strerror(db));
-      return 0;
+      return mjcr;
    }
    if (verbose) {
       Pmsg1(000, _("Created Job record for JobId: %d\n"), jr->JobId);
    }
-   return 1;
+   return mjcr;
 }
 
 /* 
@@ -638,9 +774,6 @@ static int update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel,
    struct tm tm;
    JCR *mjcr;
 
-   if (!update_db) {
-      return 1;
-   }
    mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
    if (!mjcr) {
       Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
@@ -652,20 +785,81 @@ static int update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel,
    tm_decode(&dt, &tm);
    jr->JobId = mjcr->JobId;
    jr->JobStatus = JS_Terminated;     /* ***FIXME*** need to add to EOS label */
+   mjcr->JobStatus = JS_Terminated;
    jr->EndTime = mktime(&tm);
+   mjcr->end_time = jr->EndTime;
    jr->JobFiles = elabel->JobFiles;
    jr->JobBytes = elabel->JobBytes;
    jr->VolSessionId = rec->VolSessionId;
    jr->VolSessionTime = rec->VolSessionTime;
    jr->JobTDate = (btime_t)mjcr->start_time;
    jr->ClientId = mjcr->ClientId;
+
+   if (!update_db) {
+      free_jcr(mjcr);
+      return 1;
+   }
+   
    if (!db_update_job_end_record(db, jr)) {
       Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
       free_jcr(mjcr);
       return 0;
    }
    if (verbose) {
-      Pmsg1(000, _("Updated Job termination record for JobId: %d\n"), jr->JobId);
+      Pmsg1(000, _("Updated Job termination record for JobId: %u\n"), jr->JobId);
+   }
+   if (verbose > 1) {
+      char *term_msg;
+      static char term_code[70];
+      char sdt[50], edt[50];
+      char ec1[30], ec2[30], ec3[30];
+
+      switch (mjcr->JobStatus) {
+      case JS_Terminated:
+         term_msg = _("Backup OK");
+        break;
+      case JS_FatalError:
+      case JS_ErrorTerminated:
+         term_msg = _("*** Backup Error ***");
+        break;
+      case JS_Cancelled:
+         term_msg = _("Backup Cancelled");
+        break;
+      default:
+        term_msg = term_code;
+         sprintf(term_code, _("Job Termination code: %d"), mjcr->JobStatus);
+        break;
+      }
+      bstrftime(sdt, sizeof(sdt), mjcr->start_time);
+      bstrftime(edt, sizeof(edt), mjcr->end_time);
+      Pmsg14(000,  _("%s\n\
+JobId:                  %d\n\
+Job:                    %s\n\
+FileSet:                %s\n\
+Backup Level:           %s\n\
+Client:                 %s\n\
+Start time:             %s\n\
+End time:               %s\n\
+Files Written:          %s\n\
+Bytes Written:          %s\n\
+Volume Session Id:      %d\n\
+Volume Session Time:    %d\n\
+Last Volume Bytes:      %s\n\
+Termination:            %s\n\n"),
+       edt,
+       mjcr->JobId,
+       mjcr->Job,
+       mjcr->fileset_name,
+       job_level_to_str(mjcr->JobLevel),
+       mjcr->client_name,
+       sdt,
+       edt,
+       edit_uint64_with_commas(mjcr->JobFiles, ec1),
+       edit_uint64_with_commas(mjcr->JobBytes, ec2),
+       mjcr->VolSessionId,
+       mjcr->VolSessionTime,
+       edit_uint64_with_commas(mr.VolBytes, ec3),
+       term_msg);
    }
    free_jcr(mjcr);
    return 1;
@@ -675,18 +869,23 @@ static int create_jobmedia_record(B_DB *db, JCR *mjcr)
 {
    JOBMEDIA_DBR jmr;
 
-   if (!update_db) {
-      return 1;
-   }
+   mjcr->EndBlock = dev->block_num;
+   mjcr->EndFile = dev->file;
+
    memset(&jmr, 0, sizeof(jmr));
    jmr.JobId = mjcr->JobId;
    jmr.MediaId = mr.MediaId;
    jmr.FirstIndex = mjcr->VolFirstFile;
    jmr.LastIndex = mjcr->FileIndex;
-   jmr.StartFile = mjcr->start_file;
-   jmr.EndFile = mjcr->end_file;
-   jmr.StartBlock = mjcr->start_block;
-   jmr.EndBlock = mjcr->end_block;
+   jmr.StartFile = mjcr->StartFile;
+   jmr.EndFile = mjcr->EndFile;
+   jmr.StartBlock = mjcr->StartBlock;
+   jmr.EndBlock = mjcr->EndBlock;
+
+
+   if (!update_db) {
+      return 1;
+   }
 
    if (!db_create_jobmedia_record(db, &jmr)) {
       Pmsg1(0, _("Could not create JobMedia record. ERR=%s\n"), db_strerror(db));
@@ -699,11 +898,44 @@ static int create_jobmedia_record(B_DB *db, JCR *mjcr)
    return 1;
 }
 
+/* 
+ * Simulate the database call that updates the MD5 record
+ */
+static int update_MD5_record(B_DB *db, char *MD5buf, DEV_RECORD *rec)
+{
+   JCR *mjcr;
+
+   mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+   if (!mjcr) {
+      Pmsg2(000, _("Could not find SessId=%d SessTime=%d for EOS record.\n"),
+                  rec->VolSessionId, rec->VolSessionTime);
+      return 0;
+   }
+
+   if (!update_db) {
+      free_jcr(mjcr);
+      return 1;
+   }
+   
+   if (!db_add_MD5_to_file_record(db, mjcr->FileId, MD5buf)) {
+      Pmsg1(0, _("Could not add MD5 to File record. ERR=%s\n"), db_strerror(db));
+      free_jcr(mjcr);
+      return 0;
+   }
+   if (verbose > 1) {
+      Pmsg0(000, _("Updated MD5 record\n"));
+   }
+   free_jcr(mjcr);
+   return 1;
+}
+
+
 /* 
  * Create a JCR as if we are really starting the job
  */
-static void create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
+static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
 {
+   JCR *jobjcr;
    /*
     * Transfer as much as possible to the Job JCR. Most important is
     *  the JobId and the ClientId.
@@ -720,6 +952,7 @@ static void create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
    jobjcr->VolSessionTime = rec->VolSessionTime;
    jobjcr->ClientId = jr->ClientId;
    attach_jcr_to_device(dev, jobjcr);
+   return jobjcr;
 }
 
 /* Dummies to replace askdir.c */
@@ -744,8 +977,8 @@ int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
       if (verbose) {
          Pmsg1(000, "create JobMedia for Job %s\n", mjcr->Job);
       }
-      mjcr->end_block = dev->block_num;
-      mjcr->end_file = dev->file;
+      mjcr->EndBlock = dev->block_num;
+      mjcr->EndFile = dev->file;
       if (!create_jobmedia_record(db, mjcr)) {
          Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"),
            dev->VolCatInfo.VolCatName, mjcr->Job);
index d1e480785958c2d922912a125f296a346a7e7bd2..1ed4cf398bf727cdd8c071eb91303e6dc4904035 100644 (file)
@@ -315,7 +315,7 @@ int rewind_dev(DEVICE *dev)
         break;
       }
    } else {
-      if (lseek(dev->fd, 0, SEEK_SET) < 0) {
+      if (lseek(dev->fd, (off_t)0, SEEK_SET) < 0) {
         dev->dev_errno = errno;
          Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
            dev->dev_name, strerror(dev->dev_errno));
@@ -336,7 +336,7 @@ eod_dev(DEVICE *dev)
    struct mtop mt_com;
    struct mtget mt_stat;
    int stat = 0;
-   int32_t pos;
+   off_t pos;
 
    Dmsg0(29, "eod_dev\n");
    if (dev->state & ST_EOT) {
@@ -346,8 +346,9 @@ eod_dev(DEVICE *dev)
    dev->block_num = dev->file = 0;
    dev->file_bytes = 0;
    if (!(dev->state & ST_TAPE)) {
-      pos = lseek(dev->fd, 0, SEEK_END);
-      if (pos > 0) {
+      pos = lseek(dev->fd, (off_t)0, SEEK_END);
+//    Dmsg1(000, "====== Seek to %lld\n", pos);
+      if (pos >= 0) {
         update_pos_dev(dev);
         dev->state |= ST_EOT;
         return 1;
@@ -404,7 +405,7 @@ int update_pos_dev(DEVICE *dev)
 #ifdef xxxx
    struct mtget mt_stat;
 #endif
-   int64_t pos;
+   off_t pos;
    int stat = 0;
 
    if (dev->fd < 0) {
@@ -418,15 +419,15 @@ int update_pos_dev(DEVICE *dev)
    if (!(dev->state & ST_TAPE)) {
       dev->file = 0;
       dev->file_bytes = 0;
-      pos = lseek(dev->fd, 0, SEEK_CUR);
+      pos = lseek(dev->fd, (off_t)0, SEEK_CUR);
       if (pos < 0) {
-         Dmsg1(200, "Seek error: ERR=%s\n", strerror(dev->dev_errno));
-        pos = 0;
+         Dmsg1(000, "Seek error: ERR=%s\n", strerror(dev->dev_errno));
         dev->dev_errno = errno;
          Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
            dev->dev_name, strerror(dev->dev_errno));
       } else {
         stat = 1;
+        dev->file_bytes = pos;
       }
       return stat;
    }
index 7f9025ae5dddac73137a972c9029f6a3bbb04845..83e794c1b24f8e8dae03190aa68cd7f8253a1847 100644 (file)
@@ -147,7 +147,7 @@ typedef struct s_device {
    char *errmsg;                      /* nicely edited error message */
    uint32_t block_num;                /* current block number base 0 */
    uint32_t file;                     /* current file number base 0 */
-   uint32_t file_bytes;               /* bytes in this file */
+   uint64_t file_bytes;               /* bytes in this file */
    uint32_t LastBlockNumWritten;      /* last block written */
    uint32_t min_block_size;           /* min block size */
    uint32_t max_block_size;           /* max block size */
index ecb5f189ea58b8c7d5471a2878d14bdc8537279b..e4cfe076b7be7a303e5c8623ec4423ef7480ba84 100644 (file)
@@ -92,8 +92,8 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
       for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
          Dmsg1(100, "create JobMedia for Job %s\n", mjcr->Job);
-        mjcr->end_block = dev->block_num;
-        mjcr->end_file = dev->file;
+        mjcr->EndBlock = dev->block_num;
+        mjcr->EndFile = dev->file;
         if (!dir_create_jobmedia_record(mjcr)) {
             Jmsg(mjcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=%s Job=%s\n"),
               dev->VolCatInfo.VolCatName, mjcr->Job);
@@ -165,8 +165,8 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       free_block(label_blk);
       for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
         /* Set new start/end positions */
-        mjcr->start_block = dev->block_num;
-        mjcr->start_file = dev->file;
+        mjcr->StartBlock = dev->block_num;
+        mjcr->StartFile = dev->file;
         mjcr->VolFirstFile = mjcr->JobFiles;
         mjcr->run_time += time(NULL) - wait_time; /* correct run time */
       }
index 1570709b0a5525ce3710d164deb3a5f8289e6693..bf7281b1982c83ec78cb5f5a20312816824be4e7 100644 (file)
@@ -37,11 +37,6 @@ static void create_volume_label_record(JCR *jcr, DEVICE *dev, DEV_RECORD *rec);
 extern char my_name[];
 extern int debug_level;
 
-char BaculaId[] =  "Bacula 0.9 mortal\n";
-unsigned int BaculaTapeVersion = 10;
-unsigned int OldCompatableBaculaTapeVersion = 9;
-
-
 /*
  * Read the volume label
  *
@@ -65,6 +60,7 @@ int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 {
    char *VolName = jcr->VolumeName;
    DEV_RECORD *record;
+   int ok = 0;
 
    Dmsg2(30, "Enter read_volume_label device=%s vol=%s\n", 
       dev_name(dev), VolName);
@@ -100,13 +96,20 @@ int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    /* Read the device label block */
    record = new_record();
    Dmsg0(90, "Big if statement in read_volume_label\n");
-   if (!read_block_from_dev(dev, block) || 
-       !read_record_from_block(block, record) ||
-       !unser_volume_label(dev, record) || 
-       strcmp(dev->VolHdr.Id, BaculaId) != 0) {
-
+   if (!read_block_from_dev(dev, block)) { 
       Mmsg(&jcr->errmsg, _("Volume on %s is not a Bacula labeled Volume, \
 because:\n   %s"), dev_name(dev), strerror_dev(dev));
+   } else if (!read_record_from_block(block, record)) {
+      Mmsg(&jcr->errmsg, _("Could not read Volume label from block.\n"));
+   } else if (!unser_volume_label(dev, record)) {
+      Mmsg(&jcr->errmsg, _("Could not unserialize Volume label: %s\n"),
+        strerror_dev(dev));
+   } else if (strcmp(dev->VolHdr.Id, BaculaId) != 0) {
+      Mmsg(&jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id);
+   } else {
+      ok = 1;
+   }
+   if (!ok) {
       free_record(record);
       empty_block(block);
       rewind_dev(dev);
@@ -118,7 +121,8 @@ because:\n   %s"), dev_name(dev), strerror_dev(dev));
    rewind_dev(dev);
 
    if (dev->VolHdr.VerNum != BaculaTapeVersion && 
-       dev->VolHdr.VerNum != OldCompatableBaculaTapeVersion) {
+       dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion1 &&  
+       dev->VolHdr.VerNum != OldCompatibleBaculaTapeVersion2) {
       Mmsg(&jcr->errmsg, _("Volume on %s has wrong Bacula version. Wanted %d got %d\n"),
         dev_name(dev), BaculaTapeVersion, dev->VolHdr.VerNum);
       return jcr->label_status = VOL_VERSION_ERROR;
@@ -191,10 +195,15 @@ int unser_volume_label(DEVICE *dev, DEV_RECORD *rec)
 
    unser_uint32(Fld(VerNum));
 
+   if (Fld(VerNum) >= 11) {
+      unser_btime(Fld(label_btime));
+      unser_btime(Fld(write_btime));
+   } else { /* old way */ 
    unser_float64(Fld(label_date));
    unser_float64(Fld(label_time));
-   unser_float64(Fld(write_date));
-   unser_float64(Fld(write_time));
+   }
+   unser_float64(Fld(write_date));    /* Unused with VerNum >= 11 */
+   unser_float64(Fld(write_time));    /* Unused with VerNum >= 11 */
 
    unser_string(Fld(VolName));
    unser_string(Fld(PrevVolName));
@@ -264,15 +273,22 @@ static void create_volume_label_record(JCR *jcr, DEVICE *dev, DEV_RECORD *rec)
 
    ser_uint32(Fld(VerNum));
 
+   if (Fld(VerNum >= 11)) {
+      ser_btime(Fld(label_btime));
+      Fld(write_btime) = get_current_btime();
+      ser_btime(Fld(write_btime));
+      Fld(write_date) = 0;
+      Fld(write_time) = 0;
+   } else {
    ser_float64(Fld(label_date));
    ser_float64(Fld(label_time));
-
    get_current_time(&dt);
    Fld(write_date) = dt.julian_day_number;
    Fld(write_time) = dt.julian_day_fraction;
+   }
 
-   ser_float64(Fld(write_date));
-   ser_float64(Fld(write_time));
+   ser_float64(Fld(write_date));   /* unused if VerNum >= 11 */
+   ser_float64(Fld(write_time));   /* unused if VerNum >= 11 */
 
    ser_string(Fld(VolName));
    ser_string(Fld(PrevVolName));
@@ -326,9 +342,15 @@ static int create_volume_label(DEVICE *dev, char *VolName)
    strcpy(dev->VolHdr.PoolType, "Backup");
 
    /* Put label time/date in header */
+   if (BaculaTapeVersion >= 11) {
+      dev->VolHdr.label_btime = get_current_btime();
+      dev->VolHdr.label_date = 0;
+      dev->VolHdr.label_time = 0;
+   } else {
    get_current_time(&dt);
    dev->VolHdr.label_date = dt.julian_day_number;
    dev->VolHdr.label_time = dt.julian_day_fraction;
+   }
 
    strcpy(dev->VolHdr.LabelProg, my_name);
    sprintf(dev->VolHdr.ProgVersion, "Ver. %s %s", VERSION, DATE);
@@ -374,7 +396,7 @@ int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *Poo
 
    block = new_block(dev);
    memset(&rec, 0, sizeof(rec));
-   rec.data = (char *) get_memory(SER_LENGTH_Volume_Label);
+   rec.data = get_memory(SER_LENGTH_Volume_Label);
    create_volume_label_record(jcr, dev, &rec);
    rec.Stream = 0;
 
@@ -427,9 +449,14 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label)
 
    ser_uint32(jcr->JobId);
 
+   if (BaculaTapeVersion >= 11) {
+      ser_btime(get_current_btime());
+      ser_float64(0);
+   } else {
    get_current_time(&dt);
    ser_float64(dt.julian_day_number);
    ser_float64(dt.julian_day_fraction);
+   }
 
    ser_string(jcr->pool_name);
    ser_string(jcr->pool_type);
@@ -444,11 +471,13 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label)
    if (label == EOS_LABEL) {
       ser_uint32(jcr->JobFiles);
       ser_uint64(jcr->JobBytes);
-      ser_uint32(jcr->start_block);
-      ser_uint32(jcr->end_block);
-      ser_uint32(jcr->start_file);
-      ser_uint32(jcr->end_file);
+      ser_uint32(jcr->StartBlock);
+      ser_uint32(jcr->EndBlock);
+      ser_uint32(jcr->StartFile);
+      ser_uint32(jcr->EndFile);
       ser_uint32(jcr->JobErrors);
+      /* Added in VerNum 11 */
+      ser_uint32(jcr->JobStatus);
    }
    ser_end(rec->data, SER_LENGTH_Session_Label);
    rec->data_len = ser_length(rec->data);
@@ -467,12 +496,12 @@ int write_session_label(JCR *jcr, DEV_BLOCK *block, int label)
    Dmsg1(90, "session_label record=%x\n", rec);
    switch (label) {
       case SOS_LABEL:
-        jcr->start_block = dev->block_num;
-        jcr->start_file  = dev->file;
+        jcr->StartBlock = dev->block_num;
+        jcr->StartFile  = dev->file;
         break;
       case EOS_LABEL:
-        jcr->end_block = dev->block_num;
-        jcr->end_file = dev->file;
+        jcr->EndBlock = dev->block_num;
+        jcr->EndFile = dev->file;
         break;
       default:
          Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label);
@@ -519,12 +548,13 @@ remainder=%d\n", jcr->JobId,
 
 void dump_volume_label(DEVICE *dev)
 {
-   int dbl;
+   int dbl = debug_level;
    uint32_t File;
    char *LabelType, buf[30];
    struct tm tm;
    struct date_time dt;
 
+   debug_level = 1;
    File = dev->file;
    switch (dev->VolHdr.LabelType) {
       case PRE_LABEL:
@@ -542,6 +572,8 @@ void dump_volume_label(DEVICE *dev)
       case EOS_LABEL:
          LabelType = "EOS_LABEL";
         break;
+      case EOT_LABEL:
+        goto bail_out;
       default:
         LabelType = buf;
          sprintf(buf, "Unknown %d", dev->VolHdr.LabelType);
@@ -549,8 +581,6 @@ void dump_volume_label(DEVICE *dev)
    }
              
    
-   dbl = debug_level;
-   debug_level = 1;
    Pmsg11(-1, "\nVolume Label:\n\
 Id                : %s\
 VerNo             : %d\n\
@@ -570,12 +600,20 @@ HostName          : %s\n\
             dev->VolHdr.PoolName, dev->VolHdr.MediaType, 
             dev->VolHdr.PoolType, dev->VolHdr.HostName);
 
+   if (dev->VolHdr.VerNum >= 11) {
+      char dt[50];
+      bstrftime(dt, sizeof(dt), (time_t)dev->VolHdr.label_btime);
+      Pmsg1(-1, "Date label written: %s\n", dt);
+   } else {
    dt.julian_day_number   = dev->VolHdr.label_date;
    dt.julian_day_fraction = dev->VolHdr.label_time;
    tm_decode(&dt, &tm);
    Pmsg5(-1, "\
 Date label written: %04d-%02d-%02d at %02d:%02d\n", 
       tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
+   }
+
+bail_out:
    debug_level = dbl;
 }
 
@@ -587,13 +625,17 @@ int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec)
    unser_string(label->Id);
    unser_uint32(label->VerNum);
    unser_uint32(label->JobId);
+   if (label->VerNum >= 11) {
+      unser_btime(label->write_btime);
+   } else {
    unser_float64(label->write_date);
+   }
    unser_float64(label->write_time);
    unser_string(label->PoolName);
    unser_string(label->PoolType);
    unser_string(label->JobName);
    unser_string(label->ClientName);
-   if (label->VerNum > 9) {
+   if (label->VerNum >= 10) {
       unser_string(label->Job);         /* Unique name of this Job */
       unser_string(label->FileSetName);
       unser_uint32(label->JobType);
@@ -602,11 +644,16 @@ int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec)
    if (rec->FileIndex == EOS_LABEL) {
       unser_uint32(label->JobFiles);
       unser_uint64(label->JobBytes);
-      unser_uint32(label->start_block);
-      unser_uint32(label->end_block);
-      unser_uint32(label->start_file);
-      unser_uint32(label->end_file);
+      unser_uint32(label->StartBlock);
+      unser_uint32(label->EndBlock);
+      unser_uint32(label->StartFile);
+      unser_uint32(label->EndFile);
       unser_uint32(label->JobErrors);
+      if (label->VerNum >= 11) {
+        unser_uint32(label->JobStatus);
+      } else {
+        label->JobStatus = JS_Terminated; /* kludge */
+      }
    }     
    return 1;
 }
@@ -620,18 +667,18 @@ static void dump_session_label(DEV_RECORD *rec, char *type)
    SESSION_LABEL label;
    char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], ec6[30], ec7[30];
 
-
    unser_session_label(&label, rec);
    dbl = debug_level;
    debug_level = 1;
-   Pmsg6(-1, "\n%s Record:\n\
+   Pmsg7(-1, "\n%s Record:\n\
 JobId             : %d\n\
+VerNum            : %d\n\
 PoolName          : %s\n\
 PoolType          : %s\n\
 JobName           : %s\n\
 ClientName        : %s\n\
-",    type, 
-      label.JobId, label.PoolName, label.PoolType,
+",    type, label.JobId, label.VerNum,
+      label.PoolName, label.PoolType,
       label.JobName, label.ClientName);
 
    if (label.VerNum >= 10) {
@@ -644,7 +691,7 @@ JobLevel          : %c\n\
    }
 
    if (rec->FileIndex == EOS_LABEL) {
-      Pmsg7(-1, "\
+      Pmsg8(-1, "\
 JobFiles          : %s\n\
 JobBytes          : %s\n\
 StartBlock        : %s\n\
@@ -652,21 +699,29 @@ EndBlock          : %s\n\
 StartFile         : %s\n\
 EndFile           : %s\n\
 JobErrors         : %s\n\
+JobStatus         : %c\n\
 ",
         edit_uint64_with_commas(label.JobFiles, ec1),
         edit_uint64_with_commas(label.JobBytes, ec2),
-        edit_uint64_with_commas(label.start_block, ec3),
-        edit_uint64_with_commas(label.end_block, ec4),
-        edit_uint64_with_commas(label.start_file, ec5),
-        edit_uint64_with_commas(label.end_file, ec6),
-        edit_uint64_with_commas(label.JobErrors, ec7));
+        edit_uint64_with_commas(label.StartBlock, ec3),
+        edit_uint64_with_commas(label.EndBlock, ec4),
+        edit_uint64_with_commas(label.StartFile, ec5),
+        edit_uint64_with_commas(label.EndFile, ec6),
+        edit_uint64_with_commas(label.JobErrors, ec7), 
+        label.JobStatus);
    }
+   if (label.VerNum >= 11) {
+      char dt[50];
+      bstrftime(dt, sizeof(dt), (time_t)label.write_btime);
+      Pmsg1(-1, _("Date written      : %s\n"), dt);
+   } else {
    dt.julian_day_number   = label.write_date;
    dt.julian_day_fraction = label.write_time;
    tm_decode(&dt, &tm);
-   Pmsg5(-1, "\
-Date written      : %04d-%02d-%02d at %02d:%02d\n"
+      Pmsg5(-1, _("\
+Date written      : %04d-%02d-%02d at %02d:%02d\n"),
       tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
+   }
 
    debug_level = dbl;
 }
@@ -680,22 +735,25 @@ void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose)
    debug_level = 1;
    switch (rec->FileIndex) {
       case PRE_LABEL:
-         type = "Fresh Volume";   
+         type = _("Fresh Volume");   
         break;
       case VOL_LABEL:
-         type = "Volume";
+         type = _("Volume");
         break;
       case SOS_LABEL:
-         type = "Begin Session";
+         type = _("Begin Session");
         break;
       case EOS_LABEL:
-         type = "End Session";
+         type = _("End Session");
         break;
       case EOM_LABEL:
-         type = "End of Media";
+         type = _("End of Media");
+        break;
+      case EOT_LABEL:
+         type = ("End of Tape");
         break;
       default:
-         type = "Unknown";
+         type = _("Unknown");
         break;
    }
    if (verbose) {
@@ -712,17 +770,38 @@ void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose)
            dump_session_label(rec, type);
            break;
         case EOM_LABEL:
-            Pmsg5(-1, "%s Record: VSessId=%d VSessTime=%d JobId=%d DataLen=%d\n",
+            Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
               type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
            break;
+        case EOT_LABEL:
+            Pmsg0(-1, _("End of physical tape.\n"));
+           break;
         default:
-            Pmsg5(-1, "%s Record: VSessId=%d VSessTime=%d JobId=%d DataLen=%d\n",
+            Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
               type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
            break;
       }
    } else {
-      Pmsg5(-1, "%s Record: VSessId=%d VSessTime=%d JobId=%d DataLen=%d\n",
+      switch (rec->FileIndex) {
+        case SOS_LABEL:
+        case EOS_LABEL:
+           SESSION_LABEL label;
+           unser_session_label(&label, rec);
+            Pmsg6(-1, "%s Record: SessId=%d SessTime=%d JobId=%d Level=%c \
+Type=%c\n",
+              type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, 
+              label.JobLevel, label.JobType);
+           break;
+        case EOM_LABEL:
+        case PRE_LABEL:
+        case VOL_LABEL:
+        default:
+            Pmsg5(-1, "%s Record: SessId=%d SessTime=%d JobId=%d DataLen=%d\n",
         type, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
+           break;
+        case EOT_LABEL:
+           break;
+      }
    }
    debug_level = dbl;
 }
index 4720fce987206b1abad5d478a7bea1728ede3fa5..90f508be80764801a10a190cd396213477973997 100644 (file)
@@ -56,13 +56,24 @@ int read_records(JCR *jcr,  DEVICE *dev,
       if (!read_block_from_device(dev, block)) {
          Dmsg0(20, "!read_record()\n");
         if (dev->state & ST_EOT) {
-           DEV_RECORD *record;
+           DEV_RECORD *record = new_record();
+
             Dmsg3(100, "EOT. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
                  block->BlockNumber, rec->remainder);
            if (!mount_cb(jcr, dev, block)) {
                Dmsg3(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
                  block->BlockNumber, rec->remainder);
               ok = FALSE;
+              /*
+               * Create EOT Label so that Media record may
+               *  be properly updated because this is the last
+               *  tape.
+               */
+              record->FileIndex = EOT_LABEL;
+              record->File = dev->file;
+              record->Block = rec->Block; /* return block last read */
+              record_cb(jcr, dev, block, record);
+              free_record(record);
               break;
            }
             Dmsg3(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
@@ -72,10 +83,10 @@ int read_records(JCR *jcr,  DEVICE *dev,
             *  and pass it off to the callback routine, then continue
             *  most likely reading the previous record.
             */
-           record = new_record();
            read_block_from_device(dev, block);
            read_record_from_block(block, record);
            get_session_record(dev, record, &sessrec);
+           record->File = dev->file;
            record_cb(jcr, dev, block, record);
            free_record(record);
            goto next_record;
@@ -105,6 +116,7 @@ next_record:
                  block->BlockNumber, rec->remainder);
            break;
         }
+        rec->File = dev->file;
          Dmsg3(10, "read-OK. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
                  block->BlockNumber, rec->remainder);
         /*
@@ -157,7 +169,6 @@ next_record:
            break;                    /* read second part of record */
         }
         record_cb(jcr, dev, block, rec);
-
       }
    }
    if (verbose) {
index 34dd68c6e8871e33679053587ba9cd79614219f3..991cc7ad9c062b703a32d8c9f6729fe2dd40a9f3 100644 (file)
@@ -154,21 +154,25 @@ rem=%d remainder=%d\n",
     */
    if (rec->remainder == 0) {
       /* Require enough room to write a full header */
-      if (remlen >= RECHDR_LENGTH) {
-        ser_begin(block->bufp, RECHDR_LENGTH);
+      if (remlen >= WRITE_RECHDR_LENGTH) {
+        ser_begin(block->bufp, WRITE_RECHDR_LENGTH);
+        if (BLOCK_VER == 1) {
         ser_uint32(rec->VolSessionId);
         ser_uint32(rec->VolSessionTime);
+        } else {
+           block->VolSessionId = rec->VolSessionId;
+           block->VolSessionTime = rec->VolSessionTime;
+        }
         ser_int32(rec->FileIndex);
         ser_int32(rec->Stream);
         ser_uint32(rec->data_len);
-        ASSERT(ser_length(block->bufp) == RECHDR_LENGTH);
 
-        block->bufp += RECHDR_LENGTH;
-        block->binbuf += RECHDR_LENGTH;
-        remlen -= RECHDR_LENGTH;
+        block->bufp += WRITE_RECHDR_LENGTH;
+        block->binbuf += WRITE_RECHDR_LENGTH;
+        remlen -= WRITE_RECHDR_LENGTH;
         rec->remainder = rec->data_len;
       } else {
-        rec->remainder = rec->data_len + RECHDR_LENGTH;
+        rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH;
         sm_check(__FILE__, __LINE__, False);
         return 0;
       }
@@ -188,9 +192,14 @@ rem=%d remainder=%d\n",
        * of a previous partially written record, we store the
        * Stream as -Stream in the record header.
        */
-      ser_begin(block->bufp, RECHDR_LENGTH);
+      ser_begin(block->bufp, WRITE_RECHDR_LENGTH);
+      if (BLOCK_VER == 1) {
       ser_uint32(rec->VolSessionId);
       ser_uint32(rec->VolSessionTime);
+      } else {
+        block->VolSessionId = rec->VolSessionId;
+        block->VolSessionTime = rec->VolSessionTime;
+      }
       ser_int32(rec->FileIndex);
       if (rec->remainder > rec->data_len) {
         ser_int32(rec->Stream);      /* normal full header */
@@ -200,14 +209,13 @@ rem=%d remainder=%d\n",
         ser_int32(-rec->Stream);     /* mark this as a continuation record */
         ser_uint32(rec->remainder);  /* bytes to do */
       }
-      ASSERT(ser_length(block->bufp) == RECHDR_LENGTH);
 
       /* Require enough room to write a full header */
-      ASSERT(remlen >= RECHDR_LENGTH);
+      ASSERT(remlen >= WRITE_RECHDR_LENGTH);
 
-      block->bufp += RECHDR_LENGTH;
-      block->binbuf += RECHDR_LENGTH;
-      remlen -= RECHDR_LENGTH;
+      block->bufp += WRITE_RECHDR_LENGTH;
+      block->binbuf += WRITE_RECHDR_LENGTH;
+      remlen -= WRITE_RECHDR_LENGTH;
    }
    if (remlen == 0) {
       sm_check(__FILE__, __LINE__, False);
@@ -269,8 +277,8 @@ int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
 
    remlen = block->buf_len - block->binbuf;
    if (rec->remainder == 0) {
-      if (remlen >= RECHDR_LENGTH) {
-        remlen -= RECHDR_LENGTH;
+      if (remlen >= WRITE_RECHDR_LENGTH) {
+        remlen -= WRITE_RECHDR_LENGTH;
         rec->remainder = rec->data_len;
       } else {
         return 0;
@@ -302,8 +310,10 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
    int32_t  FileIndex;
    int32_t  Stream;
    uint32_t data_bytes;
+   uint32_t rhl;
 
    remlen = block->binbuf;
+   rec->Block = block->BlockNumber;
 
    /* Clear state flags */
    rec->state = 0;
@@ -312,21 +322,32 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
     * Get the header. There is always a full header,
     * otherwise we find it in the next block.
     */
-   if (remlen >= RECHDR_LENGTH) {
-      Dmsg3(90, "read_record_block: remlen=%d data_len=%d rem=%d\n", 
-           remlen, rec->data_len, rec->remainder);
+   Dmsg3(100, "Block=%d Ver=%d size=%u\n", block->BlockNumber, block->BlockVer,
+        block->block_len);
+   if (block->BlockVer == 1) {
+      rhl = RECHDR1_LENGTH;
+   } else {
+      rhl = RECHDR2_LENGTH;
+   }
+   if (remlen >= rhl) {
+      Dmsg4(90, "Enter read_record_block: remlen=%d data_len=%d rem=%d blkver=%d\n", 
+           remlen, rec->data_len, rec->remainder, block->BlockVer);
 
-      unser_begin(block->bufp, RECHDR_LENGTH);
+      unser_begin(block->bufp, WRITE_RECHDR_LENGTH);
+      if (block->BlockVer == 1) {
       unser_uint32(VolSessionId);
       unser_uint32(VolSessionTime);
+      } else {
+        VolSessionId = block->VolSessionId;
+        VolSessionTime = block->VolSessionTime;
+      }
       unser_int32(FileIndex);
       unser_int32(Stream);
       unser_uint32(data_bytes);
 
-      ASSERT(unser_length(block->bufp) == RECHDR_LENGTH);
-      block->bufp += RECHDR_LENGTH;
-      block->binbuf -= RECHDR_LENGTH;
-      remlen -= RECHDR_LENGTH;
+      block->bufp += rhl;
+      block->binbuf -= rhl;
+      remlen -= rhl;
 
       /* If we are looking for more (remainder!=0), we reject anything
        *  where the VolSessionId and VolSessionTime don't agree
@@ -359,7 +380,7 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
       rec->VolSessionTime = VolSessionTime;
       rec->FileIndex = FileIndex;
 
-      Dmsg6(90, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%d\n\
+      Dmsg6(100, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%u\n\
 remlen=%d data_len=%d\n",
         FI_to_ascii(rec->FileIndex), rec->VolSessionId, 
         stream_to_ascii(rec->Stream), data_bytes, remlen, rec->data_len);
index 601e9ee590ab075abc8f50335eb58c37270614bd..2f300b1e6eac93164900a9854d1ccf52dbeb1aec 100644 (file)
 #define VOL_LABEL_ERROR   7               /* Bad label type */
 
 
-/* Length of Record Header (5 * 4 bytes) */
-#define RECHDR_LENGTH 20
+/*  See block.h for RECHDR_LENGTH */
 
 /*
  * This is the Media structure for a record header.
  *  NB: when it is written it is serialized.
- */
-typedef struct s_record_hdr {
+
    uint32_t VolSessionId;
    uint32_t VolSessionTime;
+
+ * The above 8 bytes are only written in a BB01 block, BB02
+ *  and later blocks contain these values in the block header
+ *  rather than the record header.
+
    int32_t  FileIndex;
    int32_t  Stream;
    uint32_t data_len;
-} RECORD_HDR;
+
+ */
 
 /* Record state bit definitions */
 #define REC_NO_HEADER        0x01     /* No header read */
@@ -85,7 +89,7 @@ typedef struct s_dev_rec {
    uint32_t data_len;                 /* current record length */
    uint32_t remainder;                /* remaining bytes to read/write */
    uint32_t state;                    /* state bits */
-   uint8_t  ser_buf[RECHDR_LENGTH];   /* serialized record header goes here */
+   uint8_t  ser_buf[WRITE_RECHDR_LENGTH];   /* serialized record header goes here */
    POOLMEM *data;                     /* Record data. This MUST be a memory pool item */
 } DEV_RECORD;
 
@@ -100,11 +104,15 @@ typedef struct s_dev_rec {
 #define EOM_LABEL   -3                /* Writen at end of tape */        
 #define SOS_LABEL   -4                /* Start of Session */
 #define EOS_LABEL   -5                /* End of Session */
+#define EOT_LABEL   -6                /* End of physical tape (2 eofs) */
 
 /* 
- *   Volume Label Record
+ *   Volume Label Record.  This is the in-memory definition. The
+ *     tape definition is defined in the serialization code itself
+ *     ser_volume_label() and unser_volume_label() and is slightly different.
  */
+
 struct Volume_Label {
   /*  
    * The first items in this structure are saved
@@ -121,8 +129,15 @@ struct Volume_Label {
 
   uint32_t VerNum;                    /* Label version number */
 
+  /* VerNum <= 10 */
   float64_t label_date;               /* Date tape labeled */
   float64_t label_time;               /* Time tape labeled */
+
+  /* VerNum >= 11 */
+  btime_t   label_btime;              /* tdate tape labeled */
+  btime_t   write_btime;              /* tdate tape written */
+
+  /* Unused with VerNum >= 11 */
   float64_t write_date;               /* Date this label written */
   float64_t write_time;               /* Time this label written */
 
@@ -155,7 +170,13 @@ struct Session_Label {
   uint32_t JobId;                     /* Job id */
   uint32_t VolumeIndex;               /* Sequence no of volume for this job */
 
+  /* VerNum >= 11 */
+  btime_t   write_btime;              /* Tdate this label written */
+
+  /* VerNum < 11 */
   float64_t write_date;               /* Date this label written */
+
+  /* Unused VerNum >= 11 */
   float64_t write_time;               /* Time this label written */
 
   char PoolName[MAX_NAME_LENGTH];     /* Pool name */
@@ -169,11 +190,12 @@ struct Session_Label {
   /* The remainder are part of EOS label only */
   uint32_t JobFiles;
   uint64_t JobBytes;
-  uint32_t start_block;
-  uint32_t end_block;
-  uint32_t start_file;
-  uint32_t end_file;
+  uint32_t StartBlock;
+  uint32_t EndBlock;
+  uint32_t StartFile;
+  uint32_t EndFile;
   uint32_t JobErrors;
+  uint32_t JobStatus;                 /* Job status */
 
 };
 typedef struct Session_Label SESSION_LABEL;
index e566b7bb3c9205d6489fb03e9d15ed9449bb1133..c2761e8a41f126c9af10469dace2fc10532b080a 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.26"
 #define VSTRING "1"
-#define DATE    "25 September 2002"
-#define LSMDATE "25Sep02"
+#define DATE    "4 October 2002"
+#define LSMDATE "04Oct02"
 
 /* Debug flags */
 #define DEBUG 1