From 32841f71caa7337a62ce231ed787609003bce86f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:22 +0000 Subject: [PATCH 01/16] *** empty log message *** --- src/buffer.c | 1353 +++++++++++++++++++++++++++++++++++++++++++++++++ src/extract.c | 16 +- 2 files changed, 1361 insertions(+), 8 deletions(-) create mode 100644 src/buffer.c diff --git a/src/buffer.c b/src/buffer.c new file mode 100644 index 0000000..603bdc2 --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,1353 @@ +/* Buffer management for tar. + Copyright (C) 1988 Free Software Foundation + +This file is part of GNU Tar. + +GNU Tar is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Tar is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Tar; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + * Buffer management for tar. + * + * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985. + */ + +#include +#include +#ifndef STDC_HEADERS +extern int errno; +#endif +#include /* For non-Berkeley systems */ +#include +#include +time_t time(); + +#ifndef NO_MTIO +#include +#include +#endif + +#ifdef BSD42 +#include +#else +#ifndef V7 +#include +#endif +#endif + +#ifdef __MSDOS__ +#include +#endif + +#ifdef XENIX +#include +#endif + +#include "tar.h" +#include "port.h" +#include "rmt.h" +#include "regex.h" + +/* Either stdout or stderr: The thing we write messages (standard msgs, not + errors) to. Stdout unless we're writing a pipe, in which case stderr */ +FILE *msg_file = stdout; + +#define STDIN 0 /* Standard input file descriptor */ +#define STDOUT 1 /* Standard output file descriptor */ + +#define PREAD 0 /* Read file descriptor from pipe() */ +#define PWRITE 1 /* Write file descriptor from pipe() */ + +#define MAGIC_STAT 105 /* Magic status returned by child, if + it can't exec. We hope compress/sh + never return this status! */ + +char *valloc(); + +void writeerror(); +void readerror(); + +void ck_pipe(); +void ck_close(); + +int backspace_output(); +extern void finish_header(); +void flush_archive(); +int isfile(); +int new_volume(); +void verify_volume(); +extern void to_oct(); + +#ifndef __MSDOS__ +/* Obnoxious test to see if dimwit is trying to dump the archive */ +dev_t ar_dev; +ino_t ar_ino; +#endif + +/* + * The record pointed to by save_rec should not be overlaid + * when reading in a new tape block. Copy it to record_save_area first, and + * change the pointer in *save_rec to point to record_save_area. + * Saved_recno records the record number at the time of the save. + * This is used by annofile() to print the record number of a file's + * header record. + */ +static union record **save_rec; + union record record_save_area; +static long saved_recno; + +/* + * PID of child program, if f_compress or remote archive access. + */ +static int childpid = 0; + +/* + * Record number of the start of this block of records + */ +long baserec; + +/* + * Error recovery stuff + */ +static int r_error_count; + +/* + * Have we hit EOF yet? + */ +static int eof; + +/* JF we're reading, but we just read the last record and its time to update */ +extern time_to_start_writing; +int file_to_switch_to= -1; /* If remote update, close archive, and use + this descriptor to write to */ + +static int volno = 1; /* JF which volume of a multi-volume tape + we're on */ + +char *save_name = 0; /* Name of the file we are currently writing */ +long save_totsize; /* total size of file we are writing. Only + valid if save_name is non_zero */ +long save_sizeleft; /* Where we are in the file we are writing. + Only valid if save_name is non-zero */ + +int write_archive_to_stdout; + +/* Used by fl_read and fl_write to store the real info about saved names */ +static char real_s_name[NAMSIZ]; +static long real_s_totsize; +static long real_s_sizeleft; + +/* Reset the EOF flag (if set), and re-set ar_record, etc */ + +void +reset_eof() +{ + if(eof) { + eof=0; + ar_record=ar_block; + ar_last=ar_block+blocking; + ar_reading=0; + } +} + +/* + * Return the location of the next available input or output record. + * Return NULL for EOF. Once we have returned NULL, we just keep returning + * it, to avoid accidentally going on to the next file on the "tape". + */ +union record * +findrec() +{ + if (ar_record == ar_last) { + if (eof) + return (union record *)NULL; /* EOF */ + flush_archive(); + if (ar_record == ar_last) { + eof++; + return (union record *)NULL; /* EOF */ + } + } + return ar_record; +} + + +/* + * Indicate that we have used all records up thru the argument. + * (should the arg have an off-by-1? XXX FIXME) + */ +void +userec(rec) + union record *rec; +{ + while(rec >= ar_record) + ar_record++; + /* + * Do NOT flush the archive here. If we do, the same + * argument to userec() could mean the next record (if the + * input block is exactly one record long), which is not what + * is intended. + */ + if (ar_record > ar_last) + abort(); +} + + +/* + * Return a pointer to the end of the current records buffer. + * All the space between findrec() and endofrecs() is available + * for filling with data, or taking data from. + */ +union record * +endofrecs() +{ + return ar_last; +} + + +/* + * Duplicate a file descriptor into a certain slot. + * Equivalent to BSD "dup2" with error reporting. + */ +void +dupto(from, to, msg) + int from, to; + char *msg; +{ + int err; + + if (from != to) { + err=close(to); + if(err<0 && errno!=EBADF) { + msg_perror("Cannot close descriptor %d",to); + exit(EX_SYSTEM); + } + err = dup(from); + if (err != to) { + msg_perror("cannot dup %s",msg); + exit(EX_SYSTEM); + } + ck_close(from); + } +} + +#ifdef __MSDOS__ +void +child_open() +{ + fprintf(stderr,"MS-DOS %s can't use compressed or remote archives\n",tar); + exit(EX_ARGSBAD); +} +#else +void +child_open() +{ + int pipe[2]; + int err = 0; + + int kidpipe[2]; + int kidchildpid; + +#define READ 0 +#define WRITE 1 + + ck_pipe(pipe); + + childpid=fork(); + if(childpid<0) { + msg_perror("cannot fork"); + exit(EX_SYSTEM); + } + if(childpid>0) { + /* We're the parent. Clean up and be happy */ + /* This, at least, is easy */ + + if(ar_reading) { + f_reblock++; + archive=pipe[READ]; + ck_close(pipe[WRITE]); + } else { + archive = pipe[WRITE]; + ck_close(pipe[READ]); + } + return; + } + + /* We're the kid */ + if(ar_reading) { + dupto(pipe[WRITE],STDOUT,"(child) pipe to stdout"); + ck_close(pipe[READ]); + } else { + dupto(pipe[READ],STDIN,"(child) pipe to stdin"); + ck_close(pipe[WRITE]); + } + + /* We need a child tar only if + 1: we're reading/writing stdin/out (to force reblocking) + 2: the file is to be accessed by rmt (compress doesn't know how) + 3: the file is not a plain file */ +#ifdef NO_REMOTE + if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file)) +#else + if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file)) +#endif + { + /* We don't need a child tar. Open the archive */ + if(ar_reading) { + archive=open(ar_file, O_RDONLY|O_BINARY, 0666); + if(archive<0) { + msg_perror("can't open archive %s",ar_file); + exit(EX_BADARCH); + } + dupto(archive,STDIN,"archive to stdin"); + /* close(archive); */ + } else { + archive=creat(ar_file,0666); + if(archive<0) { + msg_perror("can't open archive %s",ar_file); + exit(EX_BADARCH); + } + dupto(archive,STDOUT,"archive to stdout"); + /* close(archive); */ + } + } else { + /* We need a child tar */ + ck_pipe(kidpipe); + + kidchildpid=fork(); + if(kidchildpid<0) { + msg_perror("child can't fork"); + exit(EX_SYSTEM); + } + + if(kidchildpid>0) { + /* About to exec compress: set up the files */ + if(ar_reading) { + dupto(kidpipe[READ],STDIN,"((child)) pipe to stdin"); + ck_close(kidpipe[WRITE]); + /* dup2(pipe[WRITE],STDOUT); */ + } else { + /* dup2(pipe[READ],STDIN); */ + dupto(kidpipe[WRITE],STDOUT,"((child)) pipe to stdout"); + ck_close(kidpipe[READ]); + } + /* ck_close(pipe[READ]); */ + /* ck_close(pipe[WRITE]); */ + /* ck_close(kidpipe[READ]); + ck_close(kidpipe[WRITE]); */ + } else { + /* Grandchild. Do the right thing, namely sit here and + read/write the archive, and feed stuff back to compress */ + tar="tar (child)"; + if(ar_reading) { + dupto(kidpipe[WRITE],STDOUT,"[child] pipe to stdout"); + ck_close(kidpipe[READ]); + } else { + dupto(kidpipe[READ],STDIN,"[child] pipe to stdin"); + ck_close(kidpipe[WRITE]); + } + + if (ar_file[0] == '-' && ar_file[1] == '\0') { + if (ar_reading) + archive = STDIN; + else + archive = STDOUT; + } else /* This can't happen if (ar_reading==2) + archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666); + else */if(ar_reading) + archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666); + else + archive = rmtcreat(ar_file, 0666); + + if (archive < 0) { + msg_perror("can't open archive %s",ar_file); + exit(EX_BADARCH); + } + + if(ar_reading) { + for(;;) { + char *ptr; + int max,count; + + r_error_count = 0; + error_loop: + err=rmtread(archive, ar_block->charptr,(int)(blocksize)); + if(err<0) { + readerror(); + goto error_loop; + } + if(err==0) + break; + ptr = ar_block->charptr; + max = err; + while(max) { + count = (maxcharptr; + while(n) { + err=read(STDIN,ptr,(ncharptr+blocksize-n,n); + err=rmtwrite(archive,ar_block->charptr,blocksize); + if(err!=(blocksize)) + writeerror(err); + if(f_compress<2) + blocksize+=n; + break; + } + if(n) { + msg_perror("can't read from compress"); + exit(EX_SYSTEM); + } + err=rmtwrite(archive, ar_block->charptr, (int)blocksize); + if(err!=blocksize) + writeerror(err); + } + } + + /* close_archive(); */ + exit(0); + } + } + /* So we should exec compress (-d) */ + if(ar_reading) + execlp("compress", "compress", "-d", (char *)0); + else + execlp("compress", "compress", (char *)0); + msg_perror("can't exec compress"); + _exit(EX_SYSTEM); +} + + +/* return non-zero if p is the name of a directory */ +int +isfile(p) +char *p; +{ + struct stat stbuf; + + if(stat(p,&stbuf)<0) + return 1; + if(S_ISREG(stbuf.st_mode)) + return 1; + return 0; +} + +#endif + +/* + * Open an archive file. The argument specifies whether we are + * reading or writing. + */ +/* JF if the arg is 2, open for reading and writing. */ +void +open_archive(reading) + int reading; +{ + msg_file = f_exstdout ? stderr : stdout; + + if (blocksize == 0) { + msg("invalid value for blocksize"); + exit(EX_ARGSBAD); + } + + if(ar_file==0) { + msg("No archive name given, what should I do?"); + exit(EX_BADARCH); + } + + /*NOSTRICT*/ + if(f_multivol) { + ar_block = (union record *) valloc((unsigned)(blocksize+(2*RECORDSIZE))); + if(ar_block) + ar_block += 2; + } else + ar_block = (union record *) valloc((unsigned)blocksize); + if (!ar_block) { + msg("could not allocate memory for blocking factor %d", + blocking); + exit(EX_ARGSBAD); + } + + ar_record = ar_block; + ar_last = ar_block + blocking; + ar_reading = reading; + + if (f_compress) { + if(reading==2 || f_verify) { + msg("cannot update or verify compressed archives"); + exit(EX_ARGSBAD); + } + child_open(); + if(!reading && ar_file[0]=='-' && ar_file[1]=='\0') + msg_file = stderr; + /* child_open(rem_host, rem_file); */ + } else if (ar_file[0] == '-' && ar_file[1] == '\0') { + f_reblock++; /* Could be a pipe, be safe */ + if(f_verify) { + msg("can't verify stdin/stdout archive"); + exit(EX_ARGSBAD); + } + if(reading==2) { + archive=STDIN; + msg_file=stderr; + write_archive_to_stdout++; + } else if (reading) + archive = STDIN; + else { + archive = STDOUT; + msg_file = stderr; + } + } else if (reading==2 || f_verify) { + archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666); + } else if(reading) { + archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666); + } else { + archive = rmtcreat(ar_file, 0666); + } + if (archive < 0) { + msg_perror("can't open %s",ar_file); + exit(EX_BADARCH); + } + +#ifndef __MSDOS__ + if(!_isrmt(archive)) { + struct stat tmp_stat; + + fstat(archive,&tmp_stat); + if(S_ISREG(tmp_stat.st_mode)) { + ar_dev=tmp_stat.st_dev; + ar_ino=tmp_stat.st_ino; + } + } +#endif + +#ifdef __MSDOS__ + setmode(archive, O_BINARY); +#endif + + if (reading) { + ar_last = ar_block; /* Set up for 1st block = # 0 */ + (void) findrec(); /* Read it in, check for EOF */ + + if(f_volhdr) { + union record *head; +#if 0 + char *ptr; + + if(f_multivol) { + ptr=malloc(strlen(f_volhdr)+20); + sprintf(ptr,"%s Volume %d",f_volhdr,1); + } else + ptr=f_volhdr; +#endif + head=findrec(); + if(!head) { + msg("Archive not labelled to match %s",f_volhdr); + exit(EX_BADVOL); + } + if (re_match (label_pattern, head->header.name, + strlen (head->header.name), 0, 0) < 0) { + msg ("Volume mismatch! %s!=%s", f_volhdr, + head->header.name); + exit (EX_BADVOL); + } +#if 0 + if(strcmp(ptr,head->header.name)) { + msg("Volume mismatch! %s!=%s",ptr,head->header.name); + exit(EX_BADVOL); + } + if(ptr!=f_volhdr) + free(ptr); +#endif + } + } else if(f_volhdr) { + bzero((void *)ar_block,RECORDSIZE); + if(f_multivol) + sprintf(ar_block->header.name,"%s Volume 1",f_volhdr); + else + strcpy(ar_block->header.name,f_volhdr); + ar_block->header.linkflag = LF_VOLHDR; + to_oct(time(0), 1+12, ar_block->header.mtime); + finish_header(ar_block); + /* ar_record++; */ + } +} + + +/* + * Remember a union record * as pointing to something that we + * need to keep when reading onward in the file. Only one such + * thing can be remembered at once, and it only works when reading + * an archive. + * + * We calculate "offset" then add it because some compilers end up + * adding (baserec+ar_record), doing a 9-bit shift of baserec, then + * subtracting ar_block from that, shifting it back, losing the top 9 bits. + */ +void +saverec(pointer) + union record **pointer; +{ + long offset; + + save_rec = pointer; + offset = ar_record - ar_block; + saved_recno = baserec + offset; +} + +/* + * Perform a write to flush the buffer. + */ + +/*send_buffer_to_file(); + if(new_volume) { + deal_with_new_volume_stuff(); + send_buffer_to_file(); + } + */ + +void +fl_write() +{ + int err; + int copy_back; + static long bytes_written = 0; + + if(tape_length && bytes_written >= tape_length * 1024) { + errno = ENOSPC; + err = 0; + } else + err = rmtwrite(archive, ar_block->charptr,(int) blocksize); + if(err!=blocksize && !f_multivol) + writeerror(err); + else if (f_totals) + tot_written += blocksize; + + if(err>0) + bytes_written+=err; + if (err == blocksize) { + if(f_multivol) { + if(!save_name) { + real_s_name[0]='\0'; + real_s_totsize=0; + real_s_sizeleft = 0; + return; + } +#ifdef __MSDOS__ + if(save_name[1]==':') + save_name+=2; +#endif + while(*save_name=='/') + save_name++; + + strcpy(real_s_name,save_name); + real_s_totsize = save_totsize; + real_s_sizeleft = save_sizeleft; + } + return; + } + + /* We're multivol Panic if we didn't get the right kind of response */ + /* ENXIO is for the UNIX PC */ + if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)) + writeerror(err); + + if(new_volume(0)<0) + return; + bytes_written=0; + if(f_volhdr && real_s_name[0]) { + copy_back=2; + ar_block-=2; + } else if(f_volhdr || real_s_name[0]) { + copy_back = 1; + ar_block--; + } else + copy_back = 0; + if(f_volhdr) { + bzero((void *)ar_block,RECORDSIZE); + sprintf(ar_block->header.name,"%s Volume %d",f_volhdr,volno); + to_oct(time(0), 1+12, ar_block->header.mtime); + ar_block->header.linkflag = LF_VOLHDR; + finish_header(ar_block); + } + if(real_s_name[0]) { + int tmp; + + if(f_volhdr) + ar_block++; + bzero((void *)ar_block,RECORDSIZE); + strcpy(ar_block->header.name,real_s_name); + ar_block->header.linkflag = LF_MULTIVOL; + to_oct((long)real_s_sizeleft,1+12, + ar_block->header.size); + to_oct((long)real_s_totsize-real_s_sizeleft, + 1+12,ar_block->header.offset); + tmp=f_verbose; + f_verbose=0; + finish_header(ar_block); + f_verbose=tmp; + if(f_volhdr) + ar_block--; + } + + err = rmtwrite(archive, ar_block->charptr,(int) blocksize); + if(err!=blocksize) + writeerror(err); + else if (f_totals) + tot_written += blocksize; + + + bytes_written = blocksize; + if(copy_back) { + ar_block+=copy_back; + bcopy((void *)(ar_block+blocking-copy_back), + (void *)ar_record, + copy_back*RECORDSIZE); + ar_record+=copy_back; + + if(real_s_sizeleft>=copy_back*RECORDSIZE) + real_s_sizeleft-=copy_back*RECORDSIZE; + else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back) + real_s_name[0] = '\0'; + else { +#ifdef __MSDOS__ + if(save_name[1]==':') + save_name+=2; +#endif + while(*save_name=='/') + save_name++; + + strcpy(real_s_name,save_name); + real_s_sizeleft = save_sizeleft; + real_s_totsize=save_totsize; + } + copy_back = 0; + } +} + +/* Handle write errors on the archive. Write errors are always fatal */ +/* Hitting the end of a volume does not cause a write error unless the write +* was the first block of the volume */ + +void +writeerror(err) +int err; +{ + if (err < 0) { + msg_perror("can't write to %s",ar_file); + exit(EX_BADARCH); + } else { + msg("only wrote %u of %u bytes to %s",err,blocksize,ar_file); + exit(EX_BADARCH); + } +} + +/* + * Handle read errors on the archive. + * + * If the read should be retried, readerror() returns to the caller. + */ +void +readerror() +{ +# define READ_ERROR_MAX 10 + + read_error_flag++; /* Tell callers */ + + msg_perror("read error on %s",ar_file); + + if (baserec == 0) { + /* First block of tape. Probably stupidity error */ + exit(EX_BADARCH); + } + + /* + * Read error in mid archive. We retry up to READ_ERROR_MAX times + * and then give up on reading the archive. We set read_error_flag + * for our callers, so they can cope if they want. + */ + if (r_error_count++ > READ_ERROR_MAX) { + msg("Too many errors, quitting."); + exit(EX_BADARCH); + } + return; +} + + +/* + * Perform a read to flush the buffer. + */ +void +fl_read() +{ + int err; /* Result from system call */ + int left; /* Bytes left */ + char *more; /* Pointer to next byte to read */ + + /* + * Clear the count of errors. This only applies to a single + * call to fl_read. We leave read_error_flag alone; it is + * only turned off by higher level software. + */ + r_error_count = 0; /* Clear error count */ + + /* + * If we are about to wipe out a record that + * somebody needs to keep, copy it out to a holding + * area and adjust somebody's pointer to it. + */ + if (save_rec && + *save_rec >= ar_record && + *save_rec < ar_last) { + record_save_area = **save_rec; + *save_rec = &record_save_area; + } + if(write_archive_to_stdout && baserec!=0) { + err=rmtwrite(1, ar_block->charptr, blocksize); + if(err!=blocksize) + writeerror(err); + } + if(f_multivol) { + if(save_name) { + if(save_name!=real_s_name) { +#ifdef __MSDOS__ + if(save_name[1]==':') + save_name+=2; +#endif + while(*save_name=='/') + save_name++; + + strcpy(real_s_name,save_name); + save_name=real_s_name; + } + real_s_totsize = save_totsize; + real_s_sizeleft = save_sizeleft; + + } else { + real_s_name[0]='\0'; + real_s_totsize=0; + real_s_sizeleft = 0; + } + } + +error_loop: + err = rmtread(archive, ar_block->charptr, (int)blocksize); + if (err == blocksize) + return; + + if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) { + union record *head; + + try_volume: + if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0) + return; + vol_error: + err = rmtread(archive, ar_block->charptr,(int) blocksize); + if(err < 0) { + readerror(); + goto vol_error; + } + if(err!=blocksize) + goto short_read; + + head=ar_block; + + if(head->header.linkflag==LF_VOLHDR) { + if(f_volhdr) { +#if 0 + char *ptr; + + ptr=(char *)malloc(strlen(f_volhdr)+20); + sprintf(ptr,"%s Volume %d",f_volhdr,volno); +#endif + if (re_match (label_pattern, head->header.name, + strlen (head->header.name), + 0, 0) < 0) { + msg("Volume mismatch! %s!=%s",f_volhdr, + head->header.name); + --volno; + goto try_volume; + } + +#if 0 + if(strcmp(ptr,head->header.name)) { + msg("Volume mismatch! %s!=%s",ptr,head->header.name); + --volno; + free(ptr); + goto try_volume; + } + free(ptr); +#endif + } + if(f_verbose) + fprintf(msg_file,"Reading %s\n",head->header.name); + head++; + } else if(f_volhdr) { + msg("Warning: No volume header!"); + } + + if(real_s_name[0]) { + long from_oct(); + + if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) { + msg("%s is not continued on this volume!",real_s_name); + --volno; + goto try_volume; + } + if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) { + msg("%s is the wrong size (%ld!=%ld+%ld)", + head->header.name,save_totsize, + from_oct(1+12,head->header.size), + from_oct(1+12,head->header.offset)); + --volno; + goto try_volume; + } + if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) { + msg("This volume is out of sequence"); + --volno; + goto try_volume; + } + head++; + } + ar_record=head; + return; + } else if (err < 0) { + readerror(); + goto error_loop; /* Try again */ + } + + short_read: + more = ar_block->charptr + err; + left = blocksize - err; + +again: + if (0 == (((unsigned)left) % RECORDSIZE)) { + /* FIXME, for size=0, multi vol support */ + /* On the first block, warn about the problem */ + if (!f_reblock && baserec == 0 && f_verbose && err > 0) { + /* msg("Blocksize = %d record%s", + err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/ + msg("Blocksize = %d records", err / RECORDSIZE); + } + ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE; + return; + } + if (f_reblock) { + /* + * User warned us about this. Fix up. + */ + if (left > 0) { +error2loop: + err = rmtread(archive, more, (int)left); + if (err < 0) { + readerror(); + goto error2loop; /* Try again */ + } + if (err == 0) { + msg("archive %s EOF not on block boundary",ar_file); + exit(EX_BADARCH); + } + left -= err; + more += err; + goto again; + } + } else { + msg("only read %d bytes from archive %s",err,ar_file); + exit(EX_BADARCH); + } +} + + +/* + * Flush the current buffer to/from the archive. + */ +void +flush_archive() +{ + int c; + + baserec += ar_last - ar_block; /* Keep track of block #s */ + ar_record = ar_block; /* Restore pointer to start */ + ar_last = ar_block + blocking; /* Restore pointer to end */ + + if (ar_reading) { + if(time_to_start_writing) { + time_to_start_writing=0; + ar_reading=0; + + if(file_to_switch_to>=0) { + if((c=rmtclose(archive))<0) + msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + + archive=file_to_switch_to; + } else + (void)backspace_output(); + fl_write(); + } else + fl_read(); + } else { + fl_write(); + } +} + +/* Backspace the archive descriptor by one blocks worth. + If its a tape, MTIOCTOP will work. If its something else, + we try to seek on it. If we can't seek, we lose! */ +int +backspace_output() +{ + long cur; + /* int er; */ + extern char *output_start; + +#ifdef MTIOCTOP + struct mtop t; + + t.mt_op = MTBSR; + t.mt_count = 1; + if((rmtioctl(archive,MTIOCTOP,&t))>=0) + return 1; + if(errno==EIO && (rmtioctl(archive,MTIOCTOP,&t))>=0) + return 1; +#endif + + cur=rmtlseek(archive,0L,1); + cur-=blocksize; + /* Seek back to the beginning of this block and + start writing there. */ + + if(rmtlseek(archive,cur,0)!=cur) { + /* Lseek failed. Try a different method */ + msg("Couldn't backspace archive file. It may be unreadable without -i."); + /* Replace the first part of the block with nulls */ + if(ar_block->charptr!=output_start) + bzero(ar_block->charptr,output_start-ar_block->charptr); + return 2; + } + return 3; +} + + +/* + * Close the archive file. + */ +void +close_archive() +{ + int child; + int status; + int c; + + if (time_to_start_writing || !ar_reading) + flush_archive(); + if(cmd_mode==CMD_DELETE) { + off_t pos; + + pos = rmtlseek(archive,0L,1); +#ifndef __MSDOS__ + (void) ftruncate(archive,pos); +#else + (void)rmtwrite(archive,"",0); +#endif + } + if(f_verify) + verify_volume(); + + if((c=rmtclose(archive))<0) + msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + +#ifndef __MSDOS__ + if (childpid) { + /* + * Loop waiting for the right child to die, or for + * no more kids. + */ + while (((child = wait(&status)) != childpid) && child != -1) + ; + + if (child != -1) { + switch (WTERMSIG(status)) { + case 0: + /* Child voluntarily terminated -- but why? */ + if (WEXITSTATUS(status) == MAGIC_STAT) { + exit(EX_SYSTEM);/* Child had trouble */ + } + if (WEXITSTATUS(status) == (SIGPIPE + 128)) { + /* + * /bin/sh returns this if its child + * dies with SIGPIPE. 'Sok. + */ + break; + } else if (WEXITSTATUS(status)) + msg("child returned status %d", + WEXITSTATUS(status)); + case SIGPIPE: + break; /* This is OK. */ + + default: + msg("child died with signal %d%s", + WTERMSIG(status), + WIFCOREDUMPED(status)? " (core dumped)": ""); + } + } + } +#endif /* __MSDOS__ */ +} + + +#ifdef DONTDEF +/* + * Message management. + * + * anno writes a message prefix on stream (eg stdout, stderr). + * + * The specified prefix is normally output followed by a colon and a space. + * However, if other command line options are set, more output can come + * out, such as the record # within the archive. + * + * If the specified prefix is NULL, no output is produced unless the + * command line option(s) are set. + * + * If the third argument is 1, the "saved" record # is used; if 0, the + * "current" record # is used. + */ +void +anno(stream, prefix, savedp) + FILE *stream; + char *prefix; + int savedp; +{ +# define MAXANNO 50 + char buffer[MAXANNO]; /* Holds annorecment */ +# define ANNOWIDTH 13 + int space; + long offset; + int save_e; + + save_e=errno; + /* Make sure previous output gets out in sequence */ + if (stream == stderr) + fflush(stdout); + if (f_sayblock) { + if (prefix) { + fputs(prefix, stream); + putc(' ', stream); + } + offset = ar_record - ar_block; + (void) sprintf(buffer, "rec %d: ", + savedp? saved_recno: + baserec + offset); + fputs(buffer, stream); + space = ANNOWIDTH - strlen(buffer); + if (space > 0) { + fprintf(stream, "%*s", space, ""); + } + } else if (prefix) { + fputs(prefix, stream); + fputs(": ", stream); + } + errno=save_e; +} +#endif + +/* We've hit the end of the old volume. Close it and open the next one */ +/* Values for type: 0: writing 1: reading 2: updating */ +int +new_volume(type) +int type; +{ + int c; + char inbuf[80]; + char *p; + static FILE *read_file = 0; + extern int now_verifying; + extern char TTY_NAME[]; + char *getenv(); + + if(!read_file && !f_run_script_at_end) + read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin; + + if(now_verifying) + return -1; + if(f_verify) + verify_volume(); + if((c=rmtclose(archive))<0) + msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + + volno++; + tryagain: + if (f_run_script_at_end) + system(info_script); + else for(;;) { + fprintf(msg_file,"\007Prepare volume #%d and hit return: ",volno); + fflush(msg_file); + if(fgets(inbuf,sizeof(inbuf),read_file)==0) { + fprintf(msg_file,"EOF? What does that mean?"); + if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) + msg("Warning: Archive is INCOMPLETE!"); + exit(EX_BADARCH); + } + if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y') + break; + + switch(inbuf[0]) { + case '?': + { + fprintf(msg_file,"\ + n [name] Give a new filename for the next (and subsequent) volume(s)\n\ + q Abort tar\n\ + ! Spawn a subshell\n\ + ? Print this list\n"); + } + break; + + case 'q': /* Quit */ + fprintf(msg_file,"No new volume; exiting.\n"); + if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) + msg("Warning: Archive is INCOMPLETE!"); + exit(EX_BADARCH); + + case 'n': /* Get new file name */ + { + char *q,*r; + static char *old_name; + + for(q= &inbuf[1];*q==' ' || *q=='\t';q++) + ; + for(r=q;*r;r++) + if(*r=='\n') + *r='\0'; + if(old_name) + free(old_name); + old_name=p=(char *)malloc((unsigned)(strlen(q)+2)); + if(p==0) { + msg("Can't allocate memory for name"); + exit(EX_SYSTEM); + } + (void) strcpy(p,q); + ar_file=p; + } + break; + + case '!': +#ifdef __MSDOS__ + spawnl(P_WAIT,getenv("COMSPEC"),"-",0); +#else + /* JF this needs work! */ + switch(fork()) { + case -1: + msg_perror("can't fork!"); + break; + case 0: + p=getenv("SHELL"); + if(p==0) p="/bin/sh"; + execlp(p,"-sh","-i",0); + msg_perror("can't exec a shell %s",p); + _exit(55); + default: + wait(0); + break; + } +#endif + break; + } + } + + if(type==2 || f_verify) + archive=rmtopen(ar_file,O_RDWR|O_CREAT,0666); + else if(type==1) + archive=rmtopen(ar_file,O_RDONLY,0666); + else if(type==0) + archive=rmtcreat(ar_file,0666); + else + archive= -1; + + if(archive<0) { + msg_perror("can't open %s",ar_file); + goto tryagain; + } +#ifdef __MSDOS__ + setmode(archive,O_BINARY); +#endif + return 0; +} + +/* this is a useless function that takes a buffer returned by wantbytes + and does nothing with it. If the function called by wantbytes returns + an error indicator (non-zero), this function is called for the rest of + the file. + */ +int +no_op(size,data) +int size; +char *data; +{ + return 0; +} + +/* Some other routine wants SIZE bytes in the archive. For each chunk of + the archive, call FUNC with the size of the chunk, and the address of + the chunk it can work with. + */ +int +wantbytes(size,func) +long size; +int (*func)(); +{ + char *data; + long data_size; + + while(size) { + data = findrec()->charptr; + if (data == NULL) { /* Check it... */ + msg("Unexpected EOF on archive file"); + return -1; + } + data_size = endofrecs()->charptr - data; + if(data_size>size) + data_size=size; + if((*func)(data_size,data)) + func=no_op; + userec((union record *)(data + data_size - 1)); + size-=data_size; + } + return 0; +} diff --git a/src/extract.c b/src/extract.c index b717114..bea66ef 100644 --- a/src/extract.c +++ b/src/extract.c @@ -217,7 +217,7 @@ extract_archive () */ case LF_SPARSE: sp_array_size = 10; - sparsearray = (struct sp_array *) malloc (sp_array_size * sizeof (struct sp_array)); + sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array)); for (i = 0; i < SPARSE_IN_HDR; i++) { sparsearray[i].offset = @@ -252,7 +252,7 @@ extract_archive () * since we've run out of room -- */ sparsearray = (struct sp_array *) - realloc (sparsearray, + ck_realloc (sparsearray, 2 * sp_array_size * (sizeof (struct sp_array))); sp_array_size *= 2; } @@ -367,8 +367,8 @@ extract_archive () * that happen to contain the filename will look * REAL interesting unless we do this. */ - namelen = strlen (skipcrud + current_file_name); - name = (char *) malloc ((sizeof (char)) * namelen); + namelen = strlen (skipcrud + current_file_name) + 1; + name = (char *) ck_malloc ((sizeof (char)) * namelen); bcopy (skipcrud + current_file_name, name, namelen); size = hstat.st_size; extract_sparse_file (fd, &size, hstat.st_size, name); @@ -436,7 +436,7 @@ extract_archive () skipcrud + current_file_name); else msg ("could only write %d of %d bytes to file %s", - written, check, skipcrud + current_file_name); + check, written, skipcrud + current_file_name); skip_file ((long) (size - written)); break; /* Still do the close, mod time, chmod, etc */ } @@ -634,7 +634,7 @@ extract_archive () case LF_DIR: case LF_DUMPDIR: - namelen = strlen (current_file_name) + skipcrud - 1; + namelen = strlen (current_file_name + skipcrud) - 1; really_dir: /* Check for trailing /, and zap as many as we find. */ while (namelen @@ -682,8 +682,8 @@ extract_archive () if (f_modified) goto set_filestat; - tmp = (struct saved_dir_info *) malloc (sizeof (struct saved_dir_info)); - tmp->path = malloc (strlen (skipcrud + current_file_name) + 1); + tmp = (struct saved_dir_info *) ck_malloc (sizeof (struct saved_dir_info)); + tmp->path = ck_malloc (strlen (skipcrud + current_file_name) + 1); strcpy (tmp->path, skipcrud + current_file_name); tmp->mode = hstat.st_mode; tmp->atime = hstat.st_atime; -- 2.45.2 From 604e1433aad6da97ec24d1a491743fcb64378dbb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:25 +0000 Subject: [PATCH 02/16] *** empty log message *** --- src/buffer.c | 11 +++++----- src/extract.c | 57 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 603bdc2..9024334 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -125,7 +125,7 @@ static int r_error_count; /* * Have we hit EOF yet? */ -static int eof; +static int hit_eof; /* JF we're reading, but we just read the last record and its time to update */ extern time_to_start_writing; @@ -153,8 +153,8 @@ static long real_s_sizeleft; void reset_eof() { - if(eof) { - eof=0; + if(hit_eof) { + hit_eof=0; ar_record=ar_block; ar_last=ar_block+blocking; ar_reading=0; @@ -170,11 +170,11 @@ union record * findrec() { if (ar_record == ar_last) { - if (eof) + if (hit_eof) return (union record *)NULL; /* EOF */ flush_archive(); if (ar_record == ar_last) { - eof++; + hit_eof++; return (union record *)NULL; /* EOF */ } } @@ -546,7 +546,6 @@ open_archive(reading) msg_perror("can't open %s",ar_file); exit(EX_BADARCH); } - #ifndef __MSDOS__ if(!_isrmt(archive)) { struct stat tmp_stat; diff --git a/src/extract.c b/src/extract.c index bea66ef..d162cab 100644 --- a/src/extract.c +++ b/src/extract.c @@ -680,16 +680,53 @@ extract_archive () skipcrud + current_file_name); } - if (f_modified) - goto set_filestat; - tmp = (struct saved_dir_info *) ck_malloc (sizeof (struct saved_dir_info)); - tmp->path = ck_malloc (strlen (skipcrud + current_file_name) + 1); - strcpy (tmp->path, skipcrud + current_file_name); - tmp->mode = hstat.st_mode; - tmp->atime = hstat.st_atime; - tmp->mtime = hstat.st_mtime; - tmp->next = saved_dir_info_head; - saved_dir_info_head = tmp; + /* + * If we are root, set the owner and group of the extracted + * file. This does what is wanted both on real Unix and on + * System V. If we are running as a user, we extract as that + * user; if running as root, we extract as the original owner. + */ + if (we_are_root || f_do_chown) + { + if (chown (skipcrud + current_file_name, + hstat.st_uid, hstat.st_gid) < 0) + { + msg_perror ("cannot chown file %s to uid %d gid %d", + skipcrud + current_file_name, + hstat.st_uid, hstat.st_gid); + } + } + + if (!f_modified) + { + tmp = ((struct saved_dir_info *) + ck_malloc (sizeof (struct saved_dir_info))); + tmp->path = (char *) ck_malloc (strlen (skipcrud + + current_file_name) + 1); + strcpy (tmp->path, skipcrud + current_file_name); + tmp->mode = hstat.st_mode; + tmp->atime = hstat.st_atime; + tmp->mtime = hstat.st_mtime; + tmp->next = saved_dir_info_head; + saved_dir_info_head = tmp; + } + else + { + /* This functions exactly as the code for set_filestat above. */ + if ((!f_keep) + || (hstat.st_mode & (S_ISUID | S_ISGID | S_ISVTX))) + { + if (chmod (skipcrud + current_file_name, + notumask & (int) hstat.st_mode) < 0) + { + msg_perror ("cannot change mode of file %s to %ld", + skipcrud + current_file_name, + notumask & (int) hstat.st_mode); + } + } + } + break; + case LF_VOLHDR: if (f_verbose) { -- 2.45.2 From a295fffa66203af9f85bcdcb2aa4af0537a40440 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:28 +0000 Subject: [PATCH 03/16] *** empty log message *** --- src/buffer.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++----- src/extract.c | 6 +++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 9024334..a159b16 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,5 +1,5 @@ /* Buffer management for tar. - Copyright (C) 1988 Free Software Foundation + Copyright (C) 1988, 1992 Free Software Foundation This file is part of GNU Tar. @@ -33,7 +33,7 @@ extern int errno; #include time_t time(); -#ifndef NO_MTIO +#ifdef HAVE_SYS_MTIO_H #include #include #endif @@ -127,6 +127,9 @@ static int r_error_count; */ static int hit_eof; +/* Checkpointing counter */ +static int checkpoint; + /* JF we're reading, but we just read the last record and its time to update */ extern time_to_start_writing; int file_to_switch_to= -1; /* If remote update, close archive, and use @@ -134,6 +137,7 @@ int file_to_switch_to= -1; /* If remote update, close archive, and use static int volno = 1; /* JF which volume of a multi-volume tape we're on */ +static int global_volno = 1; /* Volume number to print in external messages. */ char *save_name = 0; /* Name of the file we are currently writing */ long save_totsize; /* total size of file we are writing. Only @@ -650,6 +654,8 @@ fl_write() int copy_back; static long bytes_written = 0; + if (f_checkpoint && ! (++checkpoint % 10)) + msg ("Write checkpoint %d\n", checkpoint); if(tape_length && bytes_written >= tape_length * 1024) { errno = ENOSPC; err = 0; @@ -686,9 +692,11 @@ fl_write() /* We're multivol Panic if we didn't get the right kind of response */ /* ENXIO is for the UNIX PC */ - if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)) + if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO) writeerror(err); + /* If error indicates a short write, we just move to the next tape. */ + if(new_volume(0)<0) return; bytes_written=0; @@ -821,6 +829,9 @@ fl_read() int left; /* Bytes left */ char *more; /* Pointer to next byte to read */ + if (f_checkpoint && ! (++checkpoint % 10)) + msg ("Read checkpoint %d\n", checkpoint); + /* * Clear the count of errors. This only applies to a single * call to fl_read. We leave read_error_flag alone; it is @@ -872,7 +883,7 @@ error_loop: if (err == blocksize) return; - if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) { + if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) { union record *head; try_volume: @@ -903,6 +914,7 @@ error_loop: msg("Volume mismatch! %s!=%s",f_volhdr, head->header.name); --volno; + --global_volno; goto try_volume; } @@ -910,6 +922,7 @@ error_loop: if(strcmp(ptr,head->header.name)) { msg("Volume mismatch! %s!=%s",ptr,head->header.name); --volno; + --global_volno; free(ptr); goto try_volume; } @@ -929,6 +942,7 @@ error_loop: if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) { msg("%s is not continued on this volume!",real_s_name); --volno; + --global_volno; goto try_volume; } if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) { @@ -937,11 +951,13 @@ error_loop: from_oct(1+12,head->header.size), from_oct(1+12,head->header.offset)); --volno; + --global_volno; goto try_volume; } if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) { msg("This volume is out of sequence"); --volno; + --global_volno; goto try_volume; } head++; @@ -1187,6 +1203,39 @@ anno(stream, prefix, savedp) } #endif +/* Called to initialize the global volume number. */ +int +init_volume_number () +{ + FILE *vf; + + vf = fopen (f_volno_file, "r"); + if (!vf && errno != ENOENT) + msg_perror ("%s", f_volno_file); + + if (vf) + { + fscanf (vf, "%d", &global_volno); + fclose (vf); + } +} + +/* Called to write out the closing global volume number. */ +int +closeout_volume_number () +{ + FILE *vf; + + vf = fopen (f_volno_file, "w"); + if (!vf) + msg_perror ("%s", f_volno_file); + else + { + fprintf (vf, "%d\n", global_volno); + fclose (vf); + } +} + /* We've hit the end of the old volume. Close it and open the next one */ /* Values for type: 0: writing 1: reading 2: updating */ int @@ -1211,12 +1260,13 @@ int type; if((c=rmtclose(archive))<0) msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + global_volno++; volno++; tryagain: if (f_run_script_at_end) system(info_script); else for(;;) { - fprintf(msg_file,"\007Prepare volume #%d and hit return: ",volno); + fprintf(msg_file,"\007Prepare volume #%d and hit return: ",global_volno); fflush(msg_file); if(fgets(inbuf,sizeof(inbuf),read_file)==0) { fprintf(msg_file,"EOF? What does that mean?"); diff --git a/src/extract.c b/src/extract.c index d162cab..84e6a23 100644 --- a/src/extract.c +++ b/src/extract.c @@ -542,7 +542,7 @@ extract_archive () if (chmod (skipcrud + current_file_name, notumask & (int) hstat.st_mode) < 0) { - msg_perror ("cannot change mode of file %s to %ld", + msg_perror ("cannot change mode of file %s to %lo", skipcrud + current_file_name, notumask & (int) hstat.st_mode); } @@ -719,7 +719,7 @@ extract_archive () if (chmod (skipcrud + current_file_name, notumask & (int) hstat.st_mode) < 0) { - msg_perror ("cannot change mode of file %s to %ld", + msg_perror ("cannot change mode of file %s to %lo", skipcrud + current_file_name, notumask & (int) hstat.st_mode); } @@ -897,7 +897,7 @@ restore_saved_dir_info () if (chmod (saved_dir_info_head->path, notumask & saved_dir_info_head->mode) < 0) { - msg_perror ("cannot change mode of file %s to %ld", + msg_perror ("cannot change mode of file %s to %lo", saved_dir_info_head->path, notumask & saved_dir_info_head->mode); } -- 2.45.2 From 740b318ceadbc4bbe4141982ffe8f9f7191959ea Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:32 +0000 Subject: [PATCH 04/16] Initial revision --- src/buffer.c | 195 ++++++++++++++++++++------------------------------- 1 file changed, 77 insertions(+), 118 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index a159b16..f402374 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,5 +1,5 @@ /* Buffer management for tar. - Copyright (C) 1988, 1992 Free Software Foundation + Copyright (C) 1988 Free Software Foundation This file is part of GNU Tar. @@ -21,38 +21,34 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ * Buffer management for tar. * * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985. + * + * @(#) buffer.c 1.28 11/6/87 - gnu */ #include #include -#ifndef STDC_HEADERS -extern int errno; -#endif #include /* For non-Berkeley systems */ +#include #include -#include -time_t time(); -#ifdef HAVE_SYS_MTIO_H +#ifndef MSDOS #include +#if !defined(USG) || defined(HAVE_MTIO) #include #endif - -#ifdef BSD42 -#include -#else -#ifndef V7 -#include -#endif #endif -#ifdef __MSDOS__ +#ifdef MSDOS +# include #include +#else +# ifdef XENIX +# include +# endif +# include #endif -#ifdef XENIX -#include -#endif +extern int errno; #include "tar.h" #include "port.h" @@ -69,24 +65,45 @@ FILE *msg_file = stdout; #define PREAD 0 /* Read file descriptor from pipe() */ #define PWRITE 1 /* Write file descriptor from pipe() */ +#ifdef __STDC__ +extern void *malloc(); +extern void *valloc(); +#else +extern char *malloc(); +extern char *valloc(); +#endif +extern time_t time(); + +extern char *index(), *strcat(); +extern char *strcpy(); + +/* + * V7 doesn't have a #define for this. + */ +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif +#ifndef O_RDWR +#define O_RDWR 2 +#endif +#ifndef O_CREAT +#define O_CREAT 0 +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + #define MAGIC_STAT 105 /* Magic status returned by child, if it can't exec. We hope compress/sh never return this status! */ -char *valloc(); - void writeerror(); void readerror(); void ck_pipe(); void ck_close(); -int backspace_output(); extern void finish_header(); -void flush_archive(); -int isfile(); -int new_volume(); -void verify_volume(); extern void to_oct(); #ifndef __MSDOS__ @@ -125,10 +142,7 @@ static int r_error_count; /* * Have we hit EOF yet? */ -static int hit_eof; - -/* Checkpointing counter */ -static int checkpoint; +static int eof; /* JF we're reading, but we just read the last record and its time to update */ extern time_to_start_writing; @@ -137,7 +151,6 @@ int file_to_switch_to= -1; /* If remote update, close archive, and use static int volno = 1; /* JF which volume of a multi-volume tape we're on */ -static int global_volno = 1; /* Volume number to print in external messages. */ char *save_name = 0; /* Name of the file we are currently writing */ long save_totsize; /* total size of file we are writing. Only @@ -157,8 +170,8 @@ static long real_s_sizeleft; void reset_eof() { - if(hit_eof) { - hit_eof=0; + if(eof) { + eof=0; ar_record=ar_block; ar_last=ar_block+blocking; ar_reading=0; @@ -174,11 +187,11 @@ union record * findrec() { if (ar_record == ar_last) { - if (hit_eof) + if (eof) return (union record *)NULL; /* EOF */ flush_archive(); if (ar_record == ar_last) { - hit_eof++; + eof++; return (union record *)NULL; /* EOF */ } } @@ -245,11 +258,11 @@ dupto(from, to, msg) } } -#ifdef __MSDOS__ +#ifdef MSDOS void child_open() { - fprintf(stderr,"MS-DOS %s can't use compressed or remote archives\n",tar); + fprintf(stderr,"MSDOS %s can't use compressed or remote archives\n",tar); exit(EX_ARGSBAD); } #else @@ -461,7 +474,6 @@ child_open() /* return non-zero if p is the name of a directory */ -int isfile(p) char *p; { @@ -469,7 +481,7 @@ char *p; if(stat(p,&stbuf)<0) return 1; - if(S_ISREG(stbuf.st_mode)) + if((stbuf.st_mode&S_IFMT)==S_IFREG) return 1; return 0; } @@ -481,7 +493,6 @@ char *p; * reading or writing. */ /* JF if the arg is 2, open for reading and writing. */ -void open_archive(reading) int reading; { @@ -546,23 +557,23 @@ open_archive(reading) } else { archive = rmtcreat(ar_file, 0666); } - if (archive < 0) { - msg_perror("can't open %s",ar_file); - exit(EX_BADARCH); - } #ifndef __MSDOS__ if(!_isrmt(archive)) { struct stat tmp_stat; fstat(archive,&tmp_stat); - if(S_ISREG(tmp_stat.st_mode)) { + if((tmp_stat.st_mode&S_IFMT)==S_IFREG) { ar_dev=tmp_stat.st_dev; ar_ino=tmp_stat.st_ino; } } #endif -#ifdef __MSDOS__ + if (archive < 0) { + msg_perror("can't open %s",ar_file); + exit(EX_BADARCH); + } +#ifdef MSDOS setmode(archive, O_BINARY); #endif @@ -625,7 +636,6 @@ open_archive(reading) * adding (baserec+ar_record), doing a 9-bit shift of baserec, then * subtracting ar_block from that, shifting it back, losing the top 9 bits. */ -void saverec(pointer) union record **pointer; { @@ -647,15 +657,12 @@ saverec(pointer) } */ -void fl_write() { int err; int copy_back; static long bytes_written = 0; - if (f_checkpoint && ! (++checkpoint % 10)) - msg ("Write checkpoint %d\n", checkpoint); if(tape_length && bytes_written >= tape_length * 1024) { errno = ENOSPC; err = 0; @@ -676,7 +683,7 @@ fl_write() real_s_sizeleft = 0; return; } -#ifdef __MSDOS__ +#ifdef MSDOS if(save_name[1]==':') save_name+=2; #endif @@ -692,11 +699,9 @@ fl_write() /* We're multivol Panic if we didn't get the right kind of response */ /* ENXIO is for the UNIX PC */ - if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO) + if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)) writeerror(err); - /* If error indicates a short write, we just move to the next tape. */ - if(new_volume(0)<0) return; bytes_written=0; @@ -755,7 +760,7 @@ fl_write() else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back) real_s_name[0] = '\0'; else { -#ifdef __MSDOS__ +#ifdef MSDOS if(save_name[1]==':') save_name+=2; #endif @@ -822,16 +827,12 @@ readerror() /* * Perform a read to flush the buffer. */ -void fl_read() { int err; /* Result from system call */ int left; /* Bytes left */ char *more; /* Pointer to next byte to read */ - if (f_checkpoint && ! (++checkpoint % 10)) - msg ("Read checkpoint %d\n", checkpoint); - /* * Clear the count of errors. This only applies to a single * call to fl_read. We leave read_error_flag alone; it is @@ -858,7 +859,7 @@ fl_read() if(f_multivol) { if(save_name) { if(save_name!=real_s_name) { -#ifdef __MSDOS__ +#ifdef MSDOS if(save_name[1]==':') save_name+=2; #endif @@ -883,7 +884,7 @@ error_loop: if (err == blocksize) return; - if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) { + if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) { union record *head; try_volume: @@ -914,7 +915,6 @@ error_loop: msg("Volume mismatch! %s!=%s",f_volhdr, head->header.name); --volno; - --global_volno; goto try_volume; } @@ -922,7 +922,6 @@ error_loop: if(strcmp(ptr,head->header.name)) { msg("Volume mismatch! %s!=%s",ptr,head->header.name); --volno; - --global_volno; free(ptr); goto try_volume; } @@ -942,7 +941,6 @@ error_loop: if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) { msg("%s is not continued on this volume!",real_s_name); --volno; - --global_volno; goto try_volume; } if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) { @@ -951,13 +949,11 @@ error_loop: from_oct(1+12,head->header.size), from_oct(1+12,head->header.offset)); --volno; - --global_volno; goto try_volume; } if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) { msg("This volume is out of sequence"); --volno; - --global_volno; goto try_volume; } head++; @@ -1014,7 +1010,6 @@ error2loop: /* * Flush the current buffer to/from the archive. */ -void flush_archive() { int c; @@ -1046,7 +1041,6 @@ flush_archive() /* Backspace the archive descriptor by one blocks worth. If its a tape, MTIOCTOP will work. If its something else, we try to seek on it. If we can't seek, we lose! */ -int backspace_output() { long cur; @@ -1084,7 +1078,6 @@ backspace_output() /* * Close the archive file. */ -void close_archive() { int child; @@ -1094,11 +1087,12 @@ close_archive() if (time_to_start_writing || !ar_reading) flush_archive(); if(cmd_mode==CMD_DELETE) { - off_t pos; + long pos; pos = rmtlseek(archive,0L,1); -#ifndef __MSDOS__ - (void) ftruncate(archive,pos); +#ifndef MSDOS + /* FIXME does ftruncate really take an INT?! */ + (void) ftruncate(archive,(int)pos); #else (void)rmtwrite(archive,"",0); #endif @@ -1109,7 +1103,7 @@ close_archive() if((c=rmtclose(archive))<0) msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); -#ifndef __MSDOS__ +#ifndef MSDOS if (childpid) { /* * Loop waiting for the right child to die, or for @@ -1119,32 +1113,32 @@ close_archive() ; if (child != -1) { - switch (WTERMSIG(status)) { + switch (TERM_SIGNAL(status)) { case 0: /* Child voluntarily terminated -- but why? */ - if (WEXITSTATUS(status) == MAGIC_STAT) { + if (TERM_VALUE(status) == MAGIC_STAT) { exit(EX_SYSTEM);/* Child had trouble */ } - if (WEXITSTATUS(status) == (SIGPIPE + 128)) { + if (TERM_VALUE(status) == (SIGPIPE + 128)) { /* * /bin/sh returns this if its child * dies with SIGPIPE. 'Sok. */ break; - } else if (WEXITSTATUS(status)) + } else if (TERM_VALUE(status)) msg("child returned status %d", - WEXITSTATUS(status)); + TERM_VALUE(status)); case SIGPIPE: break; /* This is OK. */ default: msg("child died with signal %d%s", - WTERMSIG(status), - WIFCOREDUMPED(status)? " (core dumped)": ""); + TERM_SIGNAL(status), + TERM_COREDUMP(status)? " (core dumped)": ""); } } } -#endif /* __MSDOS__ */ +#endif /* MSDOS */ } @@ -1203,42 +1197,8 @@ anno(stream, prefix, savedp) } #endif -/* Called to initialize the global volume number. */ -int -init_volume_number () -{ - FILE *vf; - - vf = fopen (f_volno_file, "r"); - if (!vf && errno != ENOENT) - msg_perror ("%s", f_volno_file); - - if (vf) - { - fscanf (vf, "%d", &global_volno); - fclose (vf); - } -} - -/* Called to write out the closing global volume number. */ -int -closeout_volume_number () -{ - FILE *vf; - - vf = fopen (f_volno_file, "w"); - if (!vf) - msg_perror ("%s", f_volno_file); - else - { - fprintf (vf, "%d\n", global_volno); - fclose (vf); - } -} - /* We've hit the end of the old volume. Close it and open the next one */ /* Values for type: 0: writing 1: reading 2: updating */ -int new_volume(type) int type; { @@ -1260,13 +1220,12 @@ int type; if((c=rmtclose(archive))<0) msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); - global_volno++; volno++; tryagain: if (f_run_script_at_end) system(info_script); else for(;;) { - fprintf(msg_file,"\007Prepare volume #%d and hit return: ",global_volno); + fprintf(msg_file,"\007Prepare volume #%d and hit return: ",volno); fflush(msg_file); if(fgets(inbuf,sizeof(inbuf),read_file)==0) { fprintf(msg_file,"EOF? What does that mean?"); @@ -1317,7 +1276,7 @@ int type; break; case '!': -#ifdef __MSDOS__ +#ifdef MSDOS spawnl(P_WAIT,getenv("COMSPEC"),"-",0); #else /* JF this needs work! */ @@ -1353,7 +1312,7 @@ int type; msg_perror("can't open %s",ar_file); goto tryagain; } -#ifdef __MSDOS__ +#ifdef MSDOS setmode(archive,O_BINARY); #endif return 0; -- 2.45.2 From c59c86911b8af1e6fb469b444d5ee610c4753f6a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:40 +0000 Subject: [PATCH 05/16] *** empty log message *** --- src/buffer.c | 195 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 118 insertions(+), 77 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index f402374..eb38704 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1,5 +1,5 @@ /* Buffer management for tar. - Copyright (C) 1988 Free Software Foundation + Copyright (C) 1988, 1992 Free Software Foundation This file is part of GNU Tar. @@ -21,34 +21,38 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ * Buffer management for tar. * * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985. - * - * @(#) buffer.c 1.28 11/6/87 - gnu */ #include #include +#ifndef STDC_HEADERS +extern int errno; +#endif #include /* For non-Berkeley systems */ -#include #include +#include +time_t time(); -#ifndef MSDOS +#ifndef NO_MTIO #include -#if !defined(USG) || defined(HAVE_MTIO) #include #endif + +#ifdef BSD42 +#include +#else +#ifndef V7 +#include +#endif #endif -#ifdef MSDOS -# include +#ifdef __MSDOS__ #include -#else -# ifdef XENIX -# include -# endif -# include #endif -extern int errno; +#ifdef XENIX +#include +#endif #include "tar.h" #include "port.h" @@ -65,45 +69,24 @@ FILE *msg_file = stdout; #define PREAD 0 /* Read file descriptor from pipe() */ #define PWRITE 1 /* Write file descriptor from pipe() */ -#ifdef __STDC__ -extern void *malloc(); -extern void *valloc(); -#else -extern char *malloc(); -extern char *valloc(); -#endif -extern time_t time(); - -extern char *index(), *strcat(); -extern char *strcpy(); - -/* - * V7 doesn't have a #define for this. - */ -#ifndef O_RDONLY -#define O_RDONLY 0 -#endif -#ifndef O_RDWR -#define O_RDWR 2 -#endif -#ifndef O_CREAT -#define O_CREAT 0 -#endif -#ifndef O_BINARY -#define O_BINARY 0 -#endif - #define MAGIC_STAT 105 /* Magic status returned by child, if it can't exec. We hope compress/sh never return this status! */ +char *valloc(); + void writeerror(); void readerror(); void ck_pipe(); void ck_close(); +int backspace_output(); extern void finish_header(); +void flush_archive(); +int isfile(); +int new_volume(); +void verify_volume(); extern void to_oct(); #ifndef __MSDOS__ @@ -142,7 +125,10 @@ static int r_error_count; /* * Have we hit EOF yet? */ -static int eof; +static int hit_eof; + +/* Checkpointing counter */ +static int checkpoint; /* JF we're reading, but we just read the last record and its time to update */ extern time_to_start_writing; @@ -151,6 +137,7 @@ int file_to_switch_to= -1; /* If remote update, close archive, and use static int volno = 1; /* JF which volume of a multi-volume tape we're on */ +static int global_volno = 1; /* Volume number to print in external messages. */ char *save_name = 0; /* Name of the file we are currently writing */ long save_totsize; /* total size of file we are writing. Only @@ -170,8 +157,8 @@ static long real_s_sizeleft; void reset_eof() { - if(eof) { - eof=0; + if(hit_eof) { + hit_eof=0; ar_record=ar_block; ar_last=ar_block+blocking; ar_reading=0; @@ -187,11 +174,11 @@ union record * findrec() { if (ar_record == ar_last) { - if (eof) + if (hit_eof) return (union record *)NULL; /* EOF */ flush_archive(); if (ar_record == ar_last) { - eof++; + hit_eof++; return (union record *)NULL; /* EOF */ } } @@ -258,11 +245,11 @@ dupto(from, to, msg) } } -#ifdef MSDOS +#ifdef __MSDOS__ void child_open() { - fprintf(stderr,"MSDOS %s can't use compressed or remote archives\n",tar); + fprintf(stderr,"MS-DOS %s can't use compressed or remote archives\n",tar); exit(EX_ARGSBAD); } #else @@ -474,6 +461,7 @@ child_open() /* return non-zero if p is the name of a directory */ +int isfile(p) char *p; { @@ -481,7 +469,7 @@ char *p; if(stat(p,&stbuf)<0) return 1; - if((stbuf.st_mode&S_IFMT)==S_IFREG) + if(S_ISREG(stbuf.st_mode)) return 1; return 0; } @@ -493,6 +481,7 @@ char *p; * reading or writing. */ /* JF if the arg is 2, open for reading and writing. */ +void open_archive(reading) int reading; { @@ -557,23 +546,23 @@ open_archive(reading) } else { archive = rmtcreat(ar_file, 0666); } + if (archive < 0) { + msg_perror("can't open %s",ar_file); + exit(EX_BADARCH); + } #ifndef __MSDOS__ if(!_isrmt(archive)) { struct stat tmp_stat; fstat(archive,&tmp_stat); - if((tmp_stat.st_mode&S_IFMT)==S_IFREG) { + if(S_ISREG(tmp_stat.st_mode)) { ar_dev=tmp_stat.st_dev; ar_ino=tmp_stat.st_ino; } } #endif - if (archive < 0) { - msg_perror("can't open %s",ar_file); - exit(EX_BADARCH); - } -#ifdef MSDOS +#ifdef __MSDOS__ setmode(archive, O_BINARY); #endif @@ -636,6 +625,7 @@ open_archive(reading) * adding (baserec+ar_record), doing a 9-bit shift of baserec, then * subtracting ar_block from that, shifting it back, losing the top 9 bits. */ +void saverec(pointer) union record **pointer; { @@ -657,12 +647,15 @@ saverec(pointer) } */ +void fl_write() { int err; int copy_back; static long bytes_written = 0; + if (f_checkpoint && ! (++checkpoint % 10)) + msg ("Write checkpoint %d\n", checkpoint); if(tape_length && bytes_written >= tape_length * 1024) { errno = ENOSPC; err = 0; @@ -683,7 +676,7 @@ fl_write() real_s_sizeleft = 0; return; } -#ifdef MSDOS +#ifdef __MSDOS__ if(save_name[1]==':') save_name+=2; #endif @@ -699,9 +692,11 @@ fl_write() /* We're multivol Panic if we didn't get the right kind of response */ /* ENXIO is for the UNIX PC */ - if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO)) + if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO) writeerror(err); + /* If error indicates a short write, we just move to the next tape. */ + if(new_volume(0)<0) return; bytes_written=0; @@ -760,7 +755,7 @@ fl_write() else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back) real_s_name[0] = '\0'; else { -#ifdef MSDOS +#ifdef __MSDOS__ if(save_name[1]==':') save_name+=2; #endif @@ -827,12 +822,16 @@ readerror() /* * Perform a read to flush the buffer. */ +void fl_read() { int err; /* Result from system call */ int left; /* Bytes left */ char *more; /* Pointer to next byte to read */ + if (f_checkpoint && ! (++checkpoint % 10)) + msg ("Read checkpoint %d\n", checkpoint); + /* * Clear the count of errors. This only applies to a single * call to fl_read. We leave read_error_flag alone; it is @@ -859,7 +858,7 @@ fl_read() if(f_multivol) { if(save_name) { if(save_name!=real_s_name) { -#ifdef MSDOS +#ifdef __MSDOS__ if(save_name[1]==':') save_name+=2; #endif @@ -884,7 +883,7 @@ error_loop: if (err == blocksize) return; - if((err == 0 || (err<0 && errno==ENOSPC)) && f_multivol) { + if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) { union record *head; try_volume: @@ -915,6 +914,7 @@ error_loop: msg("Volume mismatch! %s!=%s",f_volhdr, head->header.name); --volno; + --global_volno; goto try_volume; } @@ -922,6 +922,7 @@ error_loop: if(strcmp(ptr,head->header.name)) { msg("Volume mismatch! %s!=%s",ptr,head->header.name); --volno; + --global_volno; free(ptr); goto try_volume; } @@ -941,6 +942,7 @@ error_loop: if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) { msg("%s is not continued on this volume!",real_s_name); --volno; + --global_volno; goto try_volume; } if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) { @@ -949,11 +951,13 @@ error_loop: from_oct(1+12,head->header.size), from_oct(1+12,head->header.offset)); --volno; + --global_volno; goto try_volume; } if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) { msg("This volume is out of sequence"); --volno; + --global_volno; goto try_volume; } head++; @@ -1010,6 +1014,7 @@ error2loop: /* * Flush the current buffer to/from the archive. */ +void flush_archive() { int c; @@ -1041,6 +1046,7 @@ flush_archive() /* Backspace the archive descriptor by one blocks worth. If its a tape, MTIOCTOP will work. If its something else, we try to seek on it. If we can't seek, we lose! */ +int backspace_output() { long cur; @@ -1078,6 +1084,7 @@ backspace_output() /* * Close the archive file. */ +void close_archive() { int child; @@ -1087,12 +1094,11 @@ close_archive() if (time_to_start_writing || !ar_reading) flush_archive(); if(cmd_mode==CMD_DELETE) { - long pos; + off_t pos; pos = rmtlseek(archive,0L,1); -#ifndef MSDOS - /* FIXME does ftruncate really take an INT?! */ - (void) ftruncate(archive,(int)pos); +#ifndef __MSDOS__ + (void) ftruncate(archive,pos); #else (void)rmtwrite(archive,"",0); #endif @@ -1103,7 +1109,7 @@ close_archive() if((c=rmtclose(archive))<0) msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); -#ifndef MSDOS +#ifndef __MSDOS__ if (childpid) { /* * Loop waiting for the right child to die, or for @@ -1113,32 +1119,32 @@ close_archive() ; if (child != -1) { - switch (TERM_SIGNAL(status)) { + switch (WTERMSIG(status)) { case 0: /* Child voluntarily terminated -- but why? */ - if (TERM_VALUE(status) == MAGIC_STAT) { + if (WEXITSTATUS(status) == MAGIC_STAT) { exit(EX_SYSTEM);/* Child had trouble */ } - if (TERM_VALUE(status) == (SIGPIPE + 128)) { + if (WEXITSTATUS(status) == (SIGPIPE + 128)) { /* * /bin/sh returns this if its child * dies with SIGPIPE. 'Sok. */ break; - } else if (TERM_VALUE(status)) + } else if (WEXITSTATUS(status)) msg("child returned status %d", - TERM_VALUE(status)); + WEXITSTATUS(status)); case SIGPIPE: break; /* This is OK. */ default: msg("child died with signal %d%s", - TERM_SIGNAL(status), - TERM_COREDUMP(status)? " (core dumped)": ""); + WTERMSIG(status), + WIFCOREDUMPED(status)? " (core dumped)": ""); } } } -#endif /* MSDOS */ +#endif /* __MSDOS__ */ } @@ -1197,8 +1203,42 @@ anno(stream, prefix, savedp) } #endif +/* Called to initialize the global volume number. */ +int +init_volume_number () +{ + FILE *vf; + + vf = fopen (f_volno_file, "r"); + if (!vf && errno != ENOENT) + msg_perror ("%s", f_volno_file); + + if (vf) + { + fscanf (vf, "%d", &global_volno); + fclose (vf); + } +} + +/* Called to write out the closing global volume number. */ +int +closeout_volume_number () +{ + FILE *vf; + + vf = fopen (f_volno_file, "w"); + if (!vf) + msg_perror ("%s", f_volno_file); + else + { + fprintf (vf, "%d\n", global_volno); + fclose (vf); + } +} + /* We've hit the end of the old volume. Close it and open the next one */ /* Values for type: 0: writing 1: reading 2: updating */ +int new_volume(type) int type; { @@ -1220,12 +1260,13 @@ int type; if((c=rmtclose(archive))<0) msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + global_volno++; volno++; tryagain: if (f_run_script_at_end) system(info_script); else for(;;) { - fprintf(msg_file,"\007Prepare volume #%d and hit return: ",volno); + fprintf(msg_file,"\007Prepare volume #%d and hit return: ",global_volno); fflush(msg_file); if(fgets(inbuf,sizeof(inbuf),read_file)==0) { fprintf(msg_file,"EOF? What does that mean?"); @@ -1276,7 +1317,7 @@ int type; break; case '!': -#ifdef MSDOS +#ifdef __MSDOS__ spawnl(P_WAIT,getenv("COMSPEC"),"-",0); #else /* JF this needs work! */ @@ -1312,7 +1353,7 @@ int type; msg_perror("can't open %s",ar_file); goto tryagain; } -#ifdef MSDOS +#ifdef __MSDOS__ setmode(archive,O_BINARY); #endif return 0; -- 2.45.2 From f0ee8aa69ea34b9f6601877a03d70a32faa4b44a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:46 +0000 Subject: [PATCH 06/16] *** empty log message *** --- src/buffer.c | 218 +++++++++++++++++++++++++++------------------------ 1 file changed, 117 insertions(+), 101 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index eb38704..e98ec04 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -33,7 +33,7 @@ extern int errno; #include time_t time(); -#ifndef NO_MTIO +#ifdef HAVE_SYS_MTIO_H #include #include #endif @@ -258,6 +258,7 @@ child_open() { int pipe[2]; int err = 0; + int nar; int kidpipe[2]; int kidchildpid; @@ -301,24 +302,24 @@ child_open() 2: the file is to be accessed by rmt (compress doesn't know how) 3: the file is not a plain file */ #ifdef NO_REMOTE - if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file)) + if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && isfile(ar_files[0])) #else - if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file)) + if(!(ar_files[0][0]=='-' && ar_file[0][1]=='\0') && !_remdev(ar_files[0]) && isfile(ar_files[0])) #endif { /* We don't need a child tar. Open the archive */ if(ar_reading) { - archive=open(ar_file, O_RDONLY|O_BINARY, 0666); + archive=open(ar_files[0], O_RDONLY|O_BINARY, 0666); if(archive<0) { - msg_perror("can't open archive %s",ar_file); + msg_perror("can't open archive %s",ar_files[0]); exit(EX_BADARCH); } dupto(archive,STDIN,"archive to stdin"); /* close(archive); */ } else { - archive=creat(ar_file,0666); + archive=creat(ar_files[0],0666); if(archive<0) { - msg_perror("can't open archive %s",ar_file); + msg_perror("can't open archive %s",ar_files[0]); exit(EX_BADARCH); } dupto(archive,STDOUT,"archive to stdout"); @@ -367,14 +368,14 @@ child_open() else archive = STDOUT; } else /* This can't happen if (ar_reading==2) - archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666); + archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666); else */if(ar_reading) - archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666); + archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666); else - archive = rmtcreat(ar_file, 0666); + archive = rmtcreat(ar_files[0], 0666); if (archive < 0) { - msg_perror("can't open archive %s",ar_file); + msg_perror("can't open archive %s",ar_files[0]); exit(EX_BADARCH); } @@ -492,7 +493,7 @@ open_archive(reading) exit(EX_ARGSBAD); } - if(ar_file==0) { + if(n_ar_files==0) { msg("No archive name given, what should I do?"); exit(EX_BADARCH); } @@ -519,11 +520,15 @@ open_archive(reading) msg("cannot update or verify compressed archives"); exit(EX_ARGSBAD); } + if (f_multivol) { + msg ("cannot use multi-volume compressed archives"); + exit (EX_ARGSBAD); + } child_open(); - if(!reading && ar_file[0]=='-' && ar_file[1]=='\0') + if(!reading && ar_files[0][0]=='-' && ar_files[0][1]=='\0') msg_file = stderr; /* child_open(rem_host, rem_file); */ - } else if (ar_file[0] == '-' && ar_file[1] == '\0') { + } else if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') { f_reblock++; /* Could be a pipe, be safe */ if(f_verify) { msg("can't verify stdin/stdout archive"); @@ -540,14 +545,14 @@ open_archive(reading) msg_file = stderr; } } else if (reading==2 || f_verify) { - archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666); + archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666); } else if(reading) { - archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666); + archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666); } else { - archive = rmtcreat(ar_file, 0666); + archive = rmtcreat(ar_files[0], 0666); } if (archive < 0) { - msg_perror("can't open %s",ar_file); + msg_perror("can't open %s",ar_files[0]); exit(EX_BADARCH); } #ifndef __MSDOS__ @@ -779,10 +784,10 @@ writeerror(err) int err; { if (err < 0) { - msg_perror("can't write to %s",ar_file); + msg_perror("can't write to %s",ar_files[cur_ar_file]); exit(EX_BADARCH); } else { - msg("only wrote %u of %u bytes to %s",err,blocksize,ar_file); + msg("only wrote %u of %u bytes to %s",err,blocksize,ar_files[cur_ar_file]); exit(EX_BADARCH); } } @@ -799,7 +804,7 @@ readerror() read_error_flag++; /* Tell callers */ - msg_perror("read error on %s",ar_file); + msg_perror("read error on %s",ar_files[cur_ar_file]); if (baserec == 0) { /* First block of tape. Probably stupidity error */ @@ -997,7 +1002,7 @@ error2loop: goto error2loop; /* Try again */ } if (err == 0) { - msg("archive %s EOF not on block boundary",ar_file); + msg("archive %s EOF not on block boundary",ar_files[cur_ar_file]); exit(EX_BADARCH); } left -= err; @@ -1005,7 +1010,7 @@ error2loop: goto again; } } else { - msg("only read %d bytes from archive %s",err,ar_file); + msg("only read %d bytes from archive %s",err,ar_files[cur_ar_file]); exit(EX_BADARCH); } } @@ -1030,7 +1035,7 @@ flush_archive() if(file_to_switch_to>=0) { if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); archive=file_to_switch_to; } else @@ -1107,7 +1112,7 @@ close_archive() verify_volume(); if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); #ifndef __MSDOS__ if (childpid) { @@ -1249,6 +1254,7 @@ int type; extern int now_verifying; extern char TTY_NAME[]; char *getenv(); + static int looped = 0; if(!read_file && !f_run_script_at_end) read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin; @@ -1258,99 +1264,109 @@ int type; if(f_verify) verify_volume(); if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c); + msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); global_volno++; volno++; + cur_ar_file++; + if (cur_ar_file == n_ar_files) + { + cur_ar_file = 0; + looped = 1; + } + tryagain: - if (f_run_script_at_end) - system(info_script); - else for(;;) { - fprintf(msg_file,"\007Prepare volume #%d and hit return: ",global_volno); - fflush(msg_file); - if(fgets(inbuf,sizeof(inbuf),read_file)==0) { - fprintf(msg_file,"EOF? What does that mean?"); - if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) - msg("Warning: Archive is INCOMPLETE!"); - exit(EX_BADARCH); - } - if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y') - break; - - switch(inbuf[0]) { - case '?': - { - fprintf(msg_file,"\ + if (looped) + { + /* We have to prompt from now on. */ + if (f_run_script_at_end) + system(info_script); + else for(;;) { + fprintf(msg_file,"\007Prepare volume #%d for %s and hit return: ",global_volno, ar_files[cur_ar_file]); + fflush(msg_file); + if(fgets(inbuf,sizeof(inbuf),read_file)==0) { + fprintf(msg_file,"EOF? What does that mean?"); + if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) + msg("Warning: Archive is INCOMPLETE!"); + exit(EX_BADARCH); + } + if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y') + break; + + switch(inbuf[0]) { + case '?': + { + fprintf(msg_file,"\ n [name] Give a new filename for the next (and subsequent) volume(s)\n\ q Abort tar\n\ ! Spawn a subshell\n\ ? Print this list\n"); - } - break; - - case 'q': /* Quit */ - fprintf(msg_file,"No new volume; exiting.\n"); - if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) - msg("Warning: Archive is INCOMPLETE!"); - exit(EX_BADARCH); - - case 'n': /* Get new file name */ - { - char *q,*r; - static char *old_name; - - for(q= &inbuf[1];*q==' ' || *q=='\t';q++) - ; - for(r=q;*r;r++) - if(*r=='\n') - *r='\0'; - if(old_name) - free(old_name); - old_name=p=(char *)malloc((unsigned)(strlen(q)+2)); - if(p==0) { - msg("Can't allocate memory for name"); - exit(EX_SYSTEM); - } - (void) strcpy(p,q); - ar_file=p; - } - break; - - case '!': -#ifdef __MSDOS__ - spawnl(P_WAIT,getenv("COMSPEC"),"-",0); -#else - /* JF this needs work! */ - switch(fork()) { - case -1: - msg_perror("can't fork!"); - break; - case 0: - p=getenv("SHELL"); - if(p==0) p="/bin/sh"; - execlp(p,"-sh","-i",0); - msg_perror("can't exec a shell %s",p); - _exit(55); - default: - wait(0); - break; - } -#endif - break; - } + } + break; + + case 'q': /* Quit */ + fprintf(msg_file,"No new volume; exiting.\n"); + if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) + msg("Warning: Archive is INCOMPLETE!"); + exit(EX_BADARCH); + + case 'n': /* Get new file name */ + { + char *q,*r; + static char *old_name; + + for(q= &inbuf[1];*q==' ' || *q=='\t';q++) + ; + for(r=q;*r;r++) + if(*r=='\n') + *r='\0'; + old_name=p=(char *)malloc((unsigned)(strlen(q)+2)); + if(p==0) { + msg("Can't allocate memory for name"); + exit(EX_SYSTEM); + } + (void) strcpy(p,q); + ar_files[cur_ar_file]=p; + } + break; + + case '!': + #ifdef __MSDOS__ + spawnl(P_WAIT,getenv("COMSPEC"),"-",0); + #else + /* JF this needs work! */ + switch(fork()) { + case -1: + msg_perror("can't fork!"); + break; + case 0: + p=getenv("SHELL"); + if(p==0) p="/bin/sh"; + execlp(p,"-sh","-i",0); + msg_perror("can't exec a shell %s",p); + _exit(55); + default: + wait(0); + break; + } + #endif + break; + } + } } + if(type==2 || f_verify) - archive=rmtopen(ar_file,O_RDWR|O_CREAT,0666); + archive=rmtopen(ar_files[cur_ar_file],O_RDWR|O_CREAT,0666); else if(type==1) - archive=rmtopen(ar_file,O_RDONLY,0666); + archive=rmtopen(ar_files[cur_ar_file],O_RDONLY,0666); else if(type==0) - archive=rmtcreat(ar_file,0666); + archive=rmtcreat(ar_file[cur_ar_file],0666); else archive= -1; if(archive<0) { - msg_perror("can't open %s",ar_file); + msg_perror("can't open %s",ar_files[cur_ar_file]); goto tryagain; } #ifdef __MSDOS__ -- 2.45.2 From 9e7c78e78d927d8c2877841c3f10a4d630e4453d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:48 +0000 Subject: [PATCH 07/16] *** empty log message *** --- src/buffer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/buffer.c b/src/buffer.c index e98ec04..72071df 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -515,6 +515,12 @@ open_archive(reading) ar_last = ar_block + blocking; ar_reading = reading; + if (f_multivol && f_verify) + { + msg ("cannot verify multi-volume archives"); + exit (EX_ARGSBAD); + } + if (f_compress) { if(reading==2 || f_verify) { msg("cannot update or verify compressed archives"); -- 2.45.2 From 3da5aa697398db08cc73ea2ffcc71373f9f2fff2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:51 +0000 Subject: [PATCH 08/16] *** empty log message *** --- src/buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 72071df..4f19bb7 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -304,7 +304,7 @@ child_open() #ifdef NO_REMOTE if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && isfile(ar_files[0])) #else - if(!(ar_files[0][0]=='-' && ar_file[0][1]=='\0') && !_remdev(ar_files[0]) && isfile(ar_files[0])) + if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && !_remdev(ar_files[0]) && isfile(ar_files[0])) #endif { /* We don't need a child tar. Open the archive */ @@ -362,7 +362,7 @@ child_open() ck_close(kidpipe[WRITE]); } - if (ar_file[0] == '-' && ar_file[1] == '\0') { + if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') { if (ar_reading) archive = STDIN; else @@ -1367,7 +1367,7 @@ int type; else if(type==1) archive=rmtopen(ar_files[cur_ar_file],O_RDONLY,0666); else if(type==0) - archive=rmtcreat(ar_file[cur_ar_file],0666); + archive=rmtcreat(ar_files[cur_ar_file],0666); else archive= -1; -- 2.45.2 From 0eceef9ba14ca872e57ecd2f4ca4f5893b78bac8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:54 +0000 Subject: [PATCH 09/16] *** empty log message *** --- src/buffer.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 4f19bb7..f2b2d64 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -597,10 +597,10 @@ open_archive(reading) msg("Archive not labelled to match %s",f_volhdr); exit(EX_BADVOL); } - if (re_match (label_pattern, head->header.name, - strlen (head->header.name), 0, 0) < 0) { + if (re_match (label_pattern, head->header.arch_name, + strlen (head->header.arch_name), 0, 0) < 0) { msg ("Volume mismatch! %s!=%s", f_volhdr, - head->header.name); + head->header.arch_name); exit (EX_BADVOL); } #if 0 @@ -615,9 +615,9 @@ open_archive(reading) } else if(f_volhdr) { bzero((void *)ar_block,RECORDSIZE); if(f_multivol) - sprintf(ar_block->header.name,"%s Volume 1",f_volhdr); + sprintf(ar_block->header.arch_name,"%s Volume 1",f_volhdr); else - strcpy(ar_block->header.name,f_volhdr); + strcpy(ar_block->header.arch_name,f_volhdr); ar_block->header.linkflag = LF_VOLHDR; to_oct(time(0), 1+12, ar_block->header.mtime); finish_header(ar_block); @@ -721,7 +721,7 @@ fl_write() copy_back = 0; if(f_volhdr) { bzero((void *)ar_block,RECORDSIZE); - sprintf(ar_block->header.name,"%s Volume %d",f_volhdr,volno); + sprintf(ar_block->header.arch_name,"%s Volume %d",f_volhdr,volno); to_oct(time(0), 1+12, ar_block->header.mtime); ar_block->header.linkflag = LF_VOLHDR; finish_header(ar_block); @@ -732,7 +732,7 @@ fl_write() if(f_volhdr) ar_block++; bzero((void *)ar_block,RECORDSIZE); - strcpy(ar_block->header.name,real_s_name); + strcpy(ar_block->header.arch_name,real_s_name); ar_block->header.linkflag = LF_MULTIVOL; to_oct((long)real_s_sizeleft,1+12, ar_block->header.size); @@ -919,11 +919,11 @@ error_loop: ptr=(char *)malloc(strlen(f_volhdr)+20); sprintf(ptr,"%s Volume %d",f_volhdr,volno); #endif - if (re_match (label_pattern, head->header.name, - strlen (head->header.name), + if (re_match (label_pattern, head->header.arch_name, + strlen (head->header.arch_name), 0, 0) < 0) { msg("Volume mismatch! %s!=%s",f_volhdr, - head->header.name); + head->header.arch_name); --volno; --global_volno; goto try_volume; @@ -941,7 +941,7 @@ error_loop: #endif } if(f_verbose) - fprintf(msg_file,"Reading %s\n",head->header.name); + fprintf(msg_file,"Reading %s\n",head->header.arch_name); head++; } else if(f_volhdr) { msg("Warning: No volume header!"); @@ -950,7 +950,7 @@ error_loop: if(real_s_name[0]) { long from_oct(); - if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) { + if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.arch_name,real_s_name)) { msg("%s is not continued on this volume!",real_s_name); --volno; --global_volno; @@ -958,7 +958,7 @@ error_loop: } if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) { msg("%s is the wrong size (%ld!=%ld+%ld)", - head->header.name,save_totsize, + head->header.arch_name,save_totsize, from_oct(1+12,head->header.size), from_oct(1+12,head->header.offset)); --volno; -- 2.45.2 From 80df629d39d677964c6299d6d2b033920b734a05 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:46:57 +0000 Subject: [PATCH 10/16] *** empty log message *** --- src/buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index f2b2d64..737c5dd 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1337,9 +1337,9 @@ int type; break; case '!': - #ifdef __MSDOS__ +#ifdef __MSDOS__ spawnl(P_WAIT,getenv("COMSPEC"),"-",0); - #else +#else /* JF this needs work! */ switch(fork()) { case -1: @@ -1355,7 +1355,7 @@ int type; wait(0); break; } - #endif +#endif break; } } -- 2.45.2 From 1cc1540ea0e08c375d42ef6ef6060872810c273d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:47:00 +0000 Subject: [PATCH 11/16] *** empty log message *** --- src/buffer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/buffer.c b/src/buffer.c index 737c5dd..eb153fa 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1259,7 +1259,6 @@ int type; static FILE *read_file = 0; extern int now_verifying; extern char TTY_NAME[]; - char *getenv(); static int looped = 0; if(!read_file && !f_run_script_at_end) -- 2.45.2 From 570ead1f48e5e9c934f9aa7601c6fe60d6266ead Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:47:03 +0000 Subject: [PATCH 12/16] *** empty log message *** --- src/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/buffer.c b/src/buffer.c index eb153fa..2be44e8 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -73,7 +73,7 @@ FILE *msg_file = stdout; it can't exec. We hope compress/sh never return this status! */ -char *valloc(); +void *valloc(); void writeerror(); void readerror(); -- 2.45.2 From 4156fce552a004e11845a17e1e3e897aaf367028 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:47:05 +0000 Subject: [PATCH 13/16] *** empty log message *** --- src/buffer.c | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 2be44e8..c16ceba 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1130,30 +1130,31 @@ close_archive() ; if (child != -1) { - switch (WTERMSIG(status)) { - case 0: - /* Child voluntarily terminated -- but why? */ - if (WEXITSTATUS(status) == MAGIC_STAT) { - exit(EX_SYSTEM);/* Child had trouble */ - } - if (WEXITSTATUS(status) == (SIGPIPE + 128)) { - /* - * /bin/sh returns this if its child - * dies with SIGPIPE. 'Sok. - */ - break; - } else if (WEXITSTATUS(status)) - msg("child returned status %d", - WEXITSTATUS(status)); - case SIGPIPE: - break; /* This is OK. */ - - default: - msg("child died with signal %d%s", - WTERMSIG(status), - WIFCOREDUMPED(status)? " (core dumped)": ""); + { + if (WIFSIGNALED(status)) + { + /* SIGPIPE is OK, everything else is a problem. */ + if (WTERMSIG (status) != SIGPIPE) + msg("child died with signal %d%s", WTERMSIG(status), + WIFCOREDUMPED(status)? " (core dumped)": ""); + } + else + { + /* Child voluntarily terminated -- but why? */ + if (WEXITSTATUS(status) == MAGIC_STAT) { + exit(EX_SYSTEM);/* Child had trouble */ } - } + if (WEXITSTATUS(status) == (SIGPIPE + 128)) { + /* + * /bin/sh returns this if its child + * dies with SIGPIPE. 'Sok. + */ + break; + } else if (WEXITSTATUS(status)) + msg("child returned status %d", + WEXITSTATUS(status)); + } + } } #endif /* __MSDOS__ */ } -- 2.45.2 From 474bce237b31fb74928557de16fedea9fd61407f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:47:08 +0000 Subject: [PATCH 14/16] *** empty log message *** --- src/buffer.c | 2094 +++++++++++++++++++++++++++----------------------- 1 file changed, 1125 insertions(+), 969 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index c16ceba..5c1b808 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -31,7 +31,7 @@ extern int errno; #include /* For non-Berkeley systems */ #include #include -time_t time(); +time_t time (); #ifdef HAVE_SYS_MTIO_H #include @@ -73,21 +73,21 @@ FILE *msg_file = stdout; it can't exec. We hope compress/sh never return this status! */ -void *valloc(); +void *valloc (); -void writeerror(); -void readerror(); +void writeerror (); +void readerror (); -void ck_pipe(); -void ck_close(); +void ck_pipe (); +void ck_close (); -int backspace_output(); -extern void finish_header(); -void flush_archive(); -int isfile(); -int new_volume(); -void verify_volume(); -extern void to_oct(); +int backspace_output (); +extern void finish_header (); +void flush_archive (); +int isfile (); +int new_volume (); +void verify_volume (); +extern void to_oct (); #ifndef __MSDOS__ /* Obnoxious test to see if dimwit is trying to dump the archive */ @@ -104,35 +104,35 @@ ino_t ar_ino; * header record. */ static union record **save_rec; - union record record_save_area; -static long saved_recno; +union record record_save_area; +static long saved_recno; /* * PID of child program, if f_compress or remote archive access. */ -static int childpid = 0; +static int childpid = 0; /* * Record number of the start of this block of records */ -long baserec; +long baserec; /* * Error recovery stuff */ -static int r_error_count; +static int r_error_count; /* * Have we hit EOF yet? */ -static int hit_eof; +static int hit_eof; /* Checkpointing counter */ static int checkpoint; /* JF we're reading, but we just read the last record and its time to update */ extern time_to_start_writing; -int file_to_switch_to= -1; /* If remote update, close archive, and use +int file_to_switch_to = -1; /* If remote update, close archive, and use this descriptor to write to */ static int volno = 1; /* JF which volume of a multi-volume tape @@ -155,14 +155,15 @@ static long real_s_sizeleft; /* Reset the EOF flag (if set), and re-set ar_record, etc */ void -reset_eof() +reset_eof () { - if(hit_eof) { - hit_eof=0; - ar_record=ar_block; - ar_last=ar_block+blocking; - ar_reading=0; - } + if (hit_eof) + { + hit_eof = 0; + ar_record = ar_block; + ar_last = ar_block + blocking; + ar_reading = 0; + } } /* @@ -171,18 +172,20 @@ reset_eof() * it, to avoid accidentally going on to the next file on the "tape". */ union record * -findrec() +findrec () { - if (ar_record == ar_last) { - if (hit_eof) - return (union record *)NULL; /* EOF */ - flush_archive(); - if (ar_record == ar_last) { - hit_eof++; - return (union record *)NULL; /* EOF */ - } + if (ar_record == ar_last) + { + if (hit_eof) + return (union record *) NULL; /* EOF */ + flush_archive (); + if (ar_record == ar_last) + { + hit_eof++; + return (union record *) NULL; /* EOF */ } - return ar_record; + } + return ar_record; } @@ -191,19 +194,19 @@ findrec() * (should the arg have an off-by-1? XXX FIXME) */ void -userec(rec) - union record *rec; +userec (rec) + union record *rec; { - while(rec >= ar_record) - ar_record++; - /* + while (rec >= ar_record) + ar_record++; + /* * Do NOT flush the archive here. If we do, the same * argument to userec() could mean the next record (if the * input block is exactly one record long), which is not what * is intended. */ - if (ar_record > ar_last) - abort(); + if (ar_record > ar_last) + abort (); } @@ -213,9 +216,9 @@ userec(rec) * for filling with data, or taking data from. */ union record * -endofrecs() +endofrecs () { - return ar_last; + return ar_last; } @@ -224,255 +227,300 @@ endofrecs() * Equivalent to BSD "dup2" with error reporting. */ void -dupto(from, to, msg) - int from, to; - char *msg; +dupto (from, to, msg) + int from, to; + char *msg; { - int err; + int err; - if (from != to) { - err=close(to); - if(err<0 && errno!=EBADF) { - msg_perror("Cannot close descriptor %d",to); - exit(EX_SYSTEM); - } - err = dup(from); - if (err != to) { - msg_perror("cannot dup %s",msg); - exit(EX_SYSTEM); - } - ck_close(from); + if (from != to) + { + err = close (to); + if (err < 0 && errno != EBADF) + { + msg_perror ("Cannot close descriptor %d", to); + exit (EX_SYSTEM); + } + err = dup (from); + if (err != to) + { + msg_perror ("cannot dup %s", msg); + exit (EX_SYSTEM); } + ck_close (from); + } } #ifdef __MSDOS__ void -child_open() +child_open () { - fprintf(stderr,"MS-DOS %s can't use compressed or remote archives\n",tar); - exit(EX_ARGSBAD); + fprintf (stderr, "MS-DOS %s can't use compressed or remote archives\n", tar); + exit (EX_ARGSBAD); } + #else void -child_open() +child_open () { - int pipe[2]; - int err = 0; - int nar; + int pipe[2]; + int err = 0; + int nar; - int kidpipe[2]; - int kidchildpid; + int kidpipe[2]; + int kidchildpid; #define READ 0 #define WRITE 1 - ck_pipe(pipe); + ck_pipe (pipe); - childpid=fork(); - if(childpid<0) { - msg_perror("cannot fork"); - exit(EX_SYSTEM); + childpid = fork (); + if (childpid < 0) + { + msg_perror ("cannot fork"); + exit (EX_SYSTEM); + } + if (childpid > 0) + { + /* We're the parent. Clean up and be happy */ + /* This, at least, is easy */ + + if (ar_reading) + { + f_reblock++; + archive = pipe[READ]; + ck_close (pipe[WRITE]); } - if(childpid>0) { - /* We're the parent. Clean up and be happy */ - /* This, at least, is easy */ - - if(ar_reading) { - f_reblock++; - archive=pipe[READ]; - ck_close(pipe[WRITE]); - } else { - archive = pipe[WRITE]; - ck_close(pipe[READ]); - } - return; + else + { + archive = pipe[WRITE]; + ck_close (pipe[READ]); } + return; + } - /* We're the kid */ - if(ar_reading) { - dupto(pipe[WRITE],STDOUT,"(child) pipe to stdout"); - ck_close(pipe[READ]); - } else { - dupto(pipe[READ],STDIN,"(child) pipe to stdin"); - ck_close(pipe[WRITE]); - } + /* We're the kid */ + if (ar_reading) + { + dupto (pipe[WRITE], STDOUT, "(child) pipe to stdout"); + ck_close (pipe[READ]); + } + else + { + dupto (pipe[READ], STDIN, "(child) pipe to stdin"); + ck_close (pipe[WRITE]); + } - /* We need a child tar only if + /* We need a child tar only if 1: we're reading/writing stdin/out (to force reblocking) 2: the file is to be accessed by rmt (compress doesn't know how) 3: the file is not a plain file */ #ifdef NO_REMOTE - if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && isfile(ar_files[0])) + if (!(ar_files[0][0] == '-' && ar_files[0][1] == '\0') && isfile (ar_files[0])) #else - if(!(ar_files[0][0]=='-' && ar_files[0][1]=='\0') && !_remdev(ar_files[0]) && isfile(ar_files[0])) + if (!(ar_files[0][0] == '-' && ar_files[0][1] == '\0') && !_remdev (ar_files[0]) && isfile (ar_files[0])) #endif + { + /* We don't need a child tar. Open the archive */ + if (ar_reading) { - /* We don't need a child tar. Open the archive */ - if(ar_reading) { - archive=open(ar_files[0], O_RDONLY|O_BINARY, 0666); - if(archive<0) { - msg_perror("can't open archive %s",ar_files[0]); - exit(EX_BADARCH); - } - dupto(archive,STDIN,"archive to stdin"); - /* close(archive); */ - } else { - archive=creat(ar_files[0],0666); - if(archive<0) { - msg_perror("can't open archive %s",ar_files[0]); - exit(EX_BADARCH); - } - dupto(archive,STDOUT,"archive to stdout"); - /* close(archive); */ - } - } else { - /* We need a child tar */ - ck_pipe(kidpipe); - - kidchildpid=fork(); - if(kidchildpid<0) { - msg_perror("child can't fork"); - exit(EX_SYSTEM); - } + archive = open (ar_files[0], O_RDONLY | O_BINARY, 0666); + if (archive < 0) + { + msg_perror ("can't open archive %s", ar_files[0]); + exit (EX_BADARCH); + } + dupto (archive, STDIN, "archive to stdin"); + /* close(archive); */ + } + else + { + archive = creat (ar_files[0], 0666); + if (archive < 0) + { + msg_perror ("can't open archive %s", ar_files[0]); + exit (EX_BADARCH); + } + dupto (archive, STDOUT, "archive to stdout"); + /* close(archive); */ + } + } + else + { + /* We need a child tar */ + ck_pipe (kidpipe); - if(kidchildpid>0) { - /* About to exec compress: set up the files */ - if(ar_reading) { - dupto(kidpipe[READ],STDIN,"((child)) pipe to stdin"); - ck_close(kidpipe[WRITE]); - /* dup2(pipe[WRITE],STDOUT); */ - } else { - /* dup2(pipe[READ],STDIN); */ - dupto(kidpipe[WRITE],STDOUT,"((child)) pipe to stdout"); - ck_close(kidpipe[READ]); - } - /* ck_close(pipe[READ]); */ - /* ck_close(pipe[WRITE]); */ - /* ck_close(kidpipe[READ]); + kidchildpid = fork (); + if (kidchildpid < 0) + { + msg_perror ("child can't fork"); + exit (EX_SYSTEM); + } + + if (kidchildpid > 0) + { + /* About to exec compress: set up the files */ + if (ar_reading) + { + dupto (kidpipe[READ], STDIN, "((child)) pipe to stdin"); + ck_close (kidpipe[WRITE]); + /* dup2(pipe[WRITE],STDOUT); */ + } + else + { + /* dup2(pipe[READ],STDIN); */ + dupto (kidpipe[WRITE], STDOUT, "((child)) pipe to stdout"); + ck_close (kidpipe[READ]); + } + /* ck_close(pipe[READ]); */ + /* ck_close(pipe[WRITE]); */ + /* ck_close(kidpipe[READ]); ck_close(kidpipe[WRITE]); */ - } else { - /* Grandchild. Do the right thing, namely sit here and + } + else + { + /* Grandchild. Do the right thing, namely sit here and read/write the archive, and feed stuff back to compress */ - tar="tar (child)"; - if(ar_reading) { - dupto(kidpipe[WRITE],STDOUT,"[child] pipe to stdout"); - ck_close(kidpipe[READ]); - } else { - dupto(kidpipe[READ],STDIN,"[child] pipe to stdin"); - ck_close(kidpipe[WRITE]); - } - - if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') { - if (ar_reading) - archive = STDIN; - else - archive = STDOUT; - } else /* This can't happen if (ar_reading==2) + tar = "tar (child)"; + if (ar_reading) + { + dupto (kidpipe[WRITE], STDOUT, "[child] pipe to stdout"); + ck_close (kidpipe[READ]); + } + else + { + dupto (kidpipe[READ], STDIN, "[child] pipe to stdin"); + ck_close (kidpipe[WRITE]); + } + + if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') + { + if (ar_reading) + archive = STDIN; + else + archive = STDOUT; + } + else /* This can't happen if (ar_reading==2) archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666); - else */if(ar_reading) - archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666); - else - archive = rmtcreat(ar_files[0], 0666); - - if (archive < 0) { - msg_perror("can't open archive %s",ar_files[0]); - exit(EX_BADARCH); - } - - if(ar_reading) { - for(;;) { - char *ptr; - int max,count; - - r_error_count = 0; - error_loop: - err=rmtread(archive, ar_block->charptr,(int)(blocksize)); - if(err<0) { - readerror(); - goto error_loop; - } - if(err==0) - break; - ptr = ar_block->charptr; - max = err; - while(max) { - count = (maxcharptr; - while(n) { - err=read(STDIN,ptr,(ncharptr+blocksize-n,n); - err=rmtwrite(archive,ar_block->charptr,blocksize); - if(err!=(blocksize)) - writeerror(err); - if(f_compress<2) - blocksize+=n; - break; - } - if(n) { - msg_perror("can't read from compress"); - exit(EX_SYSTEM); - } - err=rmtwrite(archive, ar_block->charptr, (int)blocksize); - if(err!=blocksize) - writeerror(err); - } + else */ if (ar_reading) + archive = rmtopen (ar_files[0], O_RDONLY | O_BINARY, 0666); + else + archive = rmtcreat (ar_files[0], 0666); + + if (archive < 0) + { + msg_perror ("can't open archive %s", ar_files[0]); + exit (EX_BADARCH); + } + + if (ar_reading) + { + for (;;) + { + char *ptr; + int max, count; + + r_error_count = 0; + error_loop: + err = rmtread (archive, ar_block->charptr, (int) (blocksize)); + if (err < 0) + { + readerror (); + goto error_loop; + } + if (err == 0) + break; + ptr = ar_block->charptr; + max = err; + while (max) + { + count = (max < RECORDSIZE) ? max : RECORDSIZE; + err = write (STDOUT, ptr, count); + if (err != count) + { + if (err < 0) + { + msg_perror ("can't write to compress"); + exit (EX_SYSTEM); + } + else + msg ("write to compress short %d bytes", count - err); + count = (err < 0) ? 0 : err; } - - /* close_archive(); */ - exit(0); + ptr += count; + max -= count; + } } + } + else + { + for (;;) + { + int n; + char *ptr; + + n = blocksize; + ptr = ar_block->charptr; + while (n) + { + err = read (STDIN, ptr, (n < RECORDSIZE) ? n : RECORDSIZE); + if (err <= 0) + break; + n -= err; + ptr += err; + } + /* EOF */ + if (err == 0) + { + if (f_compress < 2) + blocksize -= n; + else + bzero (ar_block->charptr + blocksize - n, n); + err = rmtwrite (archive, ar_block->charptr, blocksize); + if (err != (blocksize)) + writeerror (err); + if (f_compress < 2) + blocksize += n; + break; + } + if (n) + { + msg_perror ("can't read from compress"); + exit (EX_SYSTEM); + } + err = rmtwrite (archive, ar_block->charptr, (int) blocksize); + if (err != blocksize) + writeerror (err); + } + } + + /* close_archive(); */ + exit (0); } - /* So we should exec compress (-d) */ - if(ar_reading) - execlp("compress", "compress", "-d", (char *)0); - else - execlp("compress", "compress", (char *)0); - msg_perror("can't exec compress"); - _exit(EX_SYSTEM); + } + /* So we should exec compress (-d) */ + if (ar_reading) + execlp ("compress", "compress", "-d", (char *) 0); + else + execlp ("compress", "compress", (char *) 0); + msg_perror ("can't exec compress"); + _exit (EX_SYSTEM); } /* return non-zero if p is the name of a directory */ int -isfile(p) -char *p; +isfile (p) + char *p; { - struct stat stbuf; + struct stat stbuf; - if(stat(p,&stbuf)<0) - return 1; - if(S_ISREG(stbuf.st_mode)) - return 1; - return 0; + if (stat (p, &stbuf) < 0) + return 1; + if (S_ISREG (stbuf.st_mode)) + return 1; + return 0; } #endif @@ -483,146 +531,178 @@ char *p; */ /* JF if the arg is 2, open for reading and writing. */ void -open_archive(reading) - int reading; +open_archive (reading) + int reading; { - msg_file = f_exstdout ? stderr : stdout; + msg_file = f_exstdout ? stderr : stdout; - if (blocksize == 0) { - msg("invalid value for blocksize"); - exit(EX_ARGSBAD); - } + if (blocksize == 0) + { + msg ("invalid value for blocksize"); + exit (EX_ARGSBAD); + } - if(n_ar_files==0) { - msg("No archive name given, what should I do?"); - exit(EX_BADARCH); - } + if (n_ar_files == 0) + { + msg ("No archive name given, what should I do?"); + exit (EX_BADARCH); + } - /*NOSTRICT*/ - if(f_multivol) { - ar_block = (union record *) valloc((unsigned)(blocksize+(2*RECORDSIZE))); - if(ar_block) - ar_block += 2; - } else - ar_block = (union record *) valloc((unsigned)blocksize); - if (!ar_block) { - msg("could not allocate memory for blocking factor %d", - blocking); - exit(EX_ARGSBAD); - } + /*NOSTRICT*/ + if (f_multivol) + { + ar_block = (union record *) valloc ((unsigned) (blocksize + (2 * RECORDSIZE))); + if (ar_block) + ar_block += 2; + } + else + ar_block = (union record *) valloc ((unsigned) blocksize); + if (!ar_block) + { + msg ("could not allocate memory for blocking factor %d", + blocking); + exit (EX_ARGSBAD); + } - ar_record = ar_block; - ar_last = ar_block + blocking; - ar_reading = reading; + ar_record = ar_block; + ar_last = ar_block + blocking; + ar_reading = reading; - if (f_multivol && f_verify) - { - msg ("cannot verify multi-volume archives"); - exit (EX_ARGSBAD); - } - - if (f_compress) { - if(reading==2 || f_verify) { - msg("cannot update or verify compressed archives"); - exit(EX_ARGSBAD); - } - if (f_multivol) { - msg ("cannot use multi-volume compressed archives"); - exit (EX_ARGSBAD); - } - child_open(); - if(!reading && ar_files[0][0]=='-' && ar_files[0][1]=='\0') - msg_file = stderr; - /* child_open(rem_host, rem_file); */ - } else if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') { - f_reblock++; /* Could be a pipe, be safe */ - if(f_verify) { - msg("can't verify stdin/stdout archive"); - exit(EX_ARGSBAD); - } - if(reading==2) { - archive=STDIN; - msg_file=stderr; - write_archive_to_stdout++; - } else if (reading) - archive = STDIN; - else { - archive = STDOUT; - msg_file = stderr; - } - } else if (reading==2 || f_verify) { - archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666); - } else if(reading) { - archive = rmtopen(ar_files[0], O_RDONLY|O_BINARY, 0666); - } else { - archive = rmtcreat(ar_files[0], 0666); + if (f_multivol && f_verify) + { + msg ("cannot verify multi-volume archives"); + exit (EX_ARGSBAD); + } + + if (f_compress) + { + if (reading == 2 || f_verify) + { + msg ("cannot update or verify compressed archives"); + exit (EX_ARGSBAD); + } + if (f_multivol) + { + msg ("cannot use multi-volume compressed archives"); + exit (EX_ARGSBAD); + } + child_open (); + if (!reading && ar_files[0][0] == '-' && ar_files[0][1] == '\0') + msg_file = stderr; + /* child_open(rem_host, rem_file); */ + } + else if (ar_files[0][0] == '-' && ar_files[0][1] == '\0') + { + f_reblock++; /* Could be a pipe, be safe */ + if (f_verify) + { + msg ("can't verify stdin/stdout archive"); + exit (EX_ARGSBAD); } - if (archive < 0) { - msg_perror("can't open %s",ar_files[0]); - exit(EX_BADARCH); + if (reading == 2) + { + archive = STDIN; + msg_file = stderr; + write_archive_to_stdout++; + } + else if (reading) + archive = STDIN; + else + { + archive = STDOUT; + msg_file = stderr; } + } + else if (reading == 2 || f_verify) + { + archive = rmtopen (ar_files[0], O_RDWR | O_CREAT | O_BINARY, 0666); + } + else if (reading) + { + archive = rmtopen (ar_files[0], O_RDONLY | O_BINARY, 0666); + } + else + { + archive = rmtcreat (ar_files[0], 0666); + } + if (archive < 0) + { + msg_perror ("can't open %s", ar_files[0]); + exit (EX_BADARCH); + } #ifndef __MSDOS__ - if(!_isrmt(archive)) { - struct stat tmp_stat; + if (!_isrmt (archive)) + { + struct stat tmp_stat; - fstat(archive,&tmp_stat); - if(S_ISREG(tmp_stat.st_mode)) { - ar_dev=tmp_stat.st_dev; - ar_ino=tmp_stat.st_ino; - } + fstat (archive, &tmp_stat); + if (S_ISREG (tmp_stat.st_mode)) + { + ar_dev = tmp_stat.st_dev; + ar_ino = tmp_stat.st_ino; } + } #endif #ifdef __MSDOS__ - setmode(archive, O_BINARY); + setmode (archive, O_BINARY); #endif - if (reading) { - ar_last = ar_block; /* Set up for 1st block = # 0 */ - (void) findrec(); /* Read it in, check for EOF */ + if (reading) + { + ar_last = ar_block; /* Set up for 1st block = # 0 */ + (void) findrec (); /* Read it in, check for EOF */ - if(f_volhdr) { - union record *head; + if (f_volhdr) + { + union record *head; #if 0 - char *ptr; - - if(f_multivol) { - ptr=malloc(strlen(f_volhdr)+20); - sprintf(ptr,"%s Volume %d",f_volhdr,1); - } else - ptr=f_volhdr; + char *ptr; + + if (f_multivol) + { + ptr = malloc (strlen (f_volhdr) + 20); + sprintf (ptr, "%s Volume %d", f_volhdr, 1); + } + else + ptr = f_volhdr; #endif - head=findrec(); - if(!head) { - msg("Archive not labelled to match %s",f_volhdr); - exit(EX_BADVOL); - } - if (re_match (label_pattern, head->header.arch_name, - strlen (head->header.arch_name), 0, 0) < 0) { - msg ("Volume mismatch! %s!=%s", f_volhdr, - head->header.arch_name); - exit (EX_BADVOL); - } -#if 0 - if(strcmp(ptr,head->header.name)) { - msg("Volume mismatch! %s!=%s",ptr,head->header.name); - exit(EX_BADVOL); - } - if(ptr!=f_volhdr) - free(ptr); + head = findrec (); + if (!head) + { + msg ("Archive not labelled to match %s", f_volhdr); + exit (EX_BADVOL); + } + if (re_match (label_pattern, head->header.arch_name, + strlen (head->header.arch_name), 0, 0) < 0) + { + msg ("Volume mismatch! %s!=%s", f_volhdr, + head->header.arch_name); + exit (EX_BADVOL); + } +#if 0 + if (strcmp (ptr, head->header.name)) + { + msg ("Volume mismatch! %s!=%s", ptr, head->header.name); + exit (EX_BADVOL); + } + if (ptr != f_volhdr) + free (ptr); #endif - } - } else if(f_volhdr) { - bzero((void *)ar_block,RECORDSIZE); - if(f_multivol) - sprintf(ar_block->header.arch_name,"%s Volume 1",f_volhdr); - else - strcpy(ar_block->header.arch_name,f_volhdr); - ar_block->header.linkflag = LF_VOLHDR; - to_oct(time(0), 1+12, ar_block->header.mtime); - finish_header(ar_block); - /* ar_record++; */ } + } + else if (f_volhdr) + { + bzero ((void *) ar_block, RECORDSIZE); + if (f_multivol) + sprintf (ar_block->header.arch_name, "%s Volume 1", f_volhdr); + else + strcpy (ar_block->header.arch_name, f_volhdr); + ar_block->header.linkflag = LF_VOLHDR; + to_oct (time (0), 1 + 12, ar_block->header.mtime); + finish_header (ar_block); + /* ar_record++; */ + } } @@ -637,14 +717,14 @@ open_archive(reading) * subtracting ar_block from that, shifting it back, losing the top 9 bits. */ void -saverec(pointer) - union record **pointer; +saverec (pointer) + union record **pointer; { - long offset; + long offset; - save_rec = pointer; - offset = ar_record - ar_block; - saved_recno = baserec + offset; + save_rec = pointer; + offset = ar_record - ar_block; + saved_recno = baserec + offset; } /* @@ -659,126 +739,139 @@ saverec(pointer) */ void -fl_write() +fl_write () { - int err; - int copy_back; - static long bytes_written = 0; - - if (f_checkpoint && ! (++checkpoint % 10)) - msg ("Write checkpoint %d\n", checkpoint); - if(tape_length && bytes_written >= tape_length * 1024) { - errno = ENOSPC; - err = 0; - } else - err = rmtwrite(archive, ar_block->charptr,(int) blocksize); - if(err!=blocksize && !f_multivol) - writeerror(err); - else if (f_totals) - tot_written += blocksize; - - if(err>0) - bytes_written+=err; - if (err == blocksize) { - if(f_multivol) { - if(!save_name) { - real_s_name[0]='\0'; - real_s_totsize=0; - real_s_sizeleft = 0; - return; - } + int err; + int copy_back; + static long bytes_written = 0; + + if (f_checkpoint && !(++checkpoint % 10)) + msg ("Write checkpoint %d\n", checkpoint); + if (tape_length && bytes_written >= tape_length * 1024) + { + errno = ENOSPC; + err = 0; + } + else + err = rmtwrite (archive, ar_block->charptr, (int) blocksize); + if (err != blocksize && !f_multivol) + writeerror (err); + else if (f_totals) + tot_written += blocksize; + + if (err > 0) + bytes_written += err; + if (err == blocksize) + { + if (f_multivol) + { + if (!save_name) + { + real_s_name[0] = '\0'; + real_s_totsize = 0; + real_s_sizeleft = 0; + return; + } #ifdef __MSDOS__ - if(save_name[1]==':') - save_name+=2; + if (save_name[1] == ':') + save_name += 2; #endif - while(*save_name=='/') - save_name++; + while (*save_name == '/') + save_name++; - strcpy(real_s_name,save_name); - real_s_totsize = save_totsize; - real_s_sizeleft = save_sizeleft; - } - return; + strcpy (real_s_name, save_name); + real_s_totsize = save_totsize; + real_s_sizeleft = save_sizeleft; } + return; + } - /* We're multivol Panic if we didn't get the right kind of response */ - /* ENXIO is for the UNIX PC */ - if(err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO) - writeerror(err); - - /* If error indicates a short write, we just move to the next tape. */ - - if(new_volume(0)<0) - return; - bytes_written=0; - if(f_volhdr && real_s_name[0]) { - copy_back=2; - ar_block-=2; - } else if(f_volhdr || real_s_name[0]) { - copy_back = 1; - ar_block--; - } else - copy_back = 0; - if(f_volhdr) { - bzero((void *)ar_block,RECORDSIZE); - sprintf(ar_block->header.arch_name,"%s Volume %d",f_volhdr,volno); - to_oct(time(0), 1+12, ar_block->header.mtime); - ar_block->header.linkflag = LF_VOLHDR; - finish_header(ar_block); - } - if(real_s_name[0]) { - int tmp; - - if(f_volhdr) - ar_block++; - bzero((void *)ar_block,RECORDSIZE); - strcpy(ar_block->header.arch_name,real_s_name); - ar_block->header.linkflag = LF_MULTIVOL; - to_oct((long)real_s_sizeleft,1+12, - ar_block->header.size); - to_oct((long)real_s_totsize-real_s_sizeleft, - 1+12,ar_block->header.offset); - tmp=f_verbose; - f_verbose=0; - finish_header(ar_block); - f_verbose=tmp; - if(f_volhdr) - ar_block--; - } + /* We're multivol Panic if we didn't get the right kind of response */ + /* ENXIO is for the UNIX PC */ + if (err < 0 && errno != ENOSPC && errno != EIO && errno != ENXIO) + writeerror (err); - err = rmtwrite(archive, ar_block->charptr,(int) blocksize); - if(err!=blocksize) - writeerror(err); - else if (f_totals) - tot_written += blocksize; - - - bytes_written = blocksize; - if(copy_back) { - ar_block+=copy_back; - bcopy((void *)(ar_block+blocking-copy_back), - (void *)ar_record, - copy_back*RECORDSIZE); - ar_record+=copy_back; - - if(real_s_sizeleft>=copy_back*RECORDSIZE) - real_s_sizeleft-=copy_back*RECORDSIZE; - else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back) - real_s_name[0] = '\0'; - else { + /* If error indicates a short write, we just move to the next tape. */ + + if (new_volume (0) < 0) + return; + bytes_written = 0; + if (f_volhdr && real_s_name[0]) + { + copy_back = 2; + ar_block -= 2; + } + else if (f_volhdr || real_s_name[0]) + { + copy_back = 1; + ar_block--; + } + else + copy_back = 0; + if (f_volhdr) + { + bzero ((void *) ar_block, RECORDSIZE); + sprintf (ar_block->header.arch_name, "%s Volume %d", f_volhdr, volno); + to_oct (time (0), 1 + 12, ar_block->header.mtime); + ar_block->header.linkflag = LF_VOLHDR; + finish_header (ar_block); + } + if (real_s_name[0]) + { + int tmp; + + if (f_volhdr) + ar_block++; + bzero ((void *) ar_block, RECORDSIZE); + strcpy (ar_block->header.arch_name, real_s_name); + ar_block->header.linkflag = LF_MULTIVOL; + to_oct ((long) real_s_sizeleft, 1 + 12, + ar_block->header.size); + to_oct ((long) real_s_totsize - real_s_sizeleft, + 1 + 12, ar_block->header.offset); + tmp = f_verbose; + f_verbose = 0; + finish_header (ar_block); + f_verbose = tmp; + if (f_volhdr) + ar_block--; + } + + err = rmtwrite (archive, ar_block->charptr, (int) blocksize); + if (err != blocksize) + writeerror (err); + else if (f_totals) + tot_written += blocksize; + + + bytes_written = blocksize; + if (copy_back) + { + ar_block += copy_back; + bcopy ((void *) (ar_block + blocking - copy_back), + (void *) ar_record, + copy_back * RECORDSIZE); + ar_record += copy_back; + + if (real_s_sizeleft >= copy_back * RECORDSIZE) + real_s_sizeleft -= copy_back * RECORDSIZE; + else if ((real_s_sizeleft + RECORDSIZE - 1) / RECORDSIZE <= copy_back) + real_s_name[0] = '\0'; + else + { #ifdef __MSDOS__ - if(save_name[1]==':') - save_name+=2; + if (save_name[1] == ':') + save_name += 2; #endif - while(*save_name=='/') - save_name++; + while (*save_name == '/') + save_name++; - strcpy(real_s_name,save_name); - real_s_sizeleft = save_sizeleft; - real_s_totsize=save_totsize; - } - copy_back = 0; + strcpy (real_s_name, save_name); + real_s_sizeleft = save_sizeleft; + real_s_totsize = save_totsize; } + copy_back = 0; + } } /* Handle write errors on the archive. Write errors are always fatal */ @@ -786,16 +879,19 @@ fl_write() * was the first block of the volume */ void -writeerror(err) -int err; +writeerror (err) + int err; { - if (err < 0) { - msg_perror("can't write to %s",ar_files[cur_ar_file]); - exit(EX_BADARCH); - } else { - msg("only wrote %u of %u bytes to %s",err,blocksize,ar_files[cur_ar_file]); - exit(EX_BADARCH); - } + if (err < 0) + { + msg_perror ("can't write to %s", ar_files[cur_ar_file]); + exit (EX_BADARCH); + } + else + { + msg ("only wrote %u of %u bytes to %s", err, blocksize, ar_files[cur_ar_file]); + exit (EX_BADARCH); + } } /* @@ -804,29 +900,31 @@ int err; * If the read should be retried, readerror() returns to the caller. */ void -readerror() +readerror () { # define READ_ERROR_MAX 10 - read_error_flag++; /* Tell callers */ + read_error_flag++; /* Tell callers */ - msg_perror("read error on %s",ar_files[cur_ar_file]); + msg_perror ("read error on %s", ar_files[cur_ar_file]); - if (baserec == 0) { - /* First block of tape. Probably stupidity error */ - exit(EX_BADARCH); - } + if (baserec == 0) + { + /* First block of tape. Probably stupidity error */ + exit (EX_BADARCH); + } - /* + /* * Read error in mid archive. We retry up to READ_ERROR_MAX times * and then give up on reading the archive. We set read_error_flag * for our callers, so they can cope if they want. */ - if (r_error_count++ > READ_ERROR_MAX) { - msg("Too many errors, quitting."); - exit(EX_BADARCH); - } - return; + if (r_error_count++ > READ_ERROR_MAX) + { + msg ("Too many errors, quitting."); + exit (EX_BADARCH); + } + return; } @@ -834,191 +932,220 @@ readerror() * Perform a read to flush the buffer. */ void -fl_read() +fl_read () { - int err; /* Result from system call */ - int left; /* Bytes left */ - char *more; /* Pointer to next byte to read */ + int err; /* Result from system call */ + int left; /* Bytes left */ + char *more; /* Pointer to next byte to read */ - if (f_checkpoint && ! (++checkpoint % 10)) - msg ("Read checkpoint %d\n", checkpoint); + if (f_checkpoint && !(++checkpoint % 10)) + msg ("Read checkpoint %d\n", checkpoint); - /* + /* * Clear the count of errors. This only applies to a single * call to fl_read. We leave read_error_flag alone; it is * only turned off by higher level software. */ - r_error_count = 0; /* Clear error count */ + r_error_count = 0; /* Clear error count */ - /* + /* * If we are about to wipe out a record that * somebody needs to keep, copy it out to a holding * area and adjust somebody's pointer to it. */ - if (save_rec && - *save_rec >= ar_record && - *save_rec < ar_last) { - record_save_area = **save_rec; - *save_rec = &record_save_area; - } - if(write_archive_to_stdout && baserec!=0) { - err=rmtwrite(1, ar_block->charptr, blocksize); - if(err!=blocksize) - writeerror(err); - } - if(f_multivol) { - if(save_name) { - if(save_name!=real_s_name) { + if (save_rec && + *save_rec >= ar_record && + *save_rec < ar_last) + { + record_save_area = **save_rec; + *save_rec = &record_save_area; + } + if (write_archive_to_stdout && baserec != 0) + { + err = rmtwrite (1, ar_block->charptr, blocksize); + if (err != blocksize) + writeerror (err); + } + if (f_multivol) + { + if (save_name) + { + if (save_name != real_s_name) + { #ifdef __MSDOS__ - if(save_name[1]==':') - save_name+=2; + if (save_name[1] == ':') + save_name += 2; #endif - while(*save_name=='/') - save_name++; + while (*save_name == '/') + save_name++; + + strcpy (real_s_name, save_name); + save_name = real_s_name; + } + real_s_totsize = save_totsize; + real_s_sizeleft = save_sizeleft; - strcpy(real_s_name,save_name); - save_name=real_s_name; - } - real_s_totsize = save_totsize; - real_s_sizeleft = save_sizeleft; - - } else { - real_s_name[0]='\0'; - real_s_totsize=0; - real_s_sizeleft = 0; - } } + else + { + real_s_name[0] = '\0'; + real_s_totsize = 0; + real_s_sizeleft = 0; + } + } error_loop: - err = rmtread(archive, ar_block->charptr, (int)blocksize); - if (err == blocksize) - return; - - if((err == 0 || (err<0 && errno==ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) { - union record *head; - - try_volume: - if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0) - return; - vol_error: - err = rmtread(archive, ar_block->charptr,(int) blocksize); - if(err < 0) { - readerror(); - goto vol_error; - } - if(err!=blocksize) - goto short_read; + err = rmtread (archive, ar_block->charptr, (int) blocksize); + if (err == blocksize) + return; - head=ar_block; + if ((err == 0 || (err < 0 && errno == ENOSPC) || (err > 0 && !f_reblock)) && f_multivol) + { + union record *head; - if(head->header.linkflag==LF_VOLHDR) { - if(f_volhdr) { -#if 0 - char *ptr; + try_volume: + if (new_volume ((cmd_mode == CMD_APPEND || cmd_mode == CMD_CAT || cmd_mode == CMD_UPDATE) ? 2 : 1) < 0) + return; + vol_error: + err = rmtread (archive, ar_block->charptr, (int) blocksize); + if (err < 0) + { + readerror (); + goto vol_error; + } + if (err != blocksize) + goto short_read; - ptr=(char *)malloc(strlen(f_volhdr)+20); - sprintf(ptr,"%s Volume %d",f_volhdr,volno); -#endif - if (re_match (label_pattern, head->header.arch_name, - strlen (head->header.arch_name), - 0, 0) < 0) { - msg("Volume mismatch! %s!=%s",f_volhdr, - head->header.arch_name); - --volno; - --global_volno; - goto try_volume; - } - + head = ar_block; + + if (head->header.linkflag == LF_VOLHDR) + { + if (f_volhdr) + { #if 0 - if(strcmp(ptr,head->header.name)) { - msg("Volume mismatch! %s!=%s",ptr,head->header.name); - --volno; - --global_volno; - free(ptr); - goto try_volume; - } - free(ptr); + char *ptr; + + ptr = (char *) malloc (strlen (f_volhdr) + 20); + sprintf (ptr, "%s Volume %d", f_volhdr, volno); #endif - } - if(f_verbose) - fprintf(msg_file,"Reading %s\n",head->header.arch_name); - head++; - } else if(f_volhdr) { - msg("Warning: No volume header!"); + if (re_match (label_pattern, head->header.arch_name, + strlen (head->header.arch_name), + 0, 0) < 0) + { + msg ("Volume mismatch! %s!=%s", f_volhdr, + head->header.arch_name); + --volno; + --global_volno; + goto try_volume; } - if(real_s_name[0]) { - long from_oct(); - - if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.arch_name,real_s_name)) { - msg("%s is not continued on this volume!",real_s_name); - --volno; - --global_volno; - goto try_volume; - } - if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) { - msg("%s is the wrong size (%ld!=%ld+%ld)", - head->header.arch_name,save_totsize, - from_oct(1+12,head->header.size), - from_oct(1+12,head->header.offset)); - --volno; - --global_volno; - goto try_volume; - } - if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) { - msg("This volume is out of sequence"); - --volno; - --global_volno; - goto try_volume; - } - head++; +#if 0 + if (strcmp (ptr, head->header.name)) + { + msg ("Volume mismatch! %s!=%s", ptr, head->header.name); + --volno; + --global_volno; + free (ptr); + goto try_volume; } - ar_record=head; - return; - } else if (err < 0) { - readerror(); - goto error_loop; /* Try again */ + free (ptr); +#endif + } + if (f_verbose) + fprintf (msg_file, "Reading %s\n", head->header.arch_name); + head++; + } + else if (f_volhdr) + { + msg ("Warning: No volume header!"); + } + + if (real_s_name[0]) + { + long from_oct (); + + if (head->header.linkflag != LF_MULTIVOL || strcmp (head->header.arch_name, real_s_name)) + { + msg ("%s is not continued on this volume!", real_s_name); + --volno; + --global_volno; + goto try_volume; + } + if (real_s_totsize != from_oct (1 + 12, head->header.size) + from_oct (1 + 12, head->header.offset)) + { + msg ("%s is the wrong size (%ld!=%ld+%ld)", + head->header.arch_name, save_totsize, + from_oct (1 + 12, head->header.size), + from_oct (1 + 12, head->header.offset)); + --volno; + --global_volno; + goto try_volume; + } + if (real_s_totsize - real_s_sizeleft != from_oct (1 + 12, head->header.offset)) + { + msg ("This volume is out of sequence"); + --volno; + --global_volno; + goto try_volume; + } + head++; } + ar_record = head; + return; + } + else if (err < 0) + { + readerror (); + goto error_loop; /* Try again */ + } - short_read: - more = ar_block->charptr + err; - left = blocksize - err; +short_read: + more = ar_block->charptr + err; + left = blocksize - err; again: - if (0 == (((unsigned)left) % RECORDSIZE)) { - /* FIXME, for size=0, multi vol support */ - /* On the first block, warn about the problem */ - if (!f_reblock && baserec == 0 && f_verbose && err > 0) { - /* msg("Blocksize = %d record%s", + if (0 == (((unsigned) left) % RECORDSIZE)) + { + /* FIXME, for size=0, multi vol support */ + /* On the first block, warn about the problem */ + if (!f_reblock && baserec == 0 && f_verbose && err > 0) + { + /* msg("Blocksize = %d record%s", err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/ - msg("Blocksize = %d records", err / RECORDSIZE); - } - ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE; - return; + msg ("Blocksize = %d records", err / RECORDSIZE); } - if (f_reblock) { - /* + ar_last = ar_block + ((unsigned) (blocksize - left)) / RECORDSIZE; + return; + } + if (f_reblock) + { + /* * User warned us about this. Fix up. */ - if (left > 0) { -error2loop: - err = rmtread(archive, more, (int)left); - if (err < 0) { - readerror(); - goto error2loop; /* Try again */ - } - if (err == 0) { - msg("archive %s EOF not on block boundary",ar_files[cur_ar_file]); - exit(EX_BADARCH); - } - left -= err; - more += err; - goto again; - } - } else { - msg("only read %d bytes from archive %s",err,ar_files[cur_ar_file]); - exit(EX_BADARCH); + if (left > 0) + { + error2loop: + err = rmtread (archive, more, (int) left); + if (err < 0) + { + readerror (); + goto error2loop; /* Try again */ + } + if (err == 0) + { + msg ("archive %s EOF not on block boundary", ar_files[cur_ar_file]); + exit (EX_BADARCH); + } + left -= err; + more += err; + goto again; } + } + else + { + msg ("only read %d bytes from archive %s", err, ar_files[cur_ar_file]); + exit (EX_BADARCH); + } } @@ -1026,69 +1153,77 @@ error2loop: * Flush the current buffer to/from the archive. */ void -flush_archive() +flush_archive () { - int c; - - baserec += ar_last - ar_block; /* Keep track of block #s */ - ar_record = ar_block; /* Restore pointer to start */ - ar_last = ar_block + blocking; /* Restore pointer to end */ - - if (ar_reading) { - if(time_to_start_writing) { - time_to_start_writing=0; - ar_reading=0; - - if(file_to_switch_to>=0) { - if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); - - archive=file_to_switch_to; - } else - (void)backspace_output(); - fl_write(); - } else - fl_read(); - } else { - fl_write(); + int c; + + baserec += ar_last - ar_block;/* Keep track of block #s */ + ar_record = ar_block; /* Restore pointer to start */ + ar_last = ar_block + blocking;/* Restore pointer to end */ + + if (ar_reading) + { + if (time_to_start_writing) + { + time_to_start_writing = 0; + ar_reading = 0; + + if (file_to_switch_to >= 0) + { + if ((c = rmtclose (archive)) < 0) + msg_perror ("Warning: can't close %s(%d,%d)", ar_files[cur_ar_file], archive, c); + + archive = file_to_switch_to; + } + else + (void) backspace_output (); + fl_write (); } + else + fl_read (); + } + else + { + fl_write (); + } } /* Backspace the archive descriptor by one blocks worth. If its a tape, MTIOCTOP will work. If its something else, we try to seek on it. If we can't seek, we lose! */ int -backspace_output() +backspace_output () { - long cur; - /* int er; */ - extern char *output_start; + long cur; + /* int er; */ + extern char *output_start; #ifdef MTIOCTOP - struct mtop t; - - t.mt_op = MTBSR; - t.mt_count = 1; - if((rmtioctl(archive,MTIOCTOP,&t))>=0) - return 1; - if(errno==EIO && (rmtioctl(archive,MTIOCTOP,&t))>=0) - return 1; + struct mtop t; + + t.mt_op = MTBSR; + t.mt_count = 1; + if ((rmtioctl (archive, MTIOCTOP, &t)) >= 0) + return 1; + if (errno == EIO && (rmtioctl (archive, MTIOCTOP, &t)) >= 0) + return 1; #endif - cur=rmtlseek(archive,0L,1); - cur-=blocksize; - /* Seek back to the beginning of this block and + cur = rmtlseek (archive, 0L, 1); + cur -= blocksize; + /* Seek back to the beginning of this block and start writing there. */ - if(rmtlseek(archive,cur,0)!=cur) { - /* Lseek failed. Try a different method */ - msg("Couldn't backspace archive file. It may be unreadable without -i."); - /* Replace the first part of the block with nulls */ - if(ar_block->charptr!=output_start) - bzero(ar_block->charptr,output_start-ar_block->charptr); - return 2; - } - return 3; + if (rmtlseek (archive, cur, 0) != cur) + { + /* Lseek failed. Try a different method */ + msg ("Couldn't backspace archive file. It may be unreadable without -i."); + /* Replace the first part of the block with nulls */ + if (ar_block->charptr != output_start) + bzero (ar_block->charptr, output_start - ar_block->charptr); + return 2; + } + return 3; } @@ -1096,72 +1231,78 @@ backspace_output() * Close the archive file. */ void -close_archive() +close_archive () { - int child; - int status; - int c; + int child; + int status; + int c; - if (time_to_start_writing || !ar_reading) - flush_archive(); - if(cmd_mode==CMD_DELETE) { - off_t pos; + if (time_to_start_writing || !ar_reading) + flush_archive (); + if (cmd_mode == CMD_DELETE) + { + off_t pos; - pos = rmtlseek(archive,0L,1); + pos = rmtlseek (archive, 0L, 1); #ifndef __MSDOS__ - (void) ftruncate(archive,pos); + (void) ftruncate (archive, pos); #else - (void)rmtwrite(archive,"",0); + (void) rmtwrite (archive, "", 0); #endif - } - if(f_verify) - verify_volume(); + } + if (f_verify) + verify_volume (); - if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); + if ((c = rmtclose (archive)) < 0) + msg_perror ("Warning: can't close %s(%d,%d)", ar_files[cur_ar_file], archive, c); #ifndef __MSDOS__ - if (childpid) { - /* + if (childpid) + { + /* * Loop waiting for the right child to die, or for * no more kids. */ - while (((child = wait(&status)) != childpid) && child != -1) - ; + while (((child = wait (&status)) != childpid) && child != -1) + ; - if (child != -1) { + if (child != -1) + { + { + if (WIFSIGNALED (status)) + { + /* SIGPIPE is OK, everything else is a problem. */ + if (WTERMSIG (status) != SIGPIPE) + msg ("child died with signal %d%s", WTERMSIG (status), + WIFCOREDUMPED (status) ? " (core dumped)" : ""); + } + else + { + /* Child voluntarily terminated -- but why? */ + if (WEXITSTATUS (status) == MAGIC_STAT) { - if (WIFSIGNALED(status)) - { - /* SIGPIPE is OK, everything else is a problem. */ - if (WTERMSIG (status) != SIGPIPE) - msg("child died with signal %d%s", WTERMSIG(status), - WIFCOREDUMPED(status)? " (core dumped)": ""); - } - else - { - /* Child voluntarily terminated -- but why? */ - if (WEXITSTATUS(status) == MAGIC_STAT) { - exit(EX_SYSTEM);/* Child had trouble */ - } - if (WEXITSTATUS(status) == (SIGPIPE + 128)) { - /* + exit (EX_SYSTEM); /* Child had trouble */ + } + if (WEXITSTATUS (status) == (SIGPIPE + 128)) + { + /* * /bin/sh returns this if its child * dies with SIGPIPE. 'Sok. */ - break; - } else if (WEXITSTATUS(status)) - msg("child returned status %d", - WEXITSTATUS(status)); - } + break; } + else if (WEXITSTATUS (status)) + msg ("child returned status %d", + WEXITSTATUS (status)); + } + } } -#endif /* __MSDOS__ */ -} +#endif /* __MSDOS__ */ + } #ifdef DONTDEF -/* + /* * Message management. * * anno writes a message prefix on stream (eg stdout, stderr). @@ -1176,249 +1317,264 @@ close_archive() * If the third argument is 1, the "saved" record # is used; if 0, the * "current" record # is used. */ -void -anno(stream, prefix, savedp) - FILE *stream; - char *prefix; - int savedp; -{ + void + anno (stream, prefix, savedp) + FILE *stream; + char *prefix; + int savedp; + { # define MAXANNO 50 - char buffer[MAXANNO]; /* Holds annorecment */ + char buffer[MAXANNO]; /* Holds annorecment */ # define ANNOWIDTH 13 - int space; - long offset; - int save_e; - - save_e=errno; - /* Make sure previous output gets out in sequence */ - if (stream == stderr) - fflush(stdout); - if (f_sayblock) { - if (prefix) { - fputs(prefix, stream); - putc(' ', stream); - } - offset = ar_record - ar_block; - (void) sprintf(buffer, "rec %d: ", - savedp? saved_recno: - baserec + offset); - fputs(buffer, stream); - space = ANNOWIDTH - strlen(buffer); - if (space > 0) { - fprintf(stream, "%*s", space, ""); - } - } else if (prefix) { - fputs(prefix, stream); - fputs(": ", stream); - } - errno=save_e; -} -#endif - -/* Called to initialize the global volume number. */ -int -init_volume_number () -{ - FILE *vf; - - vf = fopen (f_volno_file, "r"); - if (!vf && errno != ENOENT) - msg_perror ("%s", f_volno_file); - - if (vf) - { - fscanf (vf, "%d", &global_volno); - fclose (vf); - } -} - -/* Called to write out the closing global volume number. */ -int -closeout_volume_number () -{ - FILE *vf; - - vf = fopen (f_volno_file, "w"); - if (!vf) - msg_perror ("%s", f_volno_file); - else - { - fprintf (vf, "%d\n", global_volno); - fclose (vf); - } -} - -/* We've hit the end of the old volume. Close it and open the next one */ -/* Values for type: 0: writing 1: reading 2: updating */ -int -new_volume(type) -int type; -{ - int c; - char inbuf[80]; - char *p; - static FILE *read_file = 0; - extern int now_verifying; - extern char TTY_NAME[]; - static int looped = 0; - - if(!read_file && !f_run_script_at_end) - read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin; - - if(now_verifying) - return -1; - if(f_verify) - verify_volume(); - if((c=rmtclose(archive))<0) - msg_perror("Warning: can't close %s(%d,%d)",ar_files[cur_ar_file],archive,c); - - global_volno++; - volno++; - cur_ar_file++; - if (cur_ar_file == n_ar_files) + int space; + long offset; + int save_e; + + save_e = errno; + /* Make sure previous output gets out in sequence */ + if (stream == stderr) + fflush (stdout); + if (f_sayblock) + { + if (prefix) { - cur_ar_file = 0; - looped = 1; + fputs (prefix, stream); + putc (' ', stream); } - - tryagain: - if (looped) + offset = ar_record - ar_block; + (void) sprintf (buffer, "rec %d: ", + savedp ? saved_recno : + baserec + offset); + fputs (buffer, stream); + space = ANNOWIDTH - strlen (buffer); + if (space > 0) { - /* We have to prompt from now on. */ - if (f_run_script_at_end) - system(info_script); - else for(;;) { - fprintf(msg_file,"\007Prepare volume #%d for %s and hit return: ",global_volno, ar_files[cur_ar_file]); - fflush(msg_file); - if(fgets(inbuf,sizeof(inbuf),read_file)==0) { - fprintf(msg_file,"EOF? What does that mean?"); - if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) - msg("Warning: Archive is INCOMPLETE!"); - exit(EX_BADARCH); - } - if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y') - break; + fprintf (stream, "%*s", space, ""); + } + } + else if (prefix) + { + fputs (prefix, stream); + fputs (": ", stream); + } + errno = save_e; + } +#endif - switch(inbuf[0]) { - case '?': - { - fprintf(msg_file,"\ + /* Called to initialize the global volume number. */ + int + init_volume_number () + { + FILE *vf; + + vf = fopen (f_volno_file, "r"); + if (!vf && errno != ENOENT) + msg_perror ("%s", f_volno_file); + + if (vf) + { + fscanf (vf, "%d", &global_volno); + fclose (vf); + } + } + + /* Called to write out the closing global volume number. */ + int + closeout_volume_number () + { + FILE *vf; + + vf = fopen (f_volno_file, "w"); + if (!vf) + msg_perror ("%s", f_volno_file); + else + { + fprintf (vf, "%d\n", global_volno); + fclose (vf); + } + } + + /* We've hit the end of the old volume. Close it and open the next one */ + /* Values for type: 0: writing 1: reading 2: updating */ + int + new_volume (type) + int type; + { + int c; + char inbuf[80]; + char *p; + static FILE *read_file = 0; + extern int now_verifying; + extern char TTY_NAME[]; + static int looped = 0; + + if (!read_file && !f_run_script_at_end) + read_file = (archive == 0) ? fopen (TTY_NAME, "r") : stdin; + + if (now_verifying) + return -1; + if (f_verify) + verify_volume (); + if ((c = rmtclose (archive)) < 0) + msg_perror ("Warning: can't close %s(%d,%d)", ar_files[cur_ar_file], archive, c); + + global_volno++; + volno++; + cur_ar_file++; + if (cur_ar_file == n_ar_files) + { + cur_ar_file = 0; + looped = 1; + } + + tryagain: + if (looped) + { + /* We have to prompt from now on. */ + if (f_run_script_at_end) + system (info_script); + else + for (;;) + { + fprintf (msg_file, "\007Prepare volume #%d for %s and hit return: ", global_volno, ar_files[cur_ar_file]); + fflush (msg_file); + if (fgets (inbuf, sizeof (inbuf), read_file) == 0) + { + fprintf (msg_file, "EOF? What does that mean?"); + if (cmd_mode != CMD_EXTRACT && cmd_mode != CMD_LIST && cmd_mode != CMD_DIFF) + msg ("Warning: Archive is INCOMPLETE!"); + exit (EX_BADARCH); + } + if (inbuf[0] == '\n' || inbuf[0] == 'y' || inbuf[0] == 'Y') + break; + + switch (inbuf[0]) + { + case '?': + { + fprintf (msg_file, "\ n [name] Give a new filename for the next (and subsequent) volume(s)\n\ q Abort tar\n\ ! Spawn a subshell\n\ ? Print this list\n"); - } - break; + } + break; - case 'q': /* Quit */ - fprintf(msg_file,"No new volume; exiting.\n"); - if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF) - msg("Warning: Archive is INCOMPLETE!"); - exit(EX_BADARCH); + case 'q': /* Quit */ + fprintf (msg_file, "No new volume; exiting.\n"); + if (cmd_mode != CMD_EXTRACT && cmd_mode != CMD_LIST && cmd_mode != CMD_DIFF) + msg ("Warning: Archive is INCOMPLETE!"); + exit (EX_BADARCH); - case 'n': /* Get new file name */ - { - char *q,*r; - static char *old_name; - - for(q= &inbuf[1];*q==' ' || *q=='\t';q++) - ; - for(r=q;*r;r++) - if(*r=='\n') - *r='\0'; - old_name=p=(char *)malloc((unsigned)(strlen(q)+2)); - if(p==0) { - msg("Can't allocate memory for name"); - exit(EX_SYSTEM); - } - (void) strcpy(p,q); - ar_files[cur_ar_file]=p; - } - break; + case 'n': /* Get new file name */ + { + char *q, *r; + static char *old_name; + + for (q = &inbuf[1]; *q == ' ' || *q == '\t'; q++) + ; + for (r = q; *r; r++) + if (*r == '\n') + *r = '\0'; + old_name = p = (char *) malloc ((unsigned) (strlen (q) + 2)); + if (p == 0) + { + msg ("Can't allocate memory for name"); + exit (EX_SYSTEM); + } + (void) strcpy (p, q); + ar_files[cur_ar_file] = p; + } + break; - case '!': + case '!': #ifdef __MSDOS__ - spawnl(P_WAIT,getenv("COMSPEC"),"-",0); + spawnl (P_WAIT, getenv ("COMSPEC"), "-", 0); #else - /* JF this needs work! */ - switch(fork()) { - case -1: - msg_perror("can't fork!"); - break; - case 0: - p=getenv("SHELL"); - if(p==0) p="/bin/sh"; - execlp(p,"-sh","-i",0); - msg_perror("can't exec a shell %s",p); - _exit(55); - default: - wait(0); - break; - } + /* JF this needs work! */ + switch (fork ()) + { + case -1: + msg_perror ("can't fork!"); + break; + case 0: + p = getenv ("SHELL"); + if (p == 0) + p = "/bin/sh"; + execlp (p, "-sh", "-i", 0); + msg_perror ("can't exec a shell %s", p); + _exit (55); + default: + wait (0); + break; + } #endif - break; - } - } - } - - - if(type==2 || f_verify) - archive=rmtopen(ar_files[cur_ar_file],O_RDWR|O_CREAT,0666); - else if(type==1) - archive=rmtopen(ar_files[cur_ar_file],O_RDONLY,0666); - else if(type==0) - archive=rmtcreat(ar_files[cur_ar_file],0666); - else - archive= -1; - - if(archive<0) { - msg_perror("can't open %s",ar_files[cur_ar_file]); - goto tryagain; - } + break; + } + } + } + + + if (type == 2 || f_verify) + archive = rmtopen (ar_files[cur_ar_file], O_RDWR | O_CREAT, 0666); + else if (type == 1) + archive = rmtopen (ar_files[cur_ar_file], O_RDONLY, 0666); + else if (type == 0) + archive = rmtcreat (ar_files[cur_ar_file], 0666); + else + archive = -1; + + if (archive < 0) + { + msg_perror ("can't open %s", ar_files[cur_ar_file]); + goto tryagain; + } #ifdef __MSDOS__ - setmode(archive,O_BINARY); + setmode (archive, O_BINARY); #endif - return 0; -} + return 0; + } -/* this is a useless function that takes a buffer returned by wantbytes + /* this is a useless function that takes a buffer returned by wantbytes and does nothing with it. If the function called by wantbytes returns an error indicator (non-zero), this function is called for the rest of the file. */ -int -no_op(size,data) -int size; -char *data; -{ - return 0; -} + int + no_op (size, data) + int size; + char *data; + { + return 0; + } -/* Some other routine wants SIZE bytes in the archive. For each chunk of + /* Some other routine wants SIZE bytes in the archive. For each chunk of the archive, call FUNC with the size of the chunk, and the address of the chunk it can work with. */ -int -wantbytes(size,func) -long size; -int (*func)(); -{ - char *data; - long data_size; - - while(size) { - data = findrec()->charptr; - if (data == NULL) { /* Check it... */ - msg("Unexpected EOF on archive file"); - return -1; - } - data_size = endofrecs()->charptr - data; - if(data_size>size) - data_size=size; - if((*func)(data_size,data)) - func=no_op; - userec((union record *)(data + data_size - 1)); - size-=data_size; - } - return 0; -} + int + wantbytes (size, func) + long size; + int (*func) (); + { + char *data; + long data_size; + + while (size) + { + data = findrec ()->charptr; + if (data == NULL) + { /* Check it... */ + msg ("Unexpected EOF on archive file"); + return -1; + } + data_size = endofrecs ()->charptr - data; + if (data_size > size) + data_size = size; + if ((*func) (data_size, data)) + func = no_op; + userec ((union record *) (data + data_size - 1)); + size -= data_size; + } + return 0; + } -- 2.45.2 From 363eb1d48afd94adb4488443dd26bbb3724a2fb6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:47:13 +0000 Subject: [PATCH 15/16] *** empty log message *** --- src/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/buffer.c b/src/buffer.c index 5c1b808..6514461 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -403,7 +403,7 @@ child_open () } else /* This can't happen if (ar_reading==2) archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666); - else */ if (ar_reading) + else */ if (ar_reading) archive = rmtopen (ar_files[0], O_RDONLY | O_BINARY, 0666); else archive = rmtcreat (ar_files[0], 0666); -- 2.45.2 From 0afb59a03f6f18a574751a52f6e130ac2d8d0f87 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Pinard?= Date: Wed, 16 Nov 1994 02:47:16 +0000 Subject: [PATCH 16/16] *** empty log message *** --- src/buffer.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 6514461..6032255 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -403,7 +403,7 @@ child_open () } else /* This can't happen if (ar_reading==2) archive = rmtopen(ar_files[0], O_RDWR|O_CREAT|O_BINARY, 0666); - else */ if (ar_reading) + else */ if (ar_reading) archive = rmtopen (ar_files[0], O_RDONLY | O_BINARY, 0666); else archive = rmtcreat (ar_files[0], 0666); @@ -1260,24 +1260,23 @@ close_archive () if (childpid) { /* - * Loop waiting for the right child to die, or for - * no more kids. - */ + * Loop waiting for the right child to die, or for + * no more kids. + */ while (((child = wait (&status)) != childpid) && child != -1) ; if (child != -1) { - { - if (WIFSIGNALED (status)) - { - /* SIGPIPE is OK, everything else is a problem. */ - if (WTERMSIG (status) != SIGPIPE) - msg ("child died with signal %d%s", WTERMSIG (status), - WIFCOREDUMPED (status) ? " (core dumped)" : ""); - } - else - { + if (WIFSIGNALED (status)) + { + /* SIGPIPE is OK, everything else is a problem. */ + if (WTERMSIG (status) != SIGPIPE) + msg ("child died with signal %d%s", WTERMSIG (status), + WIFCOREDUMPED (status) ? " (core dumped)" : ""); + } + else + { /* Child voluntarily terminated -- but why? */ if (WEXITSTATUS (status) == MAGIC_STAT) { @@ -1296,9 +1295,9 @@ close_archive () WEXITSTATUS (status)); } } - } -#endif /* __MSDOS__ */ } +#endif /* __MSDOS__ */ +} #ifdef DONTDEF -- 2.45.2