]> git.sur5r.net Git - bacula/bacula/commitdiff
More SD tools cleanup
authorKern Sibbald <kern@sibbald.com>
Thu, 5 Sep 2002 13:14:26 +0000 (13:14 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 5 Sep 2002 13:14:26 +0000 (13:14 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@149 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/stored/Makefile.in
bacula/src/stored/acquire.c
bacula/src/stored/append.c
bacula/src/stored/bextract.c
bacula/src/stored/bls.c
bacula/src/stored/bscan.c
bacula/src/stored/protos.h
bacula/src/stored/read.c
bacula/src/stored/read_record.c [new file with mode: 0644]

index c9af692fba47cb2be8cdb474f0444689130411a4..330dd0211ed94a7780f2b8be86116dcc6fc7f462 100644 (file)
@@ -42,14 +42,16 @@ TAPEOBJS = btape.o block.o dev.o device.o askdir.o label.o \
           acquire.o mount.o record.o stored_conf.o 
 
 BLSOBJS = bls.o block.o device.o dev.o label.o match_bsr.o \
-         acquire.o mount.o parse_bsr.o record.o butil.o
+         acquire.o mount.o parse_bsr.o record.o butil.o \
+         read_record.o 
 
 BEXTOBJS = bextract.o block.o device.o dev.o label.o record.o \
-          acquire.o mount.o match_bsr.o parse_bsr.o butil.o
+          acquire.o mount.o match_bsr.o parse_bsr.o butil.o \
+          read_record.o
 
 SCNOBJS = bscan.o block.o device.o dev.o label.o \
          acquire.o mount.o record.o match_bsr.o parse_bsr.o \
-         butil.o 
+         butil.o read_record.o
 
 
 
index cea55c1cdeea29fa26319b4e8f08965d698e75fe..65aefaa607193bafe153620ff21eade489ec0755 100644 (file)
@@ -142,7 +142,7 @@ int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
  *  the device remains open.
  *
  */
-int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+int release_device(JCR *jcr, DEVICE *dev)
 {
    P(dev->mutex);
    Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk");
index 225b9cf86e06fda4863c743ccc9c071df5f6ac6d..a9152b9380c4bf1105b22da46ef483416f698ee9 100644 (file)
@@ -231,7 +231,7 @@ int do_append_data(JCR *jcr)
    }
 
    /* Release the device */
-   if (!release_device(jcr, dev, block)) {
+   if (!release_device(jcr, dev)) {
       Pmsg0(000, "Error in release_device\n");
       ok = FALSE;
    }
index 7df654bc1ec08478d13fb8b9b5b03bc69a11473b..3d7ffa0f481d4e5f66a368d4a2230206723dc315 100644 (file)
@@ -38,20 +38,29 @@ int win32_client = 0;
 #endif
 
 
-static void do_extract(char *fname, char *prefix);
-static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
+static void do_extract(char *fname);
+static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
 
 static DEVICE *dev = NULL;
 static int ofd = -1;
-
 static JCR *jcr;
 static FF_PKT my_ff;
 static FF_PKT *ff = &my_ff;
-
 static BSR *bsr = NULL;
-
-static DEV_RECORD *rec;
 static DEV_BLOCK *block;
+static int extract = FALSE;
+static long record_file_index;
+static long total = 0;
+static POOLMEM *fname;                   /* original file name */
+static POOLMEM *ofile;                   /* output name with prefix */
+static POOLMEM *lname;                   /* link name */
+static char *where;
+static int wherelen;                     /* prefix length */
+static uint32_t num_files = 0;
+static struct stat statp;
+static uint32_t compress_buf_size = 70000;
+static POOLMEM *compress_buf;
+static int type;
 
 static void usage()
 {
@@ -139,8 +148,8 @@ int main (int argc, char *argv[])
       add_fname_to_include_list(ff, 0, "/");  /*   include everything */
    }
 
-
-   do_extract(argv[0], argv[1]);
+   where = argv[1];
+   do_extract(argv[0]);
 
    if (bsr) {
       free_bsr(bsr);
@@ -148,44 +157,8 @@ int main (int argc, char *argv[])
    return 0;
 }
 
-/*
- * Device got an error, attempt to analyse it
- */
-static void display_error_status()
+static void do_extract(char *devname)
 {
-   uint32_t status;
-
-   Emsg0(M_ERROR, 0, dev->errmsg);
-   status_dev(dev, &status);
-   Dmsg1(20, "Device status: %x\n", status);
-   if (status & MT_EOD)
-      Emsg0(M_ERROR_TERM, 0, "Unexpected End of Data\n");
-   else if (status & MT_EOT)
-      Emsg0(M_ERROR_TERM, 0, "Unexpected End of Tape\n");
-   else if (status & MT_EOF)
-      Emsg0(M_ERROR_TERM, 0, "Unexpected End of File\n");
-   else if (status & MT_DR_OPEN)
-      Emsg0(M_ERROR_TERM, 0, "Tape Door is Open\n");
-   else if (!(status & MT_ONLINE))
-      Emsg0(M_ERROR_TERM, 0, "Unexpected Tape is Off-line\n");
-   else
-      Emsg2(M_ERROR_TERM, 0, "Read error on Record Header %s: %s\n", dev_name(dev), strerror(errno));
-}
-  
-
-static void do_extract(char *devname, char *where)
-{
-   struct stat statp;
-   int extract = FALSE;
-   int type;
-   long record_file_index;
-   long total = 0;
-   POOLMEM *fname;                   /* original file name */
-   POOLMEM *ofile;                   /* output name with prefix */
-   POOLMEM *lname;                   /* link name */
-   int wherelen;                     /* prefix length */
-   SESSION_LABEL sessrec;
-   uint32_t num_files = 0;
 
    jcr = setup_jcr("bextract", devname, bsr);
    dev = setup_to_read_device(jcr);
@@ -207,287 +180,211 @@ static void do_extract(char *devname, char *where)
    ofile = get_pool_memory(PM_FNAME);
    lname = get_pool_memory(PM_FNAME);
 
-   block = new_block(dev);
 
-   rec = new_record();
-   free_pool_memory(rec->data);
-   rec->data = get_memory(70000);     /* get a big block for reading */
 
-   uint32_t compress_buf_size = 70000;
-   POOLMEM *compress_buf = get_memory(compress_buf_size);
 
-   for ( ;; ) {
-      if (!read_block_from_device(dev, block)) {
-         Dmsg1(500, "Main read record failed. rem=%d\n", rec->remainder);
-        if (dev->state & ST_EOT) {
-           DEV_RECORD *record;
-           if (!mount_next_read_volume(jcr, dev, block)) {
-              break;
-           }
-           record = new_record();
-           read_block_from_device(dev, block);
-           read_record_from_block(block, record);
-           get_session_record(dev, record, &sessrec);
-           free_record(record);
-           goto next_record;
-        }
-        if (dev->state & ST_EOF) {
-           continue;                 /* try again */
-        }
-        if (dev->state & ST_SHORT) {
-           continue;
-        }
-        display_error_status();
-      }
+   compress_buf = get_memory(compress_buf_size);
 
-next_record:
-      for (rec->state=0; !is_block_empty(rec); ) {
-        if (!read_record_from_block(block, rec)) {
-           break;
-        }
+   read_records(jcr, dev, record_cb, mount_next_read_volume);
+   /* If output file is still open, it was the last one in the
+    * archive since we just hit an end of file, so close the file. 
+    */
+   if (ofd >= 0) {
+      close(ofd);
+      set_statp(jcr, fname, ofile, lname, type, &statp);
+   }
+   release_device(jcr, dev);
 
-        if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
-            Dmsg0(40, "Get EOM LABEL\n");
-           rec->remainder = 0;
-           break;                         /* yes, get out */
-        }
+   free_pool_memory(fname);
+   free_pool_memory(ofile);
+   free_pool_memory(lname);
+   free_pool_memory(compress_buf);
+   term_dev(dev);
+   free_jcr(jcr);
+   printf("%u files restored.\n", num_files);
+   return;
+}
+
+/*
+ * Called here for each record from read_records()
+ */
+static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+{
+   if (rec->FileIndex < 0) {
+      return;                         /* we don't want labels */
+   }
 
-        /* Some sort of label? */ 
-        if (rec->FileIndex < 0) {
-           get_session_record(dev, rec, &sessrec);
-           continue;
-        } /* end if label record */
+   /* File Attributes stream */
+   if (rec->Stream == STREAM_UNIX_ATTRIBUTES) {
+      char *ap, *lp, *fp;
 
-        /* Is this the file we want? */
-        if (bsr && !match_bsr(bsr, rec, &dev->VolHdr, &sessrec)) {
-           rec->remainder = 0;
-           continue;
-        }
-        if (is_partial_record(rec)) {
-           break;
+      /* If extracting, it was from previous stream, so
+       * close the output file.
+       */
+      if (extract) {
+        if (ofd < 0) {
+            Emsg0(M_ERROR_TERM, 0, "Logic error output file should be open\n");
         }
+        close(ofd);
+        ofd = -1;
+        extract = FALSE;
+        set_statp(jcr, fname, ofile, lname, type, &statp);
+      }
 
-        /* File Attributes stream */
-        if (rec->Stream == STREAM_UNIX_ATTRIBUTES) {
-           char *ap, *lp, *fp;
+      if (sizeof_pool_memory(fname) < rec->data_len) {
+        fname = realloc_pool_memory(fname, rec->data_len + 1);
+      }
+      if (sizeof_pool_memory(ofile) < rec->data_len + wherelen + 1) {
+        ofile = realloc_pool_memory(ofile, rec->data_len + wherelen + 1);
+      }
+      if (sizeof_pool_memory(lname) < rec->data_len) {
+        lname = realloc_pool_memory(lname, rec->data_len + wherelen + 1);
+      }
+      *fname = 0;
+      *lname = 0;
+
+      /*             
+       * An Attributes record consists of:
+       *    File_index
+       *    Type   (FT_types)
+       *    Filename
+       *    Attributes
+       *    Link name (if file linked i.e. FT_LNK)
+       *
+       */
+      sscanf(rec->data, "%ld %d", &record_file_index, &type);
+      if (record_file_index != rec->FileIndex)
+         Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
+           rec->FileIndex, record_file_index);
+      ap = rec->data;
+      while (*ap++ != ' ')         /* skip record file index */
+        ;
+      while (*ap++ != ' ')         /* skip type */
+        ;
+      /* Save filename and position to attributes */
+      fp = fname;
+      while (*ap != 0) {
+        *fp++  = *ap++;
+      }
+      *fp = *ap++;                /* terminate filename & point to attribs */
 
-           /* If extracting, it was from previous stream, so
-            * close the output file.
-            */
-           if (extract) {
-              if (ofd < 0) {
-                  Emsg0(M_ERROR_TERM, 0, "Logic error output file should be open\n");
-              }
-              close(ofd);
-              ofd = -1;
-              extract = FALSE;
-              set_statp(jcr, fname, ofile, lname, type, &statp);
-           }
+      /* Skip to Link name */
+      if (type == FT_LNK || type == FT_LNKSAVED) {
+        lp = ap;
+        while (*lp++ != 0) {
+           ;
+        }
+      } else {
+         lp = "";
+      }
 
-           if (sizeof_pool_memory(fname) < rec->data_len) {
-              fname = realloc_pool_memory(fname, rec->data_len + 1);
-           }
-           if (sizeof_pool_memory(ofile) < rec->data_len + wherelen + 1) {
-              ofile = realloc_pool_memory(ofile, rec->data_len + wherelen + 1);
-           }
-           if (sizeof_pool_memory(lname) < rec->data_len) {
-              lname = realloc_pool_memory(lname, rec->data_len + wherelen + 1);
-           }
-           *fname = 0;
-           *lname = 0;
-
-           /*              
-            * An Attributes record consists of:
-            *    File_index
-            *    Type   (FT_types)
-            *    Filename
-            *    Attributes
-            *    Link name (if file linked i.e. FT_LNK)
-            *
-            */
-            sscanf(rec->data, "%ld %d", &record_file_index, &type);
-           if (record_file_index != rec->FileIndex)
-               Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
-                 rec->FileIndex, record_file_index);
-           ap = rec->data;
-            while (*ap++ != ' ')         /* skip record file index */
-              ;
-            while (*ap++ != ' ')         /* skip type */
-              ;
-           /* Save filename and position to attributes */
-           fp = fname;
-           while (*ap != 0) {
-              *fp++  = *ap++;
+        
+      if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
+
+        decode_stat(ap, &statp);
+        /*
+         * Prepend the where directory so that the
+         * files are put where the user wants.
+         *
+         * We do a little jig here to handle Win32 files with
+         * a drive letter.  
+         *   If where is null and we are running on a win32 client,
+         *      change nothing.
+         *   Otherwise, if the second character of the filename is a
+         *   colon (:), change it into a slash (/) -- this creates
+         *   a reasonable pathname on most systems.
+         */
+        if (where[0] == 0 && win32_client) {
+           strcpy(ofile, fname);
+           strcpy(lname, lp);
+        } else {
+           strcpy(ofile, where);
+            if (fname[1] == ':') {
+               fname[1] = '/';
+              strcat(ofile, fname);
+               fname[1] = ':';
+           } else {
+              strcat(ofile, fname);
            }
-           *fp = *ap++;                 /* terminate filename & point to attribs */
-
-           /* Skip to Link name */
+           /* Fixup link name */
            if (type == FT_LNK || type == FT_LNKSAVED) {
-              lp = ap;
-              while (*lp++ != 0) {
-                 ;
+               if (lp[0] == '/') {      /* if absolute path */
+                 strcpy(lname, where);
+              }       
+               /* ***FIXME**** we shouldn't have links on Windoz */
+               if (lp[1] == ':') {
+                  lp[1] = '/';
+                 strcat(lname, lp);
+                  lp[1] = ':';
+              } else {
+                 strcat(lname, lp);
               }
-           } else {
-               lp = "";
            }
+        }
 
-              
-           if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
-
-              decode_stat(ap, &statp);
-              /*
-               * Prepend the where directory so that the
-               * files are put where the user wants.
-               *
-               * We do a little jig here to handle Win32 files with
-               * a drive letter.  
-               *   If where is null and we are running on a win32 client,
-               *      change nothing.
-               *   Otherwise, if the second character of the filename is a
-               *   colon (:), change it into a slash (/) -- this creates
-               *   a reasonable pathname on most systems.
-               */
-              if (where[0] == 0 && win32_client) {
-                 strcpy(ofile, fname);
-                 strcpy(lname, lp);
-              } else {
-                 strcpy(ofile, where);
-                  if (fname[1] == ':') {
-                     fname[1] = '/';
-                    strcat(ofile, fname);
-                     fname[1] = ':';
-                 } else {
-                    strcat(ofile, fname);
-                 }
-                 /* Fixup link name */
-                 if (type == FT_LNK || type == FT_LNKSAVED) {
-                     if (lp[0] == '/') {      /* if absolute path */
-                       strcpy(lname, where);
-                    }       
-                     /* ***FIXME**** we shouldn't have links on Windoz */
-                     if (lp[1] == ':') {
-                        lp[1] = '/';
-                       strcat(lname, lp);
-                        lp[1] = ':';
-                    } else {
-                       strcat(lname, lp);
-                    }
-                 }
-              }
+           /*          Pmsg1(000, "Restoring: %s\n", ofile); */
 
-   /*          Pmsg1(000, "Restoring: %s\n", ofile); */
+        extract = create_file(jcr, fname, ofile, lname, type, &statp, &ofd);
+        num_files++;
 
-              extract = create_file(jcr, fname, ofile, lname, type, &statp, &ofd);
-              num_files++;
+        if (extract) {
+            print_ls_output(ofile, lname, type, &statp);   
+        }
+      }
 
-              if (extract) {
-                  print_ls_output(ofile, lname, type, &statp);   
-              }
-           }
+   /* Data stream and extracting */
+   } else if (rec->Stream == STREAM_FILE_DATA) {
+      if (extract) {
+        total += rec->data_len;
+         Dmsg2(8, "Write %ld bytes, total=%ld\n", rec->data_len, total);
+        if ((uint32_t)write(ofd, rec->data, rec->data_len) != rec->data_len) {
+            Emsg1(M_ERROR_TERM, 0, "Write error: %s\n", strerror(errno));
+        }
+      }
 
-        /* Data stream and extracting */
-        } else if (rec->Stream == STREAM_FILE_DATA) {
-           if (extract) {
-              total += rec->data_len;
-               Dmsg2(8, "Write %ld bytes, total=%ld\n", rec->data_len, total);
-              if ((uint32_t)write(ofd, rec->data, rec->data_len) != rec->data_len) {
-                  Emsg1(M_ERROR_TERM, 0, "Write error: %s\n", strerror(errno));
-              }
-           }
-    
-        } else if (rec->Stream == STREAM_GZIP_DATA) {
+   } else if (rec->Stream == STREAM_GZIP_DATA) {
 #ifdef HAVE_LIBZ
-           if (extract) {
-              uLongf compress_len;
+      if (extract) {
+        uLongf compress_len;
 
-              compress_len = compress_buf_size;
-              if (uncompress((Bytef *)compress_buf, &compress_len, 
-                    (const Bytef *)rec->data, (uLong)rec->data_len) != Z_OK) {
-                  Emsg0(M_ERROR_TERM, 0, _("Uncompression error.\n"));
-              }
+        compress_len = compress_buf_size;
+        if (uncompress((Bytef *)compress_buf, &compress_len, 
+              (const Bytef *)rec->data, (uLong)rec->data_len) != Z_OK) {
+            Emsg0(M_ERROR_TERM, 0, _("Uncompression error.\n"));
+        }
 
-               Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
-              if ((uLongf)write(ofd, compress_buf, (size_t)compress_len) != compress_len) {
-                  Pmsg0(0, "===Write error===\n");
-                  Emsg2(M_ERROR_TERM, 0, "Write error on %s: %s\n", ofile, strerror(errno));
-              }
-              total += compress_len;
-               Dmsg2(100, "Compress len=%d uncompressed=%d\n", rec->data_len,
-                 compress_len);
-           }
+         Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
+        if ((uLongf)write(ofd, compress_buf, (size_t)compress_len) != compress_len) {
+            Pmsg0(0, "===Write error===\n");
+            Emsg2(M_ERROR_TERM, 0, "Write error on %s: %s\n", ofile, strerror(errno));
+        }
+        total += compress_len;
+         Dmsg2(100, "Compress len=%d uncompressed=%d\n", rec->data_len,
+           compress_len);
+      }
 #else
-           if (extract) {
-               Emsg0(M_ERROR_TERM, 0, "GZIP data stream found, but GZIP not configured!\n");
-           }
+      if (extract) {
+         Emsg0(M_ERROR_TERM, 0, "GZIP data stream found, but GZIP not configured!\n");
+      }
 #endif
 
 
-        /* If extracting, wierd stream (not 1 or 2), close output file anyway */
-        } else if (extract) {
-           if (ofd < 0) {
-               Emsg0(M_ERROR_TERM, 0, "Logic error output file should be open\n");
-           }
-           close(ofd);
-           ofd = -1;
-           extract = FALSE;
-           set_statp(jcr, fname, ofile, lname, type, &statp);
-        } else if (rec->Stream != STREAM_MD5_SIGNATURE) {
-            Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data);
-        }
+   /* If extracting, wierd stream (not 1 or 2), close output file anyway */
+   } else if (extract) {
+      if (ofd < 0) {
+         Emsg0(M_ERROR_TERM, 0, "Logic error output file should be open\n");
       }
-   }
-
-
-   /* If output file is still open, it was the last one in the
-    * archive since we just hit an end of file, so close the file. 
-    */
-   if (ofd >= 0) {
       close(ofd);
+      ofd = -1;
+      extract = FALSE;
       set_statp(jcr, fname, ofile, lname, type, &statp);
+   } else if (rec->Stream != STREAM_MD5_SIGNATURE) {
+      Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data);
    }
-   release_device(jcr, dev, block);
-
-   free_pool_memory(fname);
-   free_pool_memory(ofile);
-   free_pool_memory(lname);
-   free_pool_memory(compress_buf);
-   term_dev(dev);
-   free_block(block);
-   free_record(rec);
-   free_jcr(jcr);
-   printf("%u files restored.\n", num_files);
-   return;
 }
 
-static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec)
-{
-   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;
-   }
-   Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
-        rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
-}
+
+
 
 /* Dummies to replace askdir.c */
 int    dir_get_volume_info(JCR *jcr) { return 1;}
