- wherelen = strlen(where);
- fname = get_pool_memory(PM_FNAME);
- 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();
- }
-
-next_record:
- for (rec->state=0; !is_block_empty(rec); ) {
- if (!read_record_from_block(block, rec)) {
- break;
- }
-
- 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 */
-
- /* 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;
- }
-
- /* File Attributes stream */
- if (rec->Stream == STREAM_UNIX_ATTRIBUTES) {
- char *ap, *lp, *fp;
-
- /* 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);
- }
-
- 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 */
-
- /* Skip to Link name */
- if (type == FT_LNK || type == FT_LNKSAVED) {
- lp = ap;
- while (*lp++ != 0) {
- ;
- }
- } 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); */
-
- extract = create_file(jcr, fname, ofile, lname, type, &statp, &ofd);
- num_files++;
-
- 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));
- }
- }
-
- } else if (rec->Stream == STREAM_GZIP_DATA) {
-#ifdef HAVE_LIBZ
- 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"));
- }
-
- 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");
- }
-#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);
- }
- }
- }