]> git.sur5r.net Git - bacula/bacula/commitdiff
Make bls read multi-job file
authorKern Sibbald <kern@sibbald.com>
Thu, 22 Aug 2002 17:12:31 +0000 (17:12 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 22 Aug 2002 17:12:31 +0000 (17:12 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@115 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/stored/bls.c
bacula/src/stored/record.c
bacula/src/stored/record.h

index 3e405c6fd32090a8a223ac0229d9a8d434d9f175..94086f6057c588972ffb3ffcf5a92d6ab65c8ddc 100644 (file)
@@ -73,6 +73,32 @@ static void usage()
    exit(1);
 }
 
+static char *rec_state_to_str(DEV_RECORD *rec)
+{
+   static char buf[200]; 
+   buf[0] = 0;
+   if (rec->state & REC_NO_HEADER) {
+      strcat(buf, "Nohdr,");
+   }
+   if (rec->state & REC_PARTIAL_RECORD) {
+      strcat(buf, "partial,");
+   }
+   if (rec->state & REC_BLOCK_EMPTY) {
+      strcat(buf, "empty,");
+   }
+   if (rec->state & REC_NO_MATCH) {
+      strcat(buf, "Nomatch,");
+   }
+   if (rec->state & REC_CONTINUATION) {
+      strcat(buf, "cont,");
+   }
+   if (buf[0]) {
+      buf[strlen(buf)-1] = 0;
+   }
+   return buf;
+}
+
+
 
 int main (int argc, char *argv[])
 {
@@ -433,6 +459,8 @@ static void do_ls(char *infname)
    struct stat statp;
    int type;
    long record_file_index;
+   uint32_t num_files = 0;
+   int record;
 
    if (dump_label) {
       dump_volume_label(dev);
@@ -451,7 +479,7 @@ Warning, this Volume is a continuation of Volume %s\n",
    for ( ;; ) {
       SESSION_LABEL sessrec;
 
-      if (!read_record(dev, block, rec)) {
+      if (!read_block_from_device(dev, block)) {
          Dmsg0(20, "!read_record()\n");
         if (dev->state & ST_EOT) {
            if (!mount_next_volume(infname)) {
@@ -471,99 +499,158 @@ Warning, this Volume is a continuation of Volume %s\n",
         display_error_status();
         break;
       }
-
-      if (debug_level >= 30) {
-         Dmsg4(30, "VolSId=%ld FI=%s Strm=%s Size=%ld\n", rec->VolSessionId,
-              FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream), 
-              rec->data_len);
-      }
-
-
-      /*  
-       * Check for End of File record (all zeros)
-       *    NOTE: this no longer exists
-       */
-      if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
-         Emsg0(M_ERROR_TERM, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n");
+      if (verbose) {
+         Dmsg2(10, "Block: %d blen=%d\n", block->BlockNumber, block->block_len);
       }
 
-      /* 
-       * Check for Start or End of Session Record 
-       *
-       */
-      if (rec->FileIndex < 0) {
-        char *rtype;
-        memset(&sessrec, 0, sizeof(sessrec));
-        switch (rec->FileIndex) {
-           case PRE_LABEL:
-               rtype = "Fresh Volume Label";   
-              break;
-           case VOL_LABEL:
-               rtype = "Volume Label";
-              unser_volume_label(dev, rec);
-              break;
-           case SOS_LABEL:
-               rtype = "Begin Session";
-              unser_session_label(&sessrec, rec);
+      record = 0;
+      for ( ;; ) {
+        if (!read_record_from_block(block, rec)) {
+           if (rec->state & REC_NO_HEADER) {
+               Dmsg2(30, "!read,nohdr-break. stat=%s blk=%d\n", rec_state_to_str(rec), 
+                 block->BlockNumber);
               break;
-           case EOS_LABEL:
-               rtype = "End Session";
-              break;
-           case EOM_LABEL:
-               rtype = "End of Media";
-              break;
-           default:
-               rtype = "Unknown";
+           }
+           if (rec->state & REC_NO_MATCH) {
+               Dmsg2(30, "!read,nomatch-break. stat=%s blk=%d\n", rec_state_to_str(rec), 
+                 block->BlockNumber);
               break;
+           }
+        }
+        /*
+         * At this point, we have at least a record header.
+         *  Now decide if we want this record or not, but remember
+         *  before accessing the record, we may need to read again to
+         *  get all the data.
+         */
+        record++;
+        if (verbose) {
+            Dmsg6(30, "recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record,
+              rec_state_to_str(rec), block->BlockNumber,
+              rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
         }
-        if (debug_level > 0) {
-            printf("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
-              rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
+        if (debug_level >= 30) {
+            Dmsg4(30, "VolSId=%ld FI=%s Strm=%s Size=%ld\n", rec->VolSessionId,
+                 FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream), 
+                 rec->data_len);
         }
 
-         Dmsg1(40, "Got label = %d\n", rec->FileIndex);
-        if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
-            Dmsg0(40, "Get EOM LABEL\n");
-           break;                         /* yes, get out */
+        /*  
+         * Check for End of File record (all zeros)
+         *    NOTE: this no longer exists
+         */
+        if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
+            Emsg0(M_ERROR_TERM, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n");
         }
-        continue;                         /* ignore other labels */
-      } /* end if label record */
-
-      /* 
-       * Apply BSR filter
-       */
-      if (bsr && !match_bsr(bsr, rec, &dev->VolHdr, &sessrec)) {
-        continue;
-      }
 
-      /* File Attributes stream */
-      if (rec->Stream == STREAM_UNIX_ATTRIBUTES) {
-        char *ap, *fp;
-         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);
+        /* 
+         * Check for Start or End of Session Record 
+         *
+         */
+        if (rec->FileIndex < 0) {
+           char *rtype;
+           memset(&sessrec, 0, sizeof(sessrec));
+           switch (rec->FileIndex) {
+              case PRE_LABEL:
+                  rtype = "Fresh Volume Label";   
+                 break;
+              case VOL_LABEL:
+                  rtype = "Volume Label";
+                 unser_volume_label(dev, rec);
+                 break;
+              case SOS_LABEL:
+                  rtype = "Begin Session";
+                 unser_session_label(&sessrec, rec);
+                 break;
+              case EOS_LABEL:
+                  rtype = "End Session";
+                 break;
+              case EOM_LABEL:
+                  rtype = "End of Media";
+                 break;
+              default:
+                  rtype = "Unknown";
+                 break;
+           }
+           if (debug_level > 0) {
+               printf("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
+                 rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
+           }
+
+            Dmsg1(40, "Got label = %d\n", rec->FileIndex);
+           if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
+               Dmsg0(100, "EOM LABEL break\n");
+              rec->remainder = 0;
+              break;                         /* yes, get out */
+           }
+           rec->remainder = 0;
+           if (rec->state & REC_BLOCK_EMPTY) {
+               Dmsg0(100, "Empty, break.\n");
+               break;                 /* don't want record, read next block */
+           } else {
+               Dmsg0(100, "Label, continue.\n");
+               continue;              /* we don't want record, read next one */
+           }
+        } /* end if label record */
+
+        /* 
+         * Apply BSR filter
+         */
+        if (bsr && !match_bsr(bsr, rec, &dev->VolHdr, &sessrec)) {
+           if (verbose) {
+               Dmsg5(10, "BSR no match rec=%d block=%d SessId=%d SessTime=%d FI=%d\n",
+                 record, block->BlockNumber, rec->VolSessionId, rec->VolSessionTime, 
+                 rec->FileIndex);
+           }
+           rec->remainder = 0;
+           if (rec->state & REC_BLOCK_EMPTY) {
+               Dmsg0(100, "Empty, break.\n");
+               break;                 /* don't want record, read next block */
+           } else {
+               Dmsg0(100, "BSR reject, continue.\n");
+               continue;              /* we don't want record, read next one */
+           }
         }
-        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->state & REC_PARTIAL_RECORD) {
+            Dmsg6(10, "Partial, break. recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record,
+              rec_state_to_str(rec), block->BlockNumber,
+              rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
+           break;                    /* read second part of record */
         }
-        *fp = *ap++;                 /* terminate filename & point to attribs */
 
-        decode_stat(ap, &statp);
-        /* Skip to link name */  
-        while (*ap++ != 0)
-           ;
-        print_ls_output(fname, ap, type, &statp);
+        /* File Attributes stream */
+        if (rec->Stream == STREAM_UNIX_ATTRIBUTES) {
+           char *ap, *fp;
+            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 */
+
+           decode_stat(ap, &statp);
+           /* Skip to link name */  
+           while (*ap++ != 0)
+              ;
+           print_ls_output(fname, ap, type, &statp);
+           num_files++;
+        }
       }
    }
+   if (verbose) {
+      printf("%u files found.\n", num_files);
+   }
    return;
 }
 
index edfb265b68f16b11007a8fd488205291f60d9a6b..fb2dae35f7a6f6de63cff26d7c4fe4e42d507aac 100644 (file)
@@ -2,7 +2,7 @@
  *
  *   record.c -- tape record handling functions
  *
- *             Kern Sibbald, April MMI
+ *              Kern Sibbald, April MMI
  *
  *   Version $Id$
  *
@@ -119,7 +119,7 @@ void free_record(DEV_RECORD *rec)
  *   if necessary, handle getting a new Volume
  *
  *  Returns: 0 on failure
- *          1 on success
+ *           1 on success
  */
 int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record)
 {
@@ -127,15 +127,15 @@ int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record)
 
    while (!read_record_from_block(block, record)) {
       Dmsg2(90, "!read_record_from_block data_len=%d rem=%d\n", record->data_len,
-               record->remainder);
+                record->remainder);
       if (!read_block_from_dev(dev, block)) {
          Dmsg0(200, "===== Got read block I/O error ======\n");
-        return 0;
+         return 0;
       }
    }
    Dmsg4(90, "read_record FI=%s SessId=%d Strm=%s len=%d\n",
-             FI_to_ascii(record->FileIndex), record->VolSessionId, 
-             stream_to_ascii(record->Stream), record->data_len);
+              FI_to_ascii(record->FileIndex), record->VolSessionId, 
+              stream_to_ascii(record->Stream), record->data_len);
    record->File = dev->file;
    record->Block = dev->block_num;
    return 1;
@@ -146,7 +146,7 @@ int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record)
  * Write a Record to the block
  *
  *  Returns: 0 on failure (none or partially written)
- *          1 on success (all bytes written)
+ *           1 on success (all bytes written)
  *
  *  and remainder returned in packet.
  *
@@ -181,22 +181,22 @@ 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);
-        ser_uint32(rec->VolSessionId);
-        ser_uint32(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;
-        rec->remainder = rec->data_len;
+         ser_begin(block->bufp, RECHDR_LENGTH);
+         ser_uint32(rec->VolSessionId);
+         ser_uint32(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;
+         rec->remainder = rec->data_len;
       } else {
-        rec->remainder = rec->data_len + RECHDR_LENGTH;
-        sm_check(__FILE__, __LINE__, False);
-        return 0;
+         rec->remainder = rec->data_len + RECHDR_LENGTH;
+         sm_check(__FILE__, __LINE__, False);
+         return 0;
       }
    } else {
       /* 
@@ -219,12 +219,12 @@ rem=%d remainder=%d\n",
       ser_uint32(rec->VolSessionTime);
       ser_int32(rec->FileIndex);
       if (rec->remainder > rec->data_len) {
-        ser_int32(rec->Stream);      /* normal full header */
-        ser_uint32(rec->data_len);
-        rec->remainder = rec->data_len; /* must still do data record */
+         ser_int32(rec->Stream);      /* normal full header */
+         ser_uint32(rec->data_len);
+         rec->remainder = rec->data_len; /* must still do data record */
       } else {
-        ser_int32(-rec->Stream);     /* mark this as a continuation record */
-        ser_uint32(rec->remainder);  /* bytes to do */
+         ser_int32(-rec->Stream);     /* mark this as a continuation record */
+         ser_uint32(rec->remainder);  /* bytes to do */
       }
       ASSERT(ser_length(block->bufp) == RECHDR_LENGTH);
 
@@ -237,7 +237,7 @@ rem=%d remainder=%d\n",
    }
    if (remlen == 0) {
       sm_check(__FILE__, __LINE__, False);
-      return 0;                      /* partial transfer */
+      return 0;                       /* partial transfer */
    }
 
    /*
@@ -248,36 +248,36 @@ rem=%d remainder=%d\n",
    if (rec->remainder > 0) {
       /* Write as much of data as possible */
       if (remlen >= rec->remainder) {
-        memcpy(block->bufp, rec->data+rec->data_len-rec->remainder,
-               rec->remainder);
-        block->bufp += rec->remainder;
-        block->binbuf += rec->remainder;
+         memcpy(block->bufp, rec->data+rec->data_len-rec->remainder,
+                rec->remainder);
+         block->bufp += rec->remainder;
+         block->binbuf += rec->remainder;
       } else {
-        memcpy(block->bufp, rec->data+rec->data_len-rec->remainder, 
-               remlen);
-        if (!sm_check_rtn(__FILE__, __LINE__, False)) {
-           /* We damaged a buffer */
+         memcpy(block->bufp, rec->data+rec->data_len-rec->remainder, 
+                remlen);
+         if (!sm_check_rtn(__FILE__, __LINE__, False)) {
+            /* We damaged a buffer */
             Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n\
 rem=%d remainder=%d\n",
-              FI_to_ascii(rec->FileIndex), rec->VolSessionId, 
-              stream_to_ascii(rec->Stream), rec->data_len,
-              remlen, rec->remainder);
+               FI_to_ascii(rec->FileIndex), rec->VolSessionId, 
+               stream_to_ascii(rec->Stream), rec->data_len,
+               remlen, rec->remainder);
             Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n",
-              block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf,
-              remlen);
+               block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf,
+               remlen);
             Dmsg2(0, "Damaged block: buf=%x binbuffrombuf=%d \n",
-              block->buf, block->bufp-block->buf);
+               block->buf, block->bufp-block->buf);
 
                Emsg0(M_ABORT, 0, "Damaged buffer\n");