index fc5eb8b8e1df7c2be7b9bf201c72351c6b42ba0e..11373023cbdd4e26b1c332dbd6e05af00532996d 100644 (file)
@@ -31,8 +31,9 @@
 static void do_blocks(char *infname);
 static void do_jobs(char *infname);
 static void do_ls(char *fname);
-static void do_close();
+static void do_close(JCR *jcr);
 static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
+static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
 
 static DEVICE *dev;
 static int default_tape = FALSE;
@@ -44,7 +45,8 @@ static DEV_RECORD *rec;
 static DEV_BLOCK *block;
 static JCR *jcr;
 static SESSION_LABEL sessrec;
-
+static uint32_t num_files = 0;
+static long record_file_index;
 
 extern char BaculaId[];
 
@@ -70,32 +72,6 @@ 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 (is_partial_record(rec)) {
-      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[])
 {
@@ -201,6 +177,16 @@ int main (int argc, char *argv[])
       }
       rec = new_record();
       block = new_block(dev);
+      /*
+       * Assume that we have already read the volume label.
+       * If on second or subsequent volume, adjust buffer pointer 
+       */
+      if (dev->VolHdr.PrevVolName[0] != 0) { /* second volume */
+         Pmsg1(0, "\n\
+Warning, this Volume is a continuation of Volume %s\n",
+               dev->VolHdr.PrevVolName);
+      }
+
       if (list_blocks) {
         do_blocks(argv[i]);
       } else if (list_jobs) {
@@ -208,7 +194,7 @@ int main (int argc, char *argv[])
       } else {
         do_ls(argv[i]);
       }
