]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/btape.c
Add V: to bextract and bscan
[bacula/bacula] / bacula / src / stored / btape.c
index ae027642e9b67d3947de561cd0cfc7be639cdac3..fedf6e60b15f320a387f59ec9eaaae3a80fd45de 100644 (file)
@@ -60,6 +60,7 @@ static void wrcmd();
 static void rrcmd();
 static void eodcmd();
 static void fillcmd();
+static void qfillcmd();
 static void statcmd();
 static void unfillcmd();
 static int flush_block(DEV_BLOCK *block, int dump);
@@ -67,6 +68,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
 static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
 static void scan_blocks();
 static void set_volume_name(char *VolName, int volnum);
+static void rawfill_cmd();
 
 
 /* Static variables */
@@ -82,7 +84,7 @@ static uint64_t vol_size;
 static uint64_t VolBytes;
 static time_t now;
 static double kbs;
-static long file_index;
+static int32_t file_index;
 static int end_of_tape = 0;
 static uint32_t LastBlock = 0;
 static uint32_t eot_block;
@@ -107,19 +109,6 @@ static void terminate_btape(int sig);
 int get_cmd(char *prompt);
 
 
-int write_dev(DEVICE *dev, char *buf, size_t len) 
-{
-   Emsg0(M_ABORT, 0, "write_dev not implemented.\n");
-   return 0;
-}
-
-int read_dev(DEVICE *dev, char *buf, size_t len)
-{
-   Emsg0(M_ABORT, 0, "read_dev not implemented.\n");
-   return 0;
-}
-
-
 /*********************************************************************
  *
  *        Main Bacula Pool Creation Program
@@ -906,6 +895,7 @@ static void scancmd()
    int blocks, tot_blocks, tot_files;
    int block_size;
    uint64_t bytes;
+   char ec1[50];
 
 
    blocks = block_size = tot_blocks = 0;
@@ -916,6 +906,7 @@ static void scancmd()
    }
    update_pos_dev(dev);
    tot_files = dev->file;
+   Pmsg1(0, _("Starting scan at file %u\n"), dev->file);
    for (;;) {
       if ((stat = read(dev->fd, buf, sizeof(buf))) < 0) {
         clrerror_dev(dev, -1);
@@ -961,7 +952,8 @@ static void scancmd()
    }
    update_pos_dev(dev);
    tot_files = dev->file - tot_files;
-   printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes);
+   printf("Total files=%d, blocks=%d, bytes = %s\n", tot_files, tot_blocks, 
+      edit_uint64_with_commas(bytes, ec1));
 }
 
 
@@ -977,6 +969,7 @@ static void scan_blocks()
    uint32_t block_size;
    uint64_t bytes;
    DEV_BLOCK *block;
+   char ec1[50];
 
    block = new_block(dev);
    blocks = block_size = tot_blocks = 0;
@@ -1047,7 +1040,8 @@ static void scan_blocks()
 bail_out:
    free_block(block);
    tot_files = dev->file - tot_files;
-   printf("Total files=%d, blocks=%d, bytes = %" lld "\n", tot_files, tot_blocks, bytes);
+   printf("Total files=%d, blocks=%d, bytes = %s\n", tot_files, tot_blocks, 
+      edit_uint64_with_commas(bytes, ec1));
 }
 
 
@@ -1222,7 +1216,7 @@ This may take a long time -- hours! ...\n\n");
 
       /* Get out after writing 10 blocks to the second tape */
       if (BlockNumber > 10 && stop != 0) {     /* get out */
-         Pmsg0(-1, "Done writing 10 blocks to second tape.\n");
+         Pmsg0(-1, "Done writing ...\n");
         break;    
       }
    }
@@ -1281,22 +1275,24 @@ static void unfillcmd()
 
    end_of_tape = 0;
 
-   /* Close device so user can use autochanger if desired */
-   if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
-      offline_dev(dev);
-   }
-   force_close_dev(dev);
-   get_cmd(_("Mount first tape. Press enter when ready: ")); 
+   if (!simple) {
+      /* Close device so user can use autochanger if desired */
+      if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
+        offline_dev(dev);
+      }
+      force_close_dev(dev);
+      get_cmd(_("Mount first tape. Press enter when ready: ")); 
    
-   free_vol_list(jcr);
-   set_volume_name("TestVolume1", 1);
-   jcr->bsr = NULL;
-   create_vol_list(jcr);
-   close_dev(dev);
-   dev->state &= ~ST_READ;
-   if (!acquire_device_for_read(jcr, dev, block)) {
-      Pmsg1(-1, "%s", dev->errmsg);
-      return;
+      free_vol_list(jcr);
+      set_volume_name("TestVolume1", 1);
+      jcr->bsr = NULL;
+      create_vol_list(jcr);
+      close_dev(dev);
+      dev->state &= ~ST_READ;
+      if (!acquire_device_for_read(jcr, dev, block)) {
+         Pmsg1(-1, "%s", dev->errmsg);
+        return;
+      }
    }
 
    time(&jcr->run_time);             /* start counting time for rates */
@@ -1325,7 +1321,7 @@ static void unfillcmd()
       Pmsg1(-1, _("Forward space to file %u complete. Reading blocks ...\n"), 
            last_file);
       Pmsg1(-1, _("Now reading to block %u.\n"), last_block_num);