-        }
+         }
 
-        block->bufp += remlen;
-        block->binbuf += remlen;
-        rec->remainder -= remlen;
-        return 0;                    /* did partial transfer */
+         block->bufp += remlen;
+         block->binbuf += remlen;
+         rec->remainder -= remlen;
+         return 0;                    /* did partial transfer */
       }
    }
-   rec->remainder = 0;               /* did whole transfer */
+   rec->remainder = 0;                /* did whole transfer */
    sm_check(__FILE__, __LINE__, False);
    return 1;
 }
@@ -286,7 +286,7 @@ rem=%d remainder=%d\n",
 /*
  * Read a Record from the block
  *  Returns: 0 on failure
- *          1 on success
+ *           1 on success
  */
 int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
 {
@@ -300,13 +300,16 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
 
    remlen = block->binbuf;
 
+   /* Clear state flags */
+   rec->state = 0;
+
    /* 
     * 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);
+            remlen, rec->data_len, rec->remainder);
 
       unser_begin(block->bufp, RECHDR_LENGTH);
       unser_uint32(VolSessionId);
@@ -324,20 +327,22 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
        * if Stream is negative, it means that this is a continuation
        * of a previous partially written record.
        */
-      if (Stream < 0) {              /* continuation record? */
+      if (Stream < 0) {               /* continuation record? */
          Dmsg1(500, "Got negative Stream => continuation. remainder=%d\n", 
-           rec->remainder);
+            rec->remainder);
+         rec->state |= REC_CONTINUATION;
          if (!rec->remainder) {       /* if we didn't read previously */
-           rec->data_len = 0;        /* return data as if no continuation */
-        } else if (rec->VolSessionId != VolSessionId || 
-                   rec->VolSessionTime != VolSessionTime ||
-                   rec->Stream != -Stream) {
-           return 0;                 /* This is from some other Session */
-        }
-        rec->Stream = -Stream;       /* set correct Stream */
-      } else {                       /* Regular record */
-        rec->Stream = Stream;
-        rec->data_len = 0;           /* transfer to beginning of data */
+            rec->data_len = 0;        /* return data as if no continuation */
+         } else if (rec->VolSessionId != VolSessionId || 
+                    rec->VolSessionTime != VolSessionTime ||
+                    rec->Stream != -Stream) {
+            rec->state |= REC_NO_MATCH;
+            return 0;                 /* This is from some other Session */
+         }
+         rec->Stream = -Stream;       /* set correct Stream */
+      } else {                        /* Regular record */
+         rec->Stream = Stream;
+         rec->data_len = 0;           /* transfer to beginning of data */
       }
       rec->VolSessionId = VolSessionId;
       rec->VolSessionTime = VolSessionTime;
