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;
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 */
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);
}
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) {
got_inc = TRUE;
break;
+ case 'V': /* Volume name */
+ VolumeName = optarg;
+ break;
+
case '?':
default:
usage();
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);
/* 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);
*/
static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
+ int stat;
if (rec->FileIndex < 0) {
return; /* we don't want labels */
* 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) {
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.
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);
}
/* Pmsg1(000, "Restoring: %s\n", ofile); */
- extract = create_file(jcr, fname, ofile, lname, type, stream,
- &statp, attribsEx, &ofd);
- num_files++;
-
- if (extract) {
- print_ls_output(ofile, lname, type, &statp);
- fileAddr = 0;
- }
+ extract = FALSE;
+ stat = create_file(jcr, fname, ofile, lname, type, stream,
+ &statp, attribsEx, &bfd, REPLACE_ALWAYS);
+ switch (stat) {
+ case CF_ERROR:
+ case CF_SKIP:
+ break;
+ case CF_EXTRACT:
+ extract = TRUE;
+ 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;
+ break;
+ }
}
/* Data stream and extracting */
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));
}
}
}
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;
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));
}
}
}
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));
}
/* 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) {
+ } else if (!(rec->Stream == STREAM_MD5_SIGNATURE ||
+ rec->Stream == STREAM_SHA1_SIGNATURE)) {
Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data);
}
}