- int rc = 0, dest, out, outpipe[2];
- int wc;
- int l, s;
- int file_is_compressed;
-
- /* adjust compression flag */
-
- file_is_compressed = file->compressed;
- if(!compflag && file_is_compressed && !known_compress_type(file)) {
- fprintf(stderr,
- "%s: unknown compression suffix %s, can't uncompress\n",
- get_pname(), file->comp_suffix);
- compflag = 1;
- }
-
- /* set up final destination file */
-
- if(pipeflag)
- dest = 1; /* standard output */
- else {
- char *filename_ext = NULL;
-
- if(compflag) {
- filename_ext = file_is_compressed ? file->comp_suffix
- : COMPRESS_SUFFIX;
- } else if(rawflag) {
- filename_ext = ".RAW";
- } else {
- filename_ext = "";
- }
- filename_ext = stralloc2(filename, filename_ext);
-
- if((dest = creat(filename, CREAT_MODE)) < 0)
- error("could not create output file: %s", strerror(errno));
- amfree(filename_ext);
- }
-
- out = dest;
-
- /*
- * If -r or -h, write the header before compress or uncompress pipe.
- * Only write DISK_BLOCK_BYTES, regardless of how much was read.
- * This makes the output look like a holding disk image, and also
- * makes it easier to remove the header (e.g. in amrecover) since
- * it has a fixed size.
- */
- if(rawflag || headerflag) {
- int w;
- char *cont_filename;
-
- if(compflag && !file_is_compressed) {
- file->compressed = 1;
- ap_snprintf(file->uncompress_cmd, sizeof(file->uncompress_cmd),
- " %s %s |", UNCOMPRESS_PATH,
-#ifdef UNCOMPRESS_OPT
- UNCOMPRESS_OPT
-#else
- ""
-#endif
- );
- strncpy(file->comp_suffix,
- COMPRESS_SUFFIX,
- sizeof(file->comp_suffix)-1);
- file->comp_suffix[sizeof(file->comp_suffix)-1] = '\0';
- }
-
- /* remove CONT_FILENAME from header */
- cont_filename = stralloc(file->cont_filename);
- memset(file->cont_filename,'\0',sizeof(file->cont_filename));
- file->blocksize = DISK_BLOCK_BYTES;
- build_header(buffer, file, bytes_read);
-
- if((w = fullwrite(out, buffer, DISK_BLOCK_BYTES)) != DISK_BLOCK_BYTES) {
- if(w < 0) {
- error("write error: %s", strerror(errno));
- } else {
- error("write error: %d instead of %d", w, DISK_BLOCK_BYTES);
- }
- }
- /* add CONT_FILENAME to header */
- strncpy(file->cont_filename, cont_filename, sizeof(file->cont_filename));
- }
-
- /* if -c and file not compressed, insert compress pipe */
-
- if(compflag && !file_is_compressed) {
- if(pipe(outpipe) < 0) error("error [pipe: %s]", strerror(errno));
- out = outpipe[1];
- switch(compress_pid = fork()) {
- case -1: error("could not fork for %s: %s",
- COMPRESS_PATH, strerror(errno));
- default:
- aclose(outpipe[0]);
- aclose(dest);
- break;
- case 0:
- aclose(outpipe[1]);
- if(outpipe[0] != 0) {
- if(dup2(outpipe[0], 0) == -1)
- error("error [dup2 pipe: %s]", strerror(errno));
- aclose(outpipe[0]);
- }
- if(dest != 1) {
- if(dup2(dest, 1) == -1)
- error("error [dup2 dest: %s]", strerror(errno));
- aclose(dest);
- }
- if (*compress_type == '\0') {
- compress_type = NULL;
- }
- execlp(COMPRESS_PATH, COMPRESS_PATH, compress_type, (char *)0);
- error("could not exec %s: %s", COMPRESS_PATH, strerror(errno));
- }
- }
-
- /* if not -r or -c, and file is compressed, insert uncompress pipe */
-
- else if(!rawflag && !compflag && file_is_compressed) {
- /*
- * XXX for now we know that for the two compression types we
- * understand, .Z and optionally .gz, UNCOMPRESS_PATH will take
- * care of both. Later, we may need to reference a table of
- * possible uncompress programs.
- */
- if(pipe(outpipe) < 0) error("error [pipe: %s]", strerror(errno));
- out = outpipe[1];
- switch(compress_pid = fork()) {
- case -1:
- error("could not fork for %s: %s",
- UNCOMPRESS_PATH, strerror(errno));
- default:
- aclose(outpipe[0]);
- aclose(dest);
- break;
- case 0:
- aclose(outpipe[1]);
- if(outpipe[0] != 0) {
- if(dup2(outpipe[0], 0) < 0)
- error("dup2 pipe: %s", strerror(errno));
- aclose(outpipe[0]);
- }
- if(dest != 1) {
- if(dup2(dest, 1) < 0)
- error("dup2 dest: %s", strerror(errno));
- aclose(dest);
- }
- (void) execlp(UNCOMPRESS_PATH, UNCOMPRESS_PATH,
-#ifdef UNCOMPRESS_OPT
- UNCOMPRESS_OPT,
-#endif
- (char *)0);
- error("could not exec %s: %s", UNCOMPRESS_PATH, strerror(errno));
- }
- }
-
-
- /* copy the rest of the file from tape to the output */
- got_sigpipe = 0;
- wc = 0;
- do {
- bytes_read = get_block(isafile);
- if(bytes_read < 0) {
- error("read error: %s", strerror(errno));
- }
- if(bytes_read == 0 && isafile) {
- /*
- * See if we need to switch to the next file.
- */
- if(file->cont_filename[0] == '\0') {
- break; /* no more files */
- }
- close(tapedev);
- if((tapedev = open(file->cont_filename, O_RDONLY)) == -1) {
- char *cont_filename = strrchr(file->cont_filename,'/');
- if(cont_filename) {
- cont_filename++;
- if((tapedev = open(cont_filename,O_RDONLY)) == -1) {
- error("can't open %s: %s", file->cont_filename,
- strerror(errno));
- }
- else {
- fprintf(stderr, "cannot open %s: %s\n",
- file->cont_filename, strerror(errno));
- fprintf(stderr, "using %s\n",
- cont_filename);
- }
- }
- else {
- error("can't open %s: %s", file->cont_filename,
- strerror(errno));
- }
- }
- read_file_header(file, isafile);
- if(file->type != F_DUMPFILE && file->type != F_CONT_DUMPFILE) {
- fprintf(stderr, "unexpected header type: ");
- print_header(stderr, file);
- exit(2);
- }
- continue;
- }
- for(l = 0; l < bytes_read; l += s) {
- if((s = write(out, buffer + l, bytes_read - l)) < 0) {
- if(got_sigpipe) {
- fprintf(stderr,"Error %d (%s) offset %d+%d, wrote %d\n",
- errno, strerror(errno), wc, bytes_read, rc);
- fprintf(stderr,
- "%s: pipe reader has quit in middle of file.\n",
- get_pname());
- } else {
- perror("amrestore: write error");
- }
- exit(2);
- }
- }
- wc += bytes_read;
- } while (bytes_read > 0);
- if(pipeflag) {
- if(out != dest) {
- aclose(out);
- }
- } else {
- aclose(out);
- }