-      do_close();
+      do_close(jcr);
    }
    if (bsr) {
       free_bsr(bsr);
@@ -217,8 +203,9 @@ int main (int argc, char *argv[])
 }
 
 
-static void do_close()
+static void do_close(JCR *jcr)
 {
+   release_device(jcr, dev);
    term_dev(dev);
    free_record(rec);
    free_block(block);
@@ -226,46 +213,12 @@ static void do_close()
 }
 
 
-/*
- * Device got an error, attempt to analyse it
- */
-static void display_error_status()
-{
-   uint32_t status;
-
-   Emsg0(M_ERROR, 0, dev->errmsg);
-   status_dev(dev, &status);
-   Dmsg1(20, "Device status: %x\n", status);
-   if (status & MT_EOD)
-      Emsg0(M_ERROR_TERM, 0, "Unexpected End of Data\n");
-   else if (status & MT_EOT)
-      Emsg0(M_ERROR_TERM, 0, "Unexpected End of Tape\n");
-   else if (status & MT_EOF)
-      Emsg0(M_ERROR_TERM, 0, "Unexpected End of File\n");
-   else if (status & MT_DR_OPEN)
-      Emsg0(M_ERROR_TERM, 0, "Tape Door is Open\n");
-   else if (!(status & MT_ONLINE))
-      Emsg0(M_ERROR_TERM, 0, "Unexpected Tape is Off-line\n");
-   else
-      Emsg2(M_ERROR_TERM, 0, "Read error on Record Header %s: %s\n", dev_name(dev), strerror(errno));
-}
-
-
 /* List just block information */
 static void do_blocks(char *infname)
 {
 
    dump_volume_label(dev);
 
-   /* Assume that we have already read the volume label.
-    * If on second or subsequent volume, adjust buffer pointer 
-    */
-   if (dev->VolHdr.PrevVolName[0] != 0) { /* second volume */
-      Pmsg1(0, "\n\
-Warning, this Volume is a continuation of Volume %s\n",
-               dev->VolHdr.PrevVolName);
-   }
    if (verbose) {
       rec = new_record();
    }
@@ -295,7 +248,7 @@ Warning, this Volume is a continuation of Volume %s\n",
            Emsg0(M_INFO, 0, dev->errmsg);
            continue;
         }
