/* bug: xs testblock -v -n bla Neither -w or -r specified, so will both write then read. Block size 61440 (0xf000). Caution: Unusual combination of options -n, -w, & -r. Writing then reading. Writing bla. NEEB1 38,744,186,880 /mnt: write failed, filesystem is full 18,446,744,073,709,551,615 Wrote -1 bytes, after previous 38,744,186,880 (0x5556000) bytes (630602 * 61440 (0xf000) byte blocks). NEEB2 Reading bla. 18,446,744,073,709,551,615 Read 0 bytes, after previous 38,744,186,880 (0x5556000) bytes (630602 * 61440 (0xf000) byte blocks). --------------- Neither -w or -r specified, so will both write then read. Block size 61440 (0xf000). Caution: Unusual combination of options -n, -w, & -r. Writing then reading. Writing bla. NEEB1 475,228,446,720 /600/usr: write failed, filesystem is full 18,446,744,073,709,551,615 Wrote -1 bytes, after previous 475,228,446,720 (0xa5d2a000) bytes (7734838 * 61440 (0xf000) byte blocks). NEEB2 Reading bla. 18,446,744,073,709,551,615 Read 0 bytes, after previous 475,228,446,720 (0xa5d2a000) bytes (7734838 * 61440 (0xf000) byte blocks). -rw-r----- 1 root wheel 475228446720 Sep 11 17:32 bla */ #ifdef ournix #include "ournix.h" #endif #ifndef LINT /* { */ char sccsID[] ="@(#) testblock.c V2.7 1997.05.20 Copyright Julian H. Stacey, Munich, 1990 03 09.\n"; #endif /* } */ /* A manual exists. */ #include #ifndef MSDOS /* { unix */ #include #else /* } { */ #define L_SET 0 /* absolute offset */ #endif /* } */ #include #include #if ( MSDOS || pc532 ) /* { */ #include #endif /* } */ #ifdef i386 /* { */ #include #endif /* } */ #include #undef HARDWARE_DEBUG #ifdef HARDWARE_DEBUG /* { */ /* Define HARDWARE_DEBUG only if you want to prove that when a tape is damaged, and repaired, does have a leader at the beginning of tape, but not at the end, and then stalls, although the driver sends a stall message to /dev/console, no signal is received by this program, and neither this program, nor dd can rewind the tape, before the tape is first removed & re-inserted. */ #include #endif /* } */ #ifdef scs #define BSD4_2 #endif extern int atoi() ; extern long atoll() ; #if MSDOS /*{*/ extern char *malloc() ; #endif /*}*/ typedef char FLAG ; char **ARGV; FLAG fixed_f = 0 ; /* 1 = all block bytes are to have a fixed value */ FLAG pipe_f = 0 ; /* 1 = tape data is to be connected to a process pipe */ FLAG write_f = 0 ; /* 1 = write tape (& possibly then read tape) */ FLAG read_f = 0 ; /* 1 = read tape (possibly after writing tape) */ FLAG verbose_f = 0 ; /* 1 = provide verbose diagnostics */ FLAG ignore_f = 0 ; /* 1 = ignore single isolated errors */ FLAG no_rewind_f = 0 ; /* 1 = dont rewind before testing tape, allows user to skip tape label by reading a no_rewind_on_close device from a shell script, before then calling testblock */ FLAG no_rotate_f = 0 ; /* 1 = force byte number zero in every block to be zero; default is to let each succesive block have its byte #0 start with an incrementally higher value */ FLAG announce_f = 0 ; /* 1 = announce test file name */ unsigned count ; unsigned display_ln ; unsigned byte_data ; unsigned block_size = #ifdef scs 8 /* same size as tar B */ /* Symmetric Unix device driver actually appears to write 8192 bytes at a time to /dev/rcst2, regardless of the block size this user program passes to the system */ #else #ifdef i386 60 /* my 525M streamer drive doesnt stream with 8K */ #else 8 #endif #endif * 1024 ; #define longlong unsigned long long /* long on FreeBSD is 4 bytes, long long is 8 */ longlong user_limit = (longlong)0 ; /* user specified limit on number of bytes */ longlong fail_limit = (longlong)0 ; /* user specified threshold (in bytes), * below which, we dont bother to do a read * after write (because tape is too short) * 0=unset, ie never inhibit read after write */ longlong written_limit ; /* reduced limit discovered on writing, that we pass to subsequent read */ unsigned char *base_out_p ; /* read pointer */ unsigned char *base_in_p ; /* read pointer */ char default_tape[] = #ifdef unix /* { */ "/dev/rtape" ; /*use a symbolic link /dev/rtape --> /dev/rmt8 or rsa0*/ #endif /* } */ #ifdef MSDOS /* { */ "/dev/ct0" ; #endif /* } */ #ifndef pc532 FILE *my_out ; #else struct _iobuf *my_out ; #endif my_exit(val) int val ; { /* if (verbose_f) fprintf(my_out,"Finished.\n"); */ exit(val) ; } void syntax() { fprintf(stderr, "%s\n%s %s %s [-- or special_file[s]]\n", "Syntax error, correct syntax is:", *ARGV, "[-i] [-n] [-r] [-v] [-w] [-u]", "[-b block_size] [-d data_byte] [-f fail_size] [-l byte_limit]" ) ; my_exit(1) ; } /* Convert longlong to a comma separated digit string, of form 18,446,74x,xxx,xxx,xxx,xxx Bytes Bits Name String Scientific 1 8 256 2- 10 1 K 1,024 2 16 64 K 65,536 3- 20 1 M 1,048,576 3 24 16 M 16,777,216 4- 30 1 G 1,073,741,824 4- 31 2 G 2,147,483,648 4 32 4 G 4,294,967,296 4.294967e+09 5 40 1 T 1,099,511,xxx,xxx 1.099511e+12 6 48 256 T 281,474,9xx,xxx,xxx 2.814749e+14 7 56 64 KT 72,057,59x,xxx,xxx,xxx 7.205759e+16 8 64 16 MT 18,446,74x,xxx,xxx,xxx,xxx 1.844674e+19 */ #define L2COMMA (( 7 * 4 ) + 1) /* 7 * {3 digit chunk + comma}, less no terminal comma, plus null, plus negative sign. Allows up to "-999,999,999,999,999,999,999" */ void l2comma(number,out) longlong number ; /* Input */ char *out ; /* Output, supplied by caller, >= L2COMMA */ { char tmp[L2COMMA ] ; char *out_p, *tmp_p ; short comma ; longlong num = number ; if (num == (longlong)0) { out[0] = '0' ; out[1] = '\0' ; return ; } if (num < (longlong)0) { out[0] = '-' ; out[1] = '\0' ; num = (longlong)0 - num ; } /* make a reverse digit string with commas */ tmp_p = tmp ; comma = 0 ; do { *tmp_p++ = '0' + (num % 10) ; num /= 10 ; if ((++comma == 3) && num ) { comma = 0 ; *tmp_p++ = ',' ; } } while ( num ) ; out_p = out ; while ( tmp_p > tmp ) *out_p++ = *--tmp_p ; *out_p = '\0' ; } void show_size(size) longlong size ; { char array[L2COMMA] ; unsigned length ; if (size >= (longlong)0) { /* (void) sprintf(array,"%ld",size) ; */ l2comma(size,array) ; printf("\r%s",array) ; display_ln = strlen(array) ; } else { /* negative */ for ( length = display_ln ; length-- ; putchar('\b') ) ; for ( length = display_ln ; length-- ; putchar(' ') ) ; for ( length = display_ln ; length-- ; putchar('\b') ) ; display_ln = 0 ; } (void)fflush(stdout) ; } #ifdef HARDWARE_DEBUG /* { */ my_sigint() { printf("%s caught signal sigint() \n",*ARGV) ; my_exit(1); } #ifndef MSDOS /* { */ my_sighup() { printf("%s caught signal sighup() \n",*ARGV) ; my_exit(1); } my_sigquit() { printf("%s caught signal sigquit() \n",*ARGV) ; my_exit(1); } my_sigill() { printf("%s caught signal sigill() \n",*ARGV) ; my_exit(1); } my_sigiot() { printf("%s caught signal sigiot() \n",*ARGV) ; my_exit(1); } my_sigemt() { printf("%s caught signal sigemt() \n",*ARGV) ; my_exit(1); } my_sigfpe() { printf("%s caught signal sigfpe() \n",*ARGV) ; my_exit(1); } my_sigalrm() { printf("%s caught signal sigalrm() \n",*ARGV) ; my_exit(1); } my_sigbus() { printf("%s caught signal sigbus() \n",*ARGV) ; my_exit(1); } my_sigsegv() { printf("%s caught signal sigsegv() \n",*ARGV) ; my_exit(1); } my_sigterm() { printf("%s caught signal sigterm() \n",*ARGV) ; my_exit(1); } #ifdef BSD4_2 /* { */ my_sigtstp() { printf("%s caught signal sigtstp() \n",*ARGV) ; my_exit(1); } #endif /* } */ #endif /* } */ sigs_assign(where_to) int (*where_to)() ; { if (where_to == SIG_DFL) { (void)signal(SIGINT,where_to) ; #ifndef MSDOS /* { */ (void)signal(SIGHUP,where_to) ; (void)signal(SIGQUIT,where_to) ; (void)signal(SIGILL,where_to) ; (void)signal(SIGIOT,where_to) ; (void)signal(SIGEMT,where_to) ; (void)signal(SIGFPE,where_to) ; (void)signal(SIGALRM,where_to) ; (void)signal(SIGBUS,where_to) ; (void)signal(SIGSEGV,where_to) ; (void)signal(SIGTERM,where_to) ; #ifdef BSD4_2 /* { */ (void)signal(SIGTSTP,where_to) ; #endif /* } */ #endif /* } */ } else { (void)signal(SIGINT,my_sigint) ; /* ^C, or DEL */ #ifndef MSDOS /* { */ (void)signal(SIGHUP,my_sighup) ; (void)signal(SIGQUIT,my_sigquit); /* ^\ = core dump */ (void)signal(SIGILL,my_sigill) ; (void)signal(SIGIOT,my_sigiot) ; (void)signal(SIGEMT,my_sigemt) ; (void)signal(SIGFPE,my_sigfpe) ; (void)signal(SIGALRM,my_sigalrm); (void)signal(SIGBUS,my_sigbus) ; (void)signal(SIGSEGV,my_sigsegv); (void)signal(SIGTERM,my_sigterm); #ifdef BSD4_2 /* { */ (void)signal(SIGTSTP,my_sigtstp); /* Job suspend ^Z */ #endif /* } */ #endif /* } */ } } my_sigdummy() { printf("%s caught signal sigdummy() \n",*ARGV) ; } #endif /* } */ extern int read() ; extern int write() ; extern int close() ; extern u_int sleep() ; /* Open & close device to ensure if the physical device was previously * used as `a no rewind on completion' tape drive, that it will now be * rewound prior to use. * fd is not left open because although it would be slightly more effecient * on cpu, it would complicate the code too much, and anyway, compared * with the real physical device work we are doing, a couple more system * calls dont make much difference */ int my_rewind(name) char *name ; { int fd ; /* file descrip */ if (verbose_f) { fprintf(my_out, "Started rewinding") ; if (announce_f) fprintf(my_out, " %s",name) ; fprintf(my_out, ", ") ; fflush(my_out) ; } if ((fd = open(name, O_RDONLY )) == EOF) { fprintf(my_out, "%s: Error: failed to open %s to ensure rewound.\n", *ARGV, name) ; perror(*ARGV) ; return(1) ; } /* now rewind tape */ /* used to do an lseek, but maybe this doesnt retention tape, * so after a tape got mangled, repaired, mangled again, * i decided to do a real read followed by close, to ensure * tape is rewound, but I dont really know how the * TEAC drive is controlled, so this read may be * superfluous, however before taking it out, consider * the possibility of multiple system crashes whilst the * tape is inserted, and or multiple insertions before * the tape is actually used. * Only problem with a read is that if it is virgin media, * tape driver reports an error on /dev/console. */ if ( #if 0 lseek(fd,(off_t)0,L_SET) != (off_t)0 #else read(fd,base_in_p,block_size) != block_size #endif ) { fprintf(my_out, "Error: failed to rewind %s.\n", name) ; fprintf(my_out, "(If when writing you get \"failed to open\", try using \"-n\".)\n" ) ; /* if no correct sized data block previously on tape, the rewind fails */ perror(*ARGV) ; return(1) ; } (void) close(fd) ; if (verbose_f) fprintf(my_out, "finished rewinding.\n") ; return(0); } /* Initialise reference block ? */ void init_ref(block_offset) unsigned block_offset ; { unsigned char *var_out_p ; /* write pointer */ unsigned data, count ; count = block_size; var_out_p = base_out_p ; if (fixed_f) for ( ; count-- ; data++ ) *var_out_p++ = byte_data ; else if (no_rotate_f) for (data = 0 ; count-- ; data++ ) *var_out_p++ = ( 0xFF & data) ; else for (data = block_offset ; count-- ; data++ ) *var_out_p++ = ( 0xFF & data) ; } /* Print EG Wrote -1 bytes after previous 6,574,080 (0x645000)bytes (107 * 61440 (0xf000) byte blocks. */ void show_it(r_w,remainder,name,total) char *r_w ; int remainder; char *name ; longlong total ; { char buf[L2COMMA] ; fprintf(my_out, "\n" ) ; if (announce_f) fprintf(my_out, "%s: ", name ) ; fprintf(my_out, "%s %d",r_w, remainder ) ; if (remainder > 9L) /* print hex too */ fprintf(my_out, " (0x%x)", (unsigned)remainder ) ; l2comma(total,buf) ; fprintf(my_out, " bytes, after previous %s", buf ) ; if (total > 9) /* print hex too */ fprintf(my_out, " (0x%lx)", total); fprintf(my_out, " bytes"); if (total > block_size) /* show in blocks */ fprintf(my_out, "\n\t(%ld * %d (0x%x) byte blocks)", (long)(total/block_size), block_size,block_size ); } /* return 0 = ok, 1 = error */ int do_tape(name) char *name ; { int fd ; /* file descrip */ longlong cumulative ; /* byte count, increments in block_size, eg 0,60K,120K */ char *message ; unsigned char *var_in_p ; /* read pointer */ unsigned char *var_out_p ; /* write pointer */ int do_tape_tmp_int ; int errs = 0 ; char buf_a[L2COMMA] ; char buf_b[L2COMMA] ; FLAG count_fail ; /* detect sequential byte count failures */ FLAG check_fail ; /* detect sequential data check failures */ FLAG old_check_fail; /* detect sequential data check failures */ unsigned block_offset ; if (write_f) { if (read_f) message = "Writing then reading" ; else message = "Writing (with no subsequent Reading)" ; } else message = "Reading (with no prior Writing)" ; if (verbose_f) { fprintf(my_out,"%s", message); if (announce_f) fprintf(my_out," %s", name); /* fprintf(my_out,".\n"); */ fprintf(my_out,". "); } if (write_f) { #ifdef HARDWARE_DEBUG /* { */ sigs_assign(my_sigdummy) ; /* mask signals */ #endif /* } */ if (!pipe_f && !no_rewind_f) (void) my_rewind(name); if (verbose_f && !pipe_f) fprintf(my_out, "Writing %s.\n", name) ; if (pipe_f) fd = fileno(stdout) ; else if ((fd = open(name,O_WRONLY | O_CREAT | O_TRUNC #ifdef MSDOS /* { */ | O_BINARY , S_IWRITE #else /* } { */ ,0640 #endif /* } */ )) == EOF ) { perror(*ARGV) ; fprintf(my_out, "%s: Error: failed to open %s for writing.\n", *ARGV, name) ; return(1) ; } /* BUG JJLATER It reads & writes data OK, just the count is wrong. Im too busy to fix it. NEEB1 18,446,744,073,709,551,615 Wrote -1 bytes, after previous 4,294,963,200 (0xfffff000) bytes (69905 * 61440 (0xf000) byte blocks). NEEB2 Reading BLA. 18,446,744,073,709,551,615 Read 0 bytes, after previous 2,093,629,440 (0x7cca4000) bytes NEEB2 Reading BLA. 18,446,744,073,709,551,615 Read 0 bytes, after previous 4,294,963,200 (0xfffff000) bytes (69905 * 61440 (0xf000) byte blocks). */ printf("\nNEEB1\n"); cumulative = (longlong)0 ; display_ln = 0 ; count_fail = 0 ; block_offset = 0 ; for (;;) { init_ref(block_offset++); if ( (do_tape_tmp_int = write(fd, (char *)base_out_p, (int)block_size ) ) == block_size ) count_fail = 0 ; else { if (verbose_f) show_size((longlong)-1) ; show_it("Wrote",do_tape_tmp_int,name, cumulative); if ( (user_limit != (longlong)0) || (cumulative == (longlong)0) ) { l2comma(user_limit - cumulative ,buf_a) ; fprintf(my_out, ", %s unwritten.\n",buf_a); errs++ ; } else fprintf(my_out,".\n"); /* note an error if write fails either * - before expected limit is reached, or * - if you over run threshold, for * instance by using 7 byte blocks * on a 50 byte limit. */ if ( count_fail++ || !ignore_f) break ; } if (!count_fail) cumulative += block_size ; if (verbose_f) show_size(cumulative) ; if ((user_limit != (longlong)0) && ( cumulative >= user_limit ) ) { if (verbose_f) show_size((longlong)-1) ; break ; } } printf("\nNEEB2\n"); written_limit = cumulative ; if (!pipe_f) (void) close(fd) ; /* Normal unix philosophy - no news is good news. * Make no announcement of bytes succesfully written, * only if we failed will an announcement appear. */ #ifdef HARDWARE_DEBUG /* { */ sigs_assign(SIG_DFL) ; #endif /* } */ } if (read_f) { if ((fail_limit) && (written_limit < fail_limit)) { fprintf(my_out, "Not bothering to read after write as tape too short.\n" ); return(1) ; } #ifdef HARDWARE_DEBUG /* { */ sigs_assign(my_sigdummy) ; /* mask signals */ #endif /* } */ if (write_f) { /* We were previously writing the tape, * allow drive to start rewinding. * (On SCS this avoids error message of data mismatch.) * havent tested to see if sleep needed for 486pc. * No point in calling my_rewind(), either the device * will of its own accord, or if this program * was passed a `no rewind on close` device name, * then calling my_rewind() wont help anyway. */ #ifndef MSDOS /* { */ sleep(5) ; #else /* } { */ my_sleep(5) ; /* sleep() is not available on msdos, I've not written sleep for msdos. */ #endif /* } */ } else { /* rewind if not a pipe, & if user has not forbiden us, * user may have forbidden us because he's stepped past * a tape label written as a seperate file before data * created by this program */ if (!pipe_f && !no_rewind_f) (void) my_rewind(name); } if (!write_f) written_limit = user_limit ; cumulative = (longlong)0 ; if (verbose_f && !pipe_f) fprintf(my_out, "Reading %s.\n", name) ; if (pipe_f) fd = fileno(stdin) ; else if ((fd = open(name,O_RDONLY #ifdef MSDOS /* { */ | O_BINARY , S_IREAD #else /* } { */ ,0640 #endif /* } */ )) == EOF ) { perror(*ARGV) ; my_exit(1) ; } check_fail = old_check_fail = count_fail = display_ln = 0 ; block_offset = 0 ; for (;;) { init_ref(block_offset++); if ( (do_tape_tmp_int = read(fd, (char *)base_in_p, (int)block_size ) ) == block_size ) count_fail = 0 ; else { show_size((longlong)-1) ; show_it("Read",do_tape_tmp_int,name, cumulative); fprintf(my_out,".\n"); errs++ ; if (count_fail++ || !ignore_f) break ; } /* if (verbose_f) fprintf(my_out,"%s: read %d.\n", *ARGV,do_tape_tmp_int) ; */ /* check each byte read is what it should be*/ if ( !count_fail ) { old_check_fail = check_fail ; check_fail = 0 ; for (count = 0, var_in_p = base_in_p, var_out_p = base_out_p ; count < block_size ; count++ ) { if (*var_in_p++ != ((fixed_f) ? byte_data : *var_out_p++) ) { if (verbose_f) show_size((longlong)-1) ; check_fail++; break ; } } } if (check_fail) { l2comma(cumulative,buf_a) ; if (announce_f) fprintf(my_out, "%s: ", name ) ; fprintf(my_out, "Error at byte %u ", count + 1 ) ; if (count + 1 > 9) fprintf(my_out, "(0x%x), ", count + 1 ) ; fprintf(my_out, "after %s ", buf_a); if (cumulative > 9) fprintf(my_out, "(0x%lx)", cumulative ) ; fprintf(my_out, "previously read;\n"); fprintf(my_out, "Byte read 0x%x, but expected 0x%x.\n", *--var_in_p, ((fixed_f) ? byte_data : *--var_out_p) ) ; errs++ ; if (!ignore_f) break ; else if (old_check_fail) break ; } if (!count_fail) cumulative += block_size ; if (verbose_f) show_size(cumulative) ; if ((user_limit != (longlong)0) && ( cumulative >= written_limit ) ) { if (verbose_f) show_size((longlong)-1) ; break ; } } if (!pipe_f) (void) close(fd) ; if ((user_limit != (longlong)0) && (written_limit != cumulative)) { l2comma( cumulative ,buf_a) ; l2comma( written_limit - cumulative ,buf_b) ; fprintf(my_out, "%s: only checked %s bytes, %s failed.\n", name, buf_a, buf_b ) ; errs++; } #ifdef HARDWARE_DEBUG /* { */ sigs_assign(SIG_DFL) ; #endif /* } */ } return(errs?1:0) ; } int main(argc,argv) int argc ; char **argv ; { int errs = 0 ; /* cumulative error count */ int main_tmp_int ; char *p_tmp ; ARGV = argv ; #ifdef VSL /* { */ #include "../../include/vsl.h" #endif /* } */ my_out = stdout ; while (--argc) { if (**++argv == '-') { switch ( *++*argv ) { case 'i' : ignore_f = 1 ; break ; case 'n' : no_rewind_f = 1 ; break ; case 'r' : read_f = 1 ; break ; case 'v' : verbose_f = 1 ; break ; case 'w' : write_f = 1 ; break ; case '-': pipe_f = 1 ; break ; case '0': no_rotate_f = 1 ; break ; case 'b' : if (--argc <= 0) syntax() ; ++argv ; if (!(isdigit(**argv))) syntax() ; p_tmp = *argv+strlen(*argv) -1 ; main_tmp_int = 1 ; if ((*p_tmp == 'g') || (*p_tmp == 'G') ) { main_tmp_int = 1024 * 1024 * 1024 ; *p_tmp = '\0' ; /* ridiculous really */ } else if ((*p_tmp == 'm') || (*p_tmp == 'M') ) { main_tmp_int = 1024 * 1024 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'k') || (*p_tmp == 'K') ) { main_tmp_int = 1024 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'b') || (*p_tmp == 'B') ) { main_tmp_int = 512 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'w') || (*p_tmp == 'W') ) { main_tmp_int = 2 ; *p_tmp = '\0' ; } main_tmp_int = main_tmp_int * atoi(*argv); if (main_tmp_int < 0 ) syntax(); block_size = main_tmp_int ; break ; case 'd' : /* numeric value for all bytes*/ fixed_f = 1 ; if (--argc <= 0) syntax() ; if ((1 != sscanf(*++argv,"%x", &main_tmp_int)) || (main_tmp_int < 0) || (main_tmp_int > 0xFF) ) syntax() ; /* if ((main_tmp_int = atoi(*++argv)) < 0 ) syntax ; */ byte_data = main_tmp_int ; break ; case 'f' : if (--argc <= 0) syntax() ; ++argv ; if (!(isdigit(**argv))) syntax() ; p_tmp = *argv+strlen(*argv) -1 ; fail_limit = 1 ; if ((*p_tmp == 'g') || (*p_tmp == 'G') ) { fail_limit = 1024 * 1024 * 1024 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'm') || (*p_tmp == 'M') ) { fail_limit = 1024 * 1024 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'k') || (*p_tmp == 'K') ) { fail_limit = 1024 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'b') || (*p_tmp == 'B') ) { fail_limit = 512 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'w') || (*p_tmp == 'W') ) { fail_limit = 2 ; *p_tmp = '\0' ; } fail_limit = fail_limit * atoll(*argv); if (fail_limit < 0 ) syntax() ; break ; case 'l' : if (--argc <= 0) syntax() ; ++argv ; if (!(isdigit(**argv))) syntax() ; p_tmp = *argv+strlen(*argv) -1 ; user_limit = 1 ; if ((*p_tmp == 'g') || (*p_tmp == 'G') ) { user_limit = 1024 * 1024 * 1024 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'm') || (*p_tmp == 'M') ) { user_limit = 1024 * 1024 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'k') || (*p_tmp == 'K') ) { user_limit = 1024 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'b') || (*p_tmp == 'B') ) { user_limit = 512 ; *p_tmp = '\0' ; } else if ((*p_tmp == 'w') || (*p_tmp == 'W') ) { user_limit = 2 ; *p_tmp = '\0' ; } user_limit = user_limit * atoll(*argv); if (user_limit < 0 ) syntax() ; /* old code if ((user_limit = atol(*++argv)) < (longlong)0 ) syntax ; */ break ; default: syntax() ; break ; } } else break ; } if (!read_f && !write_f ) { fprintf(my_out, "Neither -w or -r specified, %s\n", "so will both write then read." ); read_f = write_f = 1 ; } if (verbose_f) { fprintf(my_out,"Block size %d (0x%x)", block_size,block_size); if (user_limit > (longlong)0) fprintf(my_out,", to a limit of %llu.\n", user_limit); else fprintf(my_out,".\n"); if (fail_limit > (longlong)0) fprintf(my_out,"Short tape failure limit %ld.\n", fail_limit); } if ((argc == 0) && !pipe_f) /* user has not specified file names or pipe IO, we will use default name, but in case user actually wanted pipe IO, we warn him */ fprintf(my_out, "%s %s,\nso using %s.\n", "Neither file name", " nor pipe IO specified", default_tape) ; if (pipe_f && read_f && write_f) { fprintf(stderr, "%s: Cannot read and write pipes.\n",*ARGV) ; /* no point, as would first be writing output pipe, then reading input pipe - which would be rather weird, and not in the tradition of unix pipes */ syntax() ; } if ((argc >= 1) && pipe_f) { fprintf(stderr, "%s: Pipes output and file output not allowed together.\n", *ARGV) ; syntax() ; } if (pipe_f && write_f) { /* Avoid errors going into pipe */ fprintf(stderr, "Status info will go to , avoiding data on pipeline.\n" ); my_out = stderr ; } if (no_rewind_f && read_f && write_f) fprintf(my_out, "Caution: Unusual combination of options -n, -w, & -r.\n") ; /* End of checking parameters */ if (((base_in_p = (unsigned char *)malloc(block_size)) == (unsigned char *)0) || ((base_out_p = (unsigned char *)malloc(block_size)) == (unsigned char *)0) ) { fprintf(stderr,"%s: malloc(%u) failed.\n",*ARGV,block_size) ; perror(*ARGV) ; my_exit(1) ; } if (pipe_f) my_exit(do_tape("pipe")) ; else if ((argc == 0) && !pipe_f) my_exit(do_tape(default_tape)) ; else { if (argc > 1 ) announce_f = 1 ; while (argc--) errs += do_tape(*argv++) ; } my_exit(errs) ; /* NEVER REACHED, to satisfy gcc -Wall */ return(errs) ; }