@@ -345,8 +350,8 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
 
       Dmsg6(90, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%d\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);
+         FI_to_ascii(rec->FileIndex), rec->VolSessionId, 
+         stream_to_ascii(rec->Stream), data_bytes, remlen, rec->data_len);
    } else {
       /*    
        * No more records in this block because the number   
@@ -358,13 +363,14 @@ remlen=%d data_len=%d\n",
        */
       Dmsg0(90, "read_record_block: nothing\n");
       if (!rec->remainder) {
-        rec->remainder = 1;          /* set to expect continuation */
-        rec->data_len = 0;           /* no data transferred */
+         rec->remainder = 1;          /* set to expect continuation */
+         rec->data_len = 0;           /* no data transferred */
       }
+      rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
       return 0;
    }
 
-   ASSERT(data_bytes < MAX_BLOCK_LENGTH);      /* temp sanity check */
+   ASSERT(data_bytes < MAX_BLOCK_LENGTH);       /* temp sanity check */
 
    rec->data = check_pool_memory_size(rec->data, rec->data_len+data_bytes);
    
@@ -388,13 +394,15 @@ remlen=%d data_len=%d\n",
       block->bufp += remlen;
       block->binbuf -= remlen;
       rec->data_len += remlen;
-      rec->remainder = 1;            /* partial record transferred */
+      rec->remainder = 1;             /* partial record transferred */
       Dmsg1(90, "read_record_block: partial xfered=%d\n", rec->data_len);