-        display_error_status();
+        display_error_status(dev);
         break;
       }
 
@@ -314,230 +267,75 @@ Warning, this Volume is a continuation of Volume %s\n",
    return;
 }
 
+/*
+ * We are only looking for labels or in particula Job Session records
+ */
+static void jobs_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+{
+   if (rec->FileIndex < 0) {
+      dump_label_record(dev, rec, verbose);
+   }
+   rec->remainder = 0;
+}
+
 /* Do list job records */
 static void do_jobs(char *infname)
 {
+   read_records(jcr, dev, jobs_cb, mount_next_read_volume);
+}
 
-   /* Assume that we have already read the volume label.
-    * If on second or subsequent volume, adjust buffer pointer 
-    */
-   if (dev->VolHdr.PrevVolName[0] != 0) { /* second volume */
-      Pmsg1(0, "\n\
-Warning, this Volume is a continuation of Volume %s\n",
-               dev->VolHdr.PrevVolName);
+/* Do an ls type listing of an archive */
+static void do_ls(char *infname)
+{
+   if (dump_label) {
+      dump_volume_label(dev);
+      return;
    }
-   for ( ;; ) {
-      if (!read_block_from_device(dev, block)) {
-         Dmsg0(20, "!read_block()\n");
-        if (dev->state & ST_EOT) {
-           DEV_RECORD *record;
-           if (!mount_next_read_volume(jcr, dev, block)) {
-               printf("Got EOF on device %s\n", dev_name(dev));
-              break;
-           }
-           record = new_record();
-           read_block_from_device(dev, block);
-           read_record_from_block(block, record);
-           get_session_record(dev, record, &sessrec);
-           free_record(record);
-            printf("Volume %s mounted.\n", jcr->VolumeName);
-           continue;
-        }
-        if (dev->state & ST_EOF) {
-            Emsg1(M_INFO, 0, "Got EOF on device %s\n", dev_name(dev));
-            Dmsg0(20, "read_record got eof. try again\n");
-           continue;
-        }
-        if (dev->state & ST_SHORT) {
-            Pmsg0(000, "Got short block.\n");
-           Emsg0(M_INFO, 0, dev->errmsg);
-           continue;
-        }
-        display_error_status();
-        break;
-      }
-      while (read_record_from_block(block, rec)) {
-        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");
-        }
-
-        /* 
-         * Check for Start or End of Session Record 
-         *
-         */
-        if (rec->FileIndex < 0) {
-           dump_label_record(dev, rec, verbose);
-           continue;
-        }
-      }
-      rec->remainder = 0;
-   }
-   return;
+   read_records(jcr, dev, record_cb, mount_next_read_volume);
 }
 