-      for (uint32_t i= 0; i < last_block_num; i++) {
+      for (uint32_t i=0; i <= last_block_num; i++) {
         if (!read_block_from_device(jcr, dev, block, NO_BLOCK_NUMBER_CHECK)) {
             Pmsg1(-1, _("Error reading blocks: ERR=%s\n"), strerror_dev(dev));
             Pmsg2(-1, _("Wanted block %u error at block %u\n"), last_block_num, i);
@@ -1350,7 +1346,6 @@ bail_out:
    Pmsg0(000, _("Done with reread of fill data.\n"));
 }
 
-
 /* 
  * We are called here from "unfill" for each record on the tape.
  */
@@ -1483,6 +1478,8 @@ static int flush_block(DEV_BLOCK *block, int dump)
       Pmsg0(000, strerror_dev(dev));           
       Pmsg3(000, "Block not written: FileIndex=%u Block=%u Size=%u\n", 
         (unsigned)file_index, block->BlockNumber, block->block_len);
+      Pmsg2(000, "last_block_num=%u this_block_num=%d\n", last_block_num,
+        this_block_num);
       if (dump) {
          dump_block(block, "Block not written");
       }
@@ -1534,6 +1531,103 @@ static int flush_block(DEV_BLOCK *block, int dump)
 }
 
 
+/* 
+ * First we label the tape, then we fill
+ *  it with data get a new tape and write a few blocks.
+ */                           
+static void qfillcmd()
+{
+   DEV_BLOCK *block;
+   DEV_RECORD *rec;
+   int i, count;
+
+   Pmsg0(0, "Test writing blocks of 64512 bytes to tape.\n");
+
+   get_cmd("How many blocks do you want to write? (1000): ");
+
+   count = atoi(cmd);
+   if (count <= 0) {
+      count = 1000;
+   }
+
+   sm_check(__FILE__, __LINE__, False);
+   block = new_block(dev);
+   rec = new_record();
+
+   i = block->buf_len - 100;
+   ASSERT (i > 0);
+   rec->data = check_pool_memory_size(rec->data, i);
+   memset(rec->data, i & 0xFF, i);
+   rec->data_len = i;
+   rewindcmd();
+   Pmsg1(0, "Begin writing %d blocks to tape ...\n", count);
+   for (i=0; i < count; i++) {
+      if (i % 100 == 0) {
+         printf("+");
+      }
+      if (!write_record_to_block(block, rec)) {
+         Pmsg0(0, _("Error writing record to block.\n")); 
+        goto bail_out;
+      }
+      if (!write_block_to_dev(jcr, dev, block)) {
+         Pmsg0(0, _("Error writing block to device.\n")); 
+        goto bail_out;
+      }
+   }
+   printf("\n");
+   weofcmd();
+   weofcmd();
+   rewindcmd();
+   scan_blocks();
+
+bail_out:
+   sm_check(__FILE__, __LINE__, False);
+   free_record(rec);
+   free_block(block);
+   sm_check(__FILE__, __LINE__, False);
+
+}
+
+static void rawfill_cmd()
+{
+   DEV_BLOCK *block;
+   int stat;
+   int fd;
+   uint32_t block_num = 0;
+   uint32_t *p;
+   int my_errno;
+
+   block = new_block(dev);
+   fd = open("/dev/urandom", O_RDONLY);
+   if (fd) {
+      read(fd, block->buf, block->buf_len);
+   } else {
+      Pmsg0(0, "Cannot open /dev/urandom.\n");
+      free_block(block);
+      return;
+   }
+   p = (uint32_t *)block->buf;
+   Pmsg1(0, "Begin writing blocks of %u bytes.\n", block->buf_len);
+   for ( ;; ) {
+      *p = block_num;
+      stat = write(dev->fd, block->buf, block->buf_len);
+      if (stat == (int)block->buf_len) {
+        if ((block_num++ % 100) == 0) {
+            printf("+");
+        }
+        continue;
+      }
+      break;
+   }
+   my_errno = errno;
+   printf("\n");
+   weofcmd();
+   printf("Write failed at block %u. stat=%d ERR=%s\n", block_num, stat,
+      strerror(my_errno));
+   free_block(block);
+
+}
+
 struct cmdstruct { char *key; void (*func)(); char *help; }; 
 static struct cmdstruct commands[] = {
  {"bsf",        bsfcmd,       "backspace file"},
@@ -1550,15 +1644,18 @@ static struct cmdstruct commands[] = {
  {"label",      labelcmd,     "write a Bacula label to the tape"},
  {"load",       loadcmd,      "load a tape"},
  {"quit",       quitcmd,      "quit btape"},   
+ {"rawfill",    rawfill_cmd,  "use write() to fill tape"},
  {"readlabel",  readlabelcmd, "read and print the Bacula tape label"},
  {"rectest",    rectestcmd,   "test record handling functions"},
  {"rewind",     rewindcmd,    "rewind the tape"},
- {"scan",       scancmd,      "read tape block by block to EOT and report"}, 
+ {"scan",       scancmd,      "read() tape block by block to EOT and report"}, 
+ {"scanblocks", scan_blocks,  "Bacula read block by block to EOT and report"},
  {"status",     statcmd,      "print tape status"},
  {"test",       testcmd,      "General test Bacula tape functions"},
  {"weof",       weofcmd,      "write an EOF on the tape"},
  {"wr",         wrcmd,        "write a single Bacula block"}, 
  {"rr",         rrcmd,        "read a single record"},
+ {"qfill",      qfillcmd,     "quick fill command"},
             };
 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
 
@@ -1642,7 +1739,7 @@ get_cmd(char *prompt)
 }
 
 /* Dummies to replace askdir.c */
-int    dir_get_volume_info(JCR *jcr, int writing) { return 1;}
+int    dir_get_volume_info(JCR *jcr, enum get_vol_info_rw  writing) { return 1;}
 int    dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
 int    dir_create_jobmedia_record(JCR *jcr) { return 1; }
 int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}