+      rec->state |= (REC_PARTIAL_RECORD | REC_BLOCK_EMPTY);
+      /********FIXME********* this should return 1 */
       return 0;
    }
    rec->remainder = 0;
    Dmsg4(90, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n",
       FI_to_ascii(rec->FileIndex), rec->VolSessionId, 
       stream_to_ascii(rec->Stream), rec->data_len);
-   return 1;                         /* transferred full record */
+   return 1;                          /* transferred full record */
 }
index 4e8919b3b7c92585c8c9000af5ad13103c6f3cfe..fe6f41cea1505a8c16d754059ee021038dd64d5c 100644 (file)
@@ -55,6 +55,12 @@ typedef struct s_record_hdr {
    uint32_t data_len;
 } RECORD_HDR;
 
+#define REC_NO_HEADER        0x01     /* No header read */
+#define REC_PARTIAL_RECORD   0x02     /* returning partial record */
+#define REC_BLOCK_EMPTY      0x04     /* not enough data in block */
+#define REC_NO_MATCH         0x08     /* No match on continuation data */
+#define REC_CONTINUATION     0x10     /* Continuation record found */
+
 /*
  * DEV_RECORD for reading and writing records.
  * It consists of a Record Header, and the Record Data
@@ -74,6 +80,7 @@ typedef struct s_dev_rec {
    int32_t  Stream;                   /* stream number */
    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 */
    POOLMEM *data;                     /* Record data. This MUST be a memory pool item */
 } DEV_RECORD;