-/* Do an ls type listing of an archive */
-static void do_ls(char *infname)
+/*
+ * Called here for each record from read_records()
+ */
+static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 {
    char fname[2000];
    struct stat statp;
    int type;
-   long record_file_index;
-   uint32_t num_files = 0;
-   int record;
 
-   if (dump_label) {
-      dump_volume_label(dev);
+   if (rec->FileIndex < 0) {
+      get_session_record(dev, rec, &sessrec);
       return;
    }
-
-   /* Assume that we have already read the volume label.
-    * If on second or subsequent volume, adjust buffer pointer 
-    */
-   if (dev->VolHdr.PrevVolName[0] != 0) { /* second volume */
-      Pmsg1(0, "\n\
-Warning, this Volume is a continuation of Volume %s\n",
-               dev->VolHdr.PrevVolName);
-   }
-   for ( ;; ) {
-
-      if (!read_block_from_device(dev, block)) {
-         Dmsg0(20, "!read_record()\n");
-        if (dev->state & ST_EOT) {
-           DEV_RECORD *record;
-            Dmsg3(100, "EOT. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
-                 block->BlockNumber, rec->remainder);
-           if (!mount_next_read_volume(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);
-              break;
-           }
-            Dmsg3(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
-                 block->BlockNumber, rec->remainder);
-           record = new_record();
-           read_block_from_device(dev, block);
-           read_record_from_block(block, record);
-           get_session_record(dev, record, &sessrec);
-           free_record(record);
-           goto next_record;
-        }
-        if (dev->state & ST_EOF) {
-            Emsg1(M_INFO, 0, "Got EOF on device %s\n", dev_name(dev));
-            Dmsg0(20, "read_record got eof. try again\n");
-           continue;
-        }
-        if (dev->state & ST_SHORT) {
-           Emsg0(M_INFO, 0, dev->errmsg);
-           continue;
-        }
-        display_error_status();
-        break;
+   /* 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);
       }
-      if (verbose) {
-         Dmsg2(10, "Block: %d blen=%d\n", block->BlockNumber, block->block_len);
+      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++;
       }
-
-next_record:
-      record = 0;
-      for (rec->state=0; !is_block_empty(rec); ) {
-        if (!read_record_from_block(block, rec)) {
-            Dmsg3(10, "!read-break. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
-                 block->BlockNumber, rec->remainder);
-           break;
-        }
-         Dmsg3(10, "read-OK. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
-                 block->BlockNumber, rec->remainder);
-        /*
-         * 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 >= 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);
-        }
-
-        if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
-            Dmsg0(40, "Get EOM LABEL\n");
-           rec->remainder = 0;
-           break;                         /* yes, get out */
-        }
-
-        /* Some sort of label? */ 
-        if (rec->FileIndex < 0) {
-           get_session_record(dev, rec, &sessrec);
-           continue;
-        } /* 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;
-            continue;              /* we don't want record, read next one */
-        }
-        if (is_partial_record(rec)) {
-            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 */
-        }
-
-        /* 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)
-              ;
-           if (file_is_included(&ff, fname) && !file_is_excluded(&ff, fname)) {
-              print_ls_output(fname, ap, type, &statp);
-              num_files++;
-           }
-        }
+      *fp = *ap++;                /* terminate filename & point to attribs */
+
+      decode_stat(ap, &statp);
+      /* Skip to link name */  
+      while (*ap++ != 0)
+        ;
+      if (file_is_included(&ff, fname) && !file_is_excluded(&ff, fname)) {
+        print_ls_output(fname, ap, type, &statp);
+        num_files++;
       }
    }
    if (verbose) {
index 8b86ec39c3f37483cd2206f002d9e59c15750e6d..56f83ff40b3d35ace95f977d50a7b0b5c73c52ea 100644 (file)
@@ -347,7 +347,7 @@ static void do_scan(char *devname)
       }
    }
 
