]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/bextract.c
Make btape fill/unfill work
[bacula/bacula] / bacula / src / stored / bextract.c
index be9b1fa5ad8c959abab2f4f49f89bd1bd3145270..5e507ebe0921360e4edff133076966aed11f44cb 100644 (file)
@@ -42,7 +42,7 @@ 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 BFILE bfd;
 static JCR *jcr;
 static FF_PKT my_ff;
 static FF_PKT *ff = &my_ff;
@@ -63,6 +63,8 @@ static POOLMEM *compress_buf;
 static int type;
 static int stream;
 static int prog_name_msg = 0;
+static int win32_data_msg = 0;
+static char *VolumeName = NULL;
 
 static char *wbuf;                   /* write buffer address */
 static uint32_t wsize;               /* write size */
@@ -75,13 +77,14 @@ char *configfile;
 static void usage()
 {
    fprintf(stderr,
-"\nVersion: " VERSION " (" DATE ")\n\n"
+"\nVersion: " VERSION " (" BDATE ")\n\n"
 "Usage: bextract [-d debug_level] <bacula-archive> <directory-to-store-files>\n"
 "       -b <file>       specify a bootstrap file\n"
 "       -c <file>       specify a configuration file\n"
 "       -dnn            set debug level to nn\n"
 "       -e <file>       exclude list\n"
 "       -i <file>       include list\n"
+"       -V              specify Volume names (separated by |)\n"
 "       -?              print this message\n\n");
    exit(1);
 }
@@ -100,6 +103,7 @@ int main (int argc, char *argv[])
 
    memset(ff, 0, sizeof(FF_PKT));
    init_include_exclude_files(ff);
+   binit(&bfd);
 
    while ((ch = getopt(argc, argv, "b:c:d:e:i:?")) != -1) {
       switch (ch) {
@@ -150,6 +154,10 @@ int main (int argc, char *argv[])
            got_inc = TRUE;
            break;
 
+         case 'V':                    /* Volume name */
+           VolumeName = optarg;
+           break;
+
          case '?':
         default:
            usage();
@@ -180,13 +188,21 @@ int main (int argc, char *argv[])
    if (bsr) {
       free_bsr(bsr);
    }
+   if (prog_name_msg) {
+      Pmsg1(000, "%d Program Name and/or Program Data Stream records ignored.\n",
+        prog_name_msg);
+   }
+   if (win32_data_msg) {
+      Pmsg1(000, "%d Win32 data or Win32 gzip data stream records. Ignored.\n",
+        win32_data_msg);
+   }
    return 0;
 }
 
 static void do_extract(char *devname)
 {
 
-   jcr = setup_jcr("bextract", devname, bsr);
+   jcr = setup_jcr("bextract", devname, bsr, VolumeName);
    dev = setup_to_access_device(jcr, 1);    /* acquire for read */
    if (!dev) {
       exit(1);
@@ -213,9 +229,9 @@ static void do_extract(char *devname)
    /* 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) {
+   if (is_bopen(&bfd)) {
       set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
-                    attribsEx, &ofd);
+                    attribsEx, &bfd);
    }
    release_device(jcr, dev);
 
@@ -250,12 +266,12 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
        * close the output file.
        */
       if (extract) {
-        if (ofd < 0) {
-            Emsg0(M_ERROR, 0, "Logic error output file should be open\n");
+        if (!is_bopen(&bfd)) {
+            Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
         }
         extract = FALSE;
         set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
-                       attribsEx, &ofd);
+                       attribsEx, &bfd);
       }
 
       if (sizeof_pool_memory(fname) < rec->data_len) {
@@ -321,8 +337,9 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 
         
       if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
+        uint32_t LinkFI;
 
-        decode_stat(ap, &statp);
+        decode_stat(ap, &statp, &LinkFI);
         /*
          * Prepend the where directory so that the
          * files are put where the user wants.
@@ -347,8 +364,10 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
                strcat(ofile, "/");
            }
            strcat(ofile, fn);        /* copy rest of name */
-           /* Fixup link name */
-           if (type == FT_LNK || type == FT_LNKSAVED) {
+           /* Fixup link name for hard links, but not for
+            * soft links 
+            */
+           if (type == FT_LNKSAVED) {
                if (lp[0] == '/') {      /* if absolute path */
                  strcpy(lname, where);
               }       
@@ -364,15 +383,20 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 
         extract = FALSE;
         stat = create_file(jcr, fname, ofile, lname, type, stream,
-                           &statp, attribsEx, &ofd, REPLACE_ALWAYS);
+                           &statp, attribsEx, &bfd, REPLACE_ALWAYS);   
         switch (stat) {
         case CF_ERROR:
         case CF_SKIP:
            break;
         case CF_EXTRACT:
            extract = TRUE;
-           /* Fall-through wanted */
+           print_ls_output(ofile, lname, type, &statp);   
+           num_files++;
+           fileAddr = 0;
+           break;
         case CF_CREATED:
+           set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
+                          attribsEx, &bfd);
            print_ls_output(ofile, lname, type, &statp);   
            num_files++;
            fileAddr = 0;
@@ -392,7 +416,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            unser_uint64(faddr);
            if (fileAddr != faddr) {
               fileAddr = faddr;
-              if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) {
+              if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
                   Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno));
               }
            }
@@ -402,7 +426,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         }
         total += wsize;
          Dmsg2(8, "Write %u bytes, total=%u\n", wsize, total);
-        if ((uint32_t)write(ofd, wbuf, wsize) != wsize) {
+        if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) {
             Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno));
         }
         fileAddr += wsize;
@@ -423,7 +447,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
            unser_uint64(faddr);
            if (fileAddr != faddr) {
               fileAddr = faddr;
-              if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) {
+              if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) {
                   Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno));
               }
            }
@@ -438,7 +462,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         }
 
          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) {
+        if ((uLongf)bwrite(&bfd, 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));
         }
@@ -456,16 +480,21 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 
    /* If extracting, wierd stream (not 1 or 2), close output file anyway */
    } else if (extract) {
-      if (ofd < 0) {
-         Emsg0(M_ERROR, 0, "Logic error output file should be open\n");
+      if (!is_bopen(&bfd)) {
+         Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n");
       }
       extract = FALSE;
       set_attributes(jcr, fname, ofile, lname, type, stream, &statp,
-                    attribsEx, &ofd);
+                    attribsEx, &bfd);
    } else if (rec->Stream == STREAM_PROGRAM_NAMES || rec->Stream == STREAM_PROGRAM_DATA) {
       if (!prog_name_msg) {
          Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n");
-        prog_name_msg = 1;
+        prog_name_msg++;
+      }
+   } else if (rec->Stream == STREAM_WIN32_DATA || rec->Stream == STREAM_WIN32_GZIP_DATA) {
+      if (!win32_data_msg) {
+         Pmsg0(000, "Got Win32 data or Win32 gzip data stream. Ignored.\n");
+        win32_data_msg++;
       }
    } else if (!(rec->Stream == STREAM_MD5_SIGNATURE ||
                rec->Stream == STREAM_SHA1_SIGNATURE)) {