-   release_device(jcr, dev, block);
+   release_device(jcr, dev);
 
    free_pool_memory(fname);
    free_pool_memory(ofile);
index 58136a523faf055b00a07e3f29944e5f7b9f7710..b55b162737357141bb179e7ed667a6763b6835ef 100644 (file)
@@ -31,7 +31,7 @@ uint32_t new_VolSessionId();
 int     acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
 int     acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
 int     ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int     release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int     release_device(JCR *jcr, DEVICE *dev);
 
 /* From askdir.c */
 int    dir_get_volume_info(JCR *jcr);
@@ -62,6 +62,7 @@ int   read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
 void print_ls_output(char *fname, char *link, int type, struct stat *statp);
 JCR *setup_jcr(char *name, char *device, BSR *bsr); 
 DEVICE *setup_to_read_device(JCR *jcr);
+void display_error_status(DEVICE *dev);
 
 
 /* From dev.c */
@@ -169,3 +170,8 @@ int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
 int    read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
 DEV_RECORD *new_record();
 void   free_record(DEV_RECORD *rec);
+
+/* From read_record.c */
+int read_records(JCR *jcr,  DEVICE *dev, 
+       void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
+       int mount_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block));
index 52cc6ad58ef13658ce67f36a96eae61a97296f70..f4fa27b31d1ac8a5d426ff1f9e74567241b2c3bc 100644 (file)
@@ -215,7 +215,7 @@ int do_read_data(JCR *jcr)
    /* Send end of data to FD */
    bnet_sig(ds, BNET_EOD);
 
-   if (!release_device(jcr, dev, block)) {
+   if (!release_device(jcr, dev)) {
       ok = FALSE;
    }
    free_pool_memory(hdr);
diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c
new file mode 100644 (file)
index 0000000..e78a2ee
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ *
+ *  This routine provides a routine that will handle all
+ *    the gory little details of reading a record from a Bacula
+ *    archive. It uses a callback to pass you each record in turn,
+ *    as well as a callback for mounting the next tape.  It takes
+ *    care of reading blocks, applying the bsr, ...
+ *
+ *   Version $Id$
+ */
+/*
+   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "stored.h"
+
+static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
+static char *rec_state_to_str(DEV_RECORD *rec);
+
+
+int read_records(JCR *jcr,  DEVICE *dev, 
+       void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
+       int mount_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block))
+{
+   DEV_BLOCK *block;
+   DEV_RECORD *rec;
+   uint32_t record, num_files = 0;
+   int verbose = FALSE;
+   int ok = TRUE;
+   SESSION_LABEL sessrec;
+
+   block = new_block(dev);
+   rec = new_record();
+   for ( ;ok; ) {
+      if (job_cancelled(jcr)) {
+        ok = FALSE;
+        break;
+      }
+      if (!read_block_from_device(dev, block)) {
+         Dmsg0(20, "!read_record()\n");
+        if (dev->state & ST_EOT) {
+           DEV_RECORD *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;
+              break;
+           }
+            Dmsg3(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
+                 block->BlockNumber, rec->remainder);
+           record = new_record();
+           read_block_from_device(dev, block);
+           read_record_from_block(block, record);
+           get_session_record(dev, record, &sessrec);
+           record_cb(jcr, dev, block, record);
+           free_record(record);
+           goto next_record;
+        }
+        if (dev->state & ST_EOF) {
+            Emsg1(M_INFO, 0, "Got EOF on device %s\n", dev_name(dev));
+            Dmsg0(20, "read_record got eof. try again\n");
+           continue;
+        }
+        if (dev->state & ST_SHORT) {
+           Emsg0(M_INFO, 0, dev->errmsg);
+           continue;
+        }
+//      display_error_status();
+        ok = FALSE;
+        break;
+      }
+      if (verbose) {
+         Dmsg2(10, "Block: %d blen=%d\n", block->BlockNumber, block->block_len);
+      }
+
+next_record:
+      record = 0;
+      for (rec->state=0; !is_block_empty(rec); ) {
+        if (!read_record_from_block(block, rec)) {
+            Dmsg3(10, "!read-break. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
+                 block->BlockNumber, rec->remainder);
+           break;
+        }
+         Dmsg3(10, "read-OK. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), 
+                 block->BlockNumber, rec->remainder);
+        /*
+         * 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 >= 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);
+        }
+
+        if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
+            Dmsg0(40, "Get EOM LABEL\n");
+           rec->remainder = 0;
+           break;                         /* yes, get out */
+        }
+
+        /* Some sort of label? */ 
+        if (rec->FileIndex < 0) {
+           get_session_record(dev, rec, &sessrec);
+           record_cb(jcr, dev, block, rec);
+           continue;
+        } /* end if label record */
+
+        /* 
+         * Apply BSR filter
+         */
+        if (jcr->bsr && !match_bsr(jcr->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;
+            continue;              /* we don't want record, read next one */
+        }
+        if (is_partial_record(rec)) {
+            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 */
+        }
+        record_cb(jcr, dev, block, rec);
+
+      }
+   }
+   if (verbose) {
+      printf("%u files found.\n", num_files);
+   }
+   free_record(rec);
+   free_block(block);
+   return ok;
+}
+
+
+static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec)
+{
+   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;
+   }
+   Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
+        rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
+}
+
+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 (is_partial_record(rec)) {
+      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;
+}
+