ramin@rtgvax.UUCP (Pantagruel) (08/26/86)
Dammit dammit dammit! I should've asked for it while it was flying past... I did see the request a few months back for a program to read TAR format tapes from VMS, but thought "oh well... who needs that." Well if anyone has one, I sure would appreciate getting a copy of it... Our unix tape drive is about to be shipped to the funny farm and the vms machines are getting all the new model ones... I looked in mod.sources listings but alas... I'll also check the decus tapes, but I doubt I'll have much luck. Thanks much... ramin -- =--------------------------------------=-------------------------------------= : alias: ramin firoozye' : USps: Systems Control Inc. : : uucp: ...!shasta \ : 1801 Page Mill Road : : ...!lll-lcc \ : Palo Alto, CA 94303 : : ...!ihnp4 \...!rtgvax!ramin : ^G: (415) 494-1165 x-1777 : =--------------------------------------=-------------------------------------=
bhoward@funvax.UUCP (Bruce Howard) (08/28/86)
> Dammit dammit dammit! > > I should've asked for it while it was flying past... I did see the > request a few months back for a program to read TAR format tapes from > VMS, but thought "oh well... who needs that." > > Well if anyone has one, I sure would appreciate getting a copy of > it... Our unix tape drive is about to be shipped to the funny farm and > the vms machines are getting all the new model ones... I looked in > mod.sources listings but alas... I'll also check the decus tapes, but > I doubt I'll have much luck. Gosh! And I thought we were the only people in the world with a screwball set up -- we have a network of VAXen that speak Internet and DECnet to each other. The only available tape drive unfortunately lies on the downstairs VAX 8600. In the long term, the BEST solution will be to obtain a TK50 or TU80? (something like that) tape drive. Anyways, please credit most of the following solution to Chris Lent at ...philabs!phri!cooper!chris. This method has been successfully used to read in our Berkeley distribution tapes. Additionally, I have managed to write what appear to be UNIX format tapes though I have not been able to test them on a tape drive attached to a UNIX host. First you must have an fdl file created that describes the file we are pulling off the UNIX format tape. I have not had the time nor the desire to fully understand its format but it seems to simply say that whatever it is we pull off the tape should be placed in a sequential file with no strange attributes: --- cut here --- IDENT "16-NOV-1985 09:34:31 VAX/VMS ANALYZE/RMS_FILE Utility" SYSTEM SOURCE VAX/VMS FILE ALLOCATION 13 BEST_TRY_CONTIGUOUS no CLUSTER_SIZE 1 CONTIGUOUS no EXTENSION 0 GLOBAL_BUFFER_COUNT 0 NAME "dua2:[bhoward.vms]tar.exe" ORGANIZATION sequential OWNER [647,24] PROTECTION (system:RWED, owner:RWED, group:RE, world:RE) RECORD BLOCK_SPAN yes CARRIAGE_CONTROL none FORMAT fixed SIZE 10240 --- cut here --- The owner field should be defined to be the UIC of the account which happens to be reading in the file. I don't think that which is defined in the NAME field is important, but you can experiment or look it up in the VMS docs. For purposes of this explanation, I shall assume you have typed this into a file named tarcvt.fdl Once you have this fdl typed in, the following steps will read a file off of the UNIX tape into a VMS file which can then be transported to UNIX via ethernet or kermit. $ mount mua0: /foreign/block=10240 (mua0: happens to be the name of our primary tape drive. 10240 is the block size on our berkeley tapes. Set as is appropriate for your tape.) $ convert /fdl=tarcvt.fdl mua0: nameoftarfile (this reads in the first file on the tape into a file on vms named nameoftarfile) $ dismount mua0: Sometimes, as in the case of the berkeley distribution, you have multiple files on a tape. One of ours had three sections. You can use the set mag command to move between files. For example, we wanted to pull off the ingress database which I believe was the third file of one tape. To do this we typed: $ mount mua0: /foreign/block=10240 $ set mag /skip=files:2 $ convert /fdl=tarcvt.fdl mua0: ingres.tar $ dismount mua0: Also useful, is set mag /rewind which rewinds without dismounting the tape. To write a tape file is almost the same as reading. You just switch the order around on the files, that is: $ mount mua0: /foreign/block=10240 $ convert /fdl=tarcvt.fdl usrbackup.tar mua0: $ convert /fdl=tarcvt.fdl srcbackup.dump mua0: $ dismount mua0: which places two files onto the tape. I have NOT confirmed that these tapes are readable by UNIX hosts. Here are a few tricks I've developed to read tar files across DECnet. For example, to pull off a directory name ./etc/getty from a tar file that has been placed onto VMS, from UNIX type: % dcp -i mother/bhoward::'[.archive]src.tar' - | tar -xvf - ./etc/getty Password for mother/bhoward::? (type password) (watch it verbosely untar) This can also be done with the cpio and dump commands though I don't believe it works with dump in interactive mode. I think this is slightly incomplete, but it should get you started. I plan of writing a more complete paper on these and other techniques our unique (silly) hardware situation has forced us to develop. Please feel free to ask me questions via mail. Cheers! Bruce -- --------------------------------- ...decvax!ittatc!funvax!bhoward Bruce Howard @ Fairfield University ...ihnp4!itivax!funvax!bhoward Located in Scenic Fairfield, CT 06430 ---------------------------------
ramin@rtgvax.UUCP (09/07/86)
Well... my recent inquiry about TAR programs in VMS garnished me the following responses... The last two have actual programs that were enclosed and I have included them verbatim (though it seems they are closely related... but I thought I'd throw them both in anyway...) I also have another FORTRAN one here that someone at a sister company wrote. I haven't included it since I don't know if he wants it distributed... I have not fully tested any of them. But since this machine is shortly due to go off the net I figured I should send it out before they pull the plug...(:-( Barring circumstances I should be back on the net via another system in about a month and I might fix up the programs to allow subdirectory creations, etc...) Again, thanks to all who responded. P.S. John Gilmore (hoptoad!gnu) has also offered a copy of a C TAR program he has... Hopefully I'll get it soon enough... If someone needs to try it out they could contact him directly if I'm not around... ramin *************************************************************************** From: H}vard Eidnes <lll-lcc!caip!seismo!mcvax!vax.runit.unit.uninett!H_Eidnes> I saw your recent request for some TAR program on VMS. It just happens that a friend of mine recently wrote such a program. The program is written in VMS Pascal. It has mainly been used to read TAR tapes down to TAR files on disk to be transferred to a Unix system to be unpacked. We've used Kermit to transfer from our VMS computer to a MicroVAX II (without 1/2" tape), and that has worked, but is slow, eg. it took 12hrs transferring TeX, but it worked... The Pascal program is capable of just extracting a part of a tape by giving it a starting and ending filename prefix. It also has routines to do actual extraction on VMS, but we haven't used these routines much. NB: the program only handles TAR files blocked 20. I will be happy to send you the program if you want it. *************************************************************************** From: lll-lcc!caip!uw-beaver!uw-june!gordon (Gordon Davisson) Here's a program that does what you want. It did get into a recent decus tape (VAX85C?), but that version happens to not work. Use this instead. -- Human: Gordon Davisson ARPA: gordon@uw-june.ARPA UUCP: {ihnp4,decvax,tektronix}!uw-beaver!uw-june!gordon Bitnet: gordon@uwaphast ATT: (206) 527-0832 USnail: 5008 12th NE, Seattle, WA, 98105 --------------- cut here, then run the file (with an @) --------------- $! $ write sys$output "creating CVT.FOR" $ create CVT.FOR $ deck c c this subroutine converts a complete filespec (directory+file) name from c unix format to VMS c subroutine cvt_dir_uv( unix, vms, vlen ) parameter reserved = 10 character*(*) unix, vms integer*2 vlen, i, j vms( 1:1 ) = '[' vlen = 1 i = 1 if ( unix( 1:1 ) .eq. '/' ) i = 2 j = index( unix( i: ), '/' ) do while ( j .ne. 0 ) vms( vlen+1:vlen+1 ) = '.' call cvt_string_uv( unix( i : i+j-2 ), vms( vlen+2: ), k ) i = i + j j = index( unix( i: ), '/' ) vlen = vlen + k + 1 if ( vlen + reserved .gt. len( vms )) then vlen = len( vms ) - reserved if ( vms( vlen:vlen ) .eq. '.' ) vlen = vlen - 1 do while ( j .ne. 0 ) i = i + j j = index( unix( i: ), '/' ) end do end if end do if ( vlen .eq. 1 ) then vlen = 0 else vlen = vlen + 1 vms( vlen:vlen ) = ']' end if call cvt_file_uv( unix( i: ), vms( vlen+1: ), k ) vlen = vlen + k return end c c this subroutine converts an individual file name from unix format to VMS c subroutine cvt_file_uv( unix, vms, vlen ) parameter mlen1 = 64, mlen2 = 64 c parameter mlen1 = 9, mlen2 = 3 ! for version 3 and before character*(*) unix, vms integer*2 vlen, i, j i = index( unix, '.' ) if ( i .eq. 0 ) i = len( unix ) + 1 call cvt_string_uv( unix( :i-1 ), vms, j ) if ( j .gt. mlen1 ) j = mlen1 vlen = j + 1 if ( vlen .gt. len( vms )) vlen = len( vms ) vms( vlen:vlen ) = '.' if ( i .ge. len( unix )) return call cvt_string_uv( unix( i+1: ), vms( vlen+1: ), j ) if ( j .gt. mlen2 ) j = mlen2 vlen = vlen + j return end c c this subroutine converts a string to characters that can appear in c VMS filenames c c if you're using a version 3 or pervious VMS system, you'll have to c rewrite this to avoid _ and $. c subroutine cvt_string_uv( unix, vms, vlen ) character*(*) unix, vms, c*1 integer*2 vlen, i vms = unix vlen = min( len( unix ), len( vms )) do i = 1, vlen c = vms( i:i ) if ( 'A' .le. c .and. c .le. 'Z' .or. - '0' .le. c .and. c .le. '9' .or. - c .eq. '_' .or. c .eq. '$' ) then continue else if ( 'a' .le. c .and. c .le. 'z' ) then vms( i:i ) = char( ichar( c ) - 32 ) else if ( c .eq. '-' ) then vms( i:i ) = '_' else vms( i:i ) = '$' end if end do return end c c this souroutine converts an octal digit to a 3-character protection mask c subroutine cvt_prot( c, out ) character c*1, out*3, mask( 8 )*3 data mask / '---', '--x', '-w-', '-wx', - 'r--', 'r-x', 'rw-', 'rwx' / out = mask( ichar( c ) - ichar( '0' ) + 1 ) return end $ eod $! $ write sys$output "creating TAPEIO.DCK" $ create TAPEIO.DCK $ deck c c parameters: c blocklen is the size of the units tar works with c saveblocks is the number of blocks into the file saved for a second chance c maxrecl is the maximum length of record a text can have c maxblockfactor is the maximum blocking factor this program can deal with c parameter blocklen = 512, saveblocks = 5, maxrecl = 512, - maxblockfactor = 20 c secondary parameters calculated from those above parameter recblocks = 2 + maxrecl/blocklen, - maxblocks = maxblockfactor + saveblocks + recblocks, - maxlen = blocklen*maxblocks c these are numbers for fortran units to be used for various files parameter inunit = 1, outunit = 2, listunit = 3, nameunit = 4 c c variables: c c i/o control stuff integer*2 channel logical*1 tape_file c this is the buffer records get read into character buffer*( maxlen ), block( maxblocks )*( blocklen ) equivalence ( buffer, block ) c control info for the buffer integer*2 using, using2, curr logical*1 eof common /commonbuf/ buffer common /commonints/ using, using2, curr, eof, tape_file, channel $ eod $! $ write sys$output "creating TAPEIO.FOR" $ create TAPEIO.FOR $ deck c c this routine accesses, checks, and rewinds the specified tape (or file, c if tape_file is true. c subroutine open_tape( name ) include 'tapeio.dck/list' include '($iodef)/nolist' include '($dvidef)/nolist' include '($devdef)/nolist' character*(*) name integer*2 iosb( 2 ), devreq_w( 2 ) integer*4 stat, devreq( 4 ), devchar, sys$assign, sys$qiow, - sys$getdvi equivalence ( devreq, devreq_w ) data devreq_w, devreq( 3 ), devreq( 4 ) - / 4, dvi$_devchar, 0, 0 / if ( tape_file ) then stat = sys$assign( name, channel,, ) if ( .not. stat ) goto 900 devreq( 2 ) = %loc( devchar ) stat = sys$getdvi( , %val( channel ),, devreq, iosb,,, ) if ( .not. stat ) goto 900 stat = iosb( 1 ) if ( .not. stat ) goto 900 if ( .not. btest( devchar, dev$v_avl )) goto 910 if ( .not. btest( devchar, dev$v_for )) goto 920 stat = sys$qiow( , %val( channel ), %val( io$_rewind ), - iosb,,,,,,,, ) if ( .not. stat ) goto 930 stat = iosb( 1 ) if ( .not. stat ) goto 930 else open( inunit, err=950, name=name, - type='old', readonly ) end if return c c fatal errors c 900 type *, 'Error accessing tape, ', name call exit( stat ) 910 type *, 'Tape offline or not available.' call exit 920 type *, 'Tape must be mounted /foreign.' call exit 930 type *, 'Error rewinding tape.' call exit( stat ) 950 type *, 'Error opening input file, ', name call exit end c c this routine makes sure the next block is available, reading it from c tape if necessary. c subroutine next_block include 'tapeio.dck' include '($iodef)/nolist' integer*2 blen, u, i, iosb( 4 ) integer*4 stat, sys$qiow data curr, blen / 0, 0 / eof = .false. curr = curr + 1 if ( curr .le. blen / blocklen ) return if ( using2 .le. 0 ) then u = using else if ( using .le. 0 ) then u = using2 else u = min( using, using2 ) end if if ( u .gt. blen / blocklen ) then type *, 'Internal error. Call the debugger.' call exit else if ( u .gt. 1 ) then buffer( 1 : blen - blocklen*(u-1)) = - buffer( 1+blocklen*(u-1) : blen ) blen = blen - blocklen*(u-1) curr = curr - u + 1 using = using - u + 1 using2 = using2 - u + 1 else if ( u .lt. 1 ) then blen = 0 curr = 1 end if do while ( curr .gt. blen / blocklen ) if ( tape_file ) then stat = sys$qiow( , %val( channel ), %val( io$_readlblk ), - iosb,,, %ref( buffer( blen+1: )), %val( maxlen-blen ) - ,,,, ) if ( .not. stat ) then type *, 'Error reading from tape' call exit( stat ) else if ( .not. iosb( 1 )) then type *, 'Error reading from tape' call exit( iosb( 1 )) else if ( iosb( 2 ) .eq. 0 ) then goto 99 endif blen = blen + iosb( 2 ) else read( inunit, 10, end=99 ) i, buffer( blen+1: ) 10 format( q, a ) blen = blen + i end if if ( blen .gt. maxlen ) then type *, 'Blocking factor too large.' call exit end if end do return 99 curr = curr - 1 eof = .true. return end $ eod $! $ write sys$output "creating TAR.CLD" $ create TAR.CLD $ deck !**************************************TAR************************************** define verb TAR image drc0:[gordon.decus.tar]TAR parameter P1 , label=TAPE , prompt="Tape drive" value (required,type=$infile) qualifier FILE qualifier EXTRACT qualifier BINARY qualifier INQUIRE qualifier SECOND_CHANCE default qualifier NAMES value (default="sys$output:",type=$outfile) qualifier LIST value (default="sys$output:",type=$outfile) qualifier VERBOSE qualifier FLATTEN default $ eod $! $ write sys$output "creating TAR.FOR" $ create TAR.FOR $ deck c c This is tar for VMS, by Gordon Davisson (gordon@uw-june). It is c not based on any liscenced software, and is completely in the c public domain. c c Version 1.0, Gordon Davisson, July 24 1985 c revised by G.D. July 29 1985 to use io$_rewind right and not abuse rms$_eof c revised by G.D. Oct 17 1985 to make sure tape is mounted c program tar parameter bell = char( 7 ), lf = char( 10 ) external cli$_present, cli$_negated, cli$_locpres, cli$_locneg, - cli$_absent, cli$_defaulted, cli$_normal, - cli$_comma, cli$_concat include 'tapeio.dck/list' character fname*100, out*128, pstr*9, prot*3, link*1, tmp*1 integer*2 i, j, start, finish, flen, olen, files, - stuff1, stuff2, stuff3, iosb( 2 ) integer*4 size, blocks, time, stat, - cli$get_value, cli$present, sys$assign, sys$qiow logical*1 listing, naming, extracting, binary, inquiring, - verbose, second_chance, flatten, absent absent( stat ) = ( stat .eq. %loc( cli$_absent ) .or. - stat .eq. %loc( cli$_negated )) c c parse command line c c file -- read from normal file, not a tape stat = cli$present( 'file' ) if ( absent( stat )) then tape_file = .true. else if ( .not. stat ) then goto 900 else tape_file = .false. end if c p1 -- tape drive name stat = cli$get_value( 'tape', fname, flen ) if ( .not. stat ) goto 900 call open_tape( fname( :flen )) c p2 -- files to extract/list/whatever. NOT IMPLEMENTED c files = 0 c stat = cli$get_value( 'match', fname, flen ) c do while ( .not. absent( stat )) c if ( .not. stat ) goto 900 c type *, 'File selector: ', fname( :flen ) c files = files + 1 c stat = cli$get_value( 'match', fname, flen ) c end do c extract -- copy files to disk stat = cli$present( 'extract' ) if ( absent( stat )) then extracting = .false. else if ( .not. stat ) then goto 900 else extracting = .true. end if c binary -- copy to disk in block mode stat = cli$present( 'binary' ) if ( absent( stat )) then binary = .false. else if ( .not. stat ) then goto 900 else binary = .true. end if c inquire -- ask what to do to each file stat = cli$present( 'inquire' ) if ( absent( stat )) then inquiring = .false. else if ( .not. stat ) then goto 900 else inquiring = .true. end if c second_chance -- try to recognize binary files and save them as such stat = cli$present( 'second_chance' ) if ( absent( stat )) then second_chance = .false. else if ( .not. stat ) then goto 900 else second_chance = .true. end if c list -- list files on tape stat = cli$get_value( 'list', fname, flen ) if ( absent( stat )) then listing = .false. else if ( .not. stat ) then goto 900 else open( listunit, err=920, name=fname( :flen ), type='new', - defaultfile='tar.lis', carriagecontrol='list' ) listing = .true. end if c verbose -- make a verbose list stat = cli$present( 'verbose' ) if ( absent( stat )) then verbose = .false. else if ( .not. stat ) then goto 900 else verbose = .true. end if c flatten -- extract all files to the current directory stat = cli$present( 'flatten' ) if ( absent( stat )) then flatten = .false. else if ( .not. stat ) then goto 900 else flatten = .true. end if c names -- make a list of what unix filenames mapped to what VMS filenames stat = cli$get_value( 'names', fname, flen ) if ( absent( stat )) then naming = .false. else if ( .not. stat ) then goto 900 else open( nameunit, err=930, name=fname( :flen ), type='new', - defaultfile='tar.nam', carriagecontrol='list' ) naming = .true. end if c c file loop: executed for each file in the archive c do while ( .true. ) 10 using = 0 using2 = 0 call next_block if ( eof .or. block( curr ) (1:1) .eq. char( 0 )) goto 899 c start parsing out a file entry -- parse the header read( block( curr ), 1001 ) fname, prot, stuff1, stuff2, - size, time, stuff3, link 1001 format( a100, 3x, a3, 2x, 2(o6,2x), 2(o11,1x), o6, 2x, a1 ) blocks = ( size + blocklen - 1 ) / blocklen flen = index( fname, char( 0 )) - 1 if ( flen .lt. 0 ) flen = len( fname ) c add it to the list if ( listing .and. verbose ) then call cvt_prot( prot( 1:1 ), pstr( 1:3 )) call cvt_prot( prot( 2:2 ), pstr( 4:6 )) call cvt_prot( prot( 3:3 ), pstr( 7:9 )) write( listunit, 2001 ) pstr, stuff1, stuff2, size, - time, fname( :flen ) 2001 format( a9, i3, '/', i3, i7, i11, 1x, a ) else if ( listing ) then write( listunit, 2002 ) fname( :flen ) 2002 format( a ) end if c ignore links if ( link .eq. '1' ) goto 10 c skip if not extracting if ( .not. extracting ) goto 40 c figure out what to do with the file if ( inquiring ) then call lib$get_input( tmp, fname( :flen ) // ': [ynbtq]' ) do while ( index( ' yYnNbBtTqQ', tmp ) .eq. 0 ) call lib$get_input( tmp, - bell // fname( :flen ) // ': [ynbtq]' ) end do call str$upcase( tmp, tmp ) if ( tmp .eq. 'Q' ) goto 899 else tmp = 'Y' end if if ( tmp .eq. 'Y' .or. tmp .eq. ' ' ) then tmp = 'T' if ( binary ) tmp = 'B' else if ( tmp .eq. 'N' ) then goto 40 end if c parse file name call cvt_dir_uv( fname( :flen ), out, olen ) if ( flatten ) then i = index( out( :olen ), ']' ) out = out( i+1:olen ) olen = olen - i end if if ( tmp .eq. 'B' ) goto 30 c create a text file 20 open( outunit, name=out( :olen ), type='new', recl=maxrecl, - defaultfile='.', carriagecontrol='list', err=38 ) if ( size .le. 0 ) then close( outunit ) goto 99 end if c copy the file to disk if ( second_chance ) using2 = curr call next_block blocks = blocks - 1 start = 1 do while ( size .gt. 0 ) using = curr finish = index( block( curr ) ( start: ), lf ) do while ( finish .eq. 0 .and. blocks .gt. 0 .and. - curr - using + 1 .lt. recblocks ) call next_block blocks = blocks - 1 if ( eof ) goto 990 finish = index( block( curr ), lf ) end do if ( finish .eq. 0 ) finish = 2 * blocklen + 1 if ( using .eq. curr ) finish = finish + start - 1 i = start + blocklen * (using-1) j = finish + blocklen * (curr-1) start = finish + 1 size = size - j + i - 1 if ( size .lt. 0 ) then j = j + size size = 0 end if if ( using2 .ne. 0 .and. j - i .gt. maxrecl ) then type *, 'Giving ', fname( :flen ), ' a second chance...' blocks = blocks + curr - using2 curr = using2 using = 0 using2 = 0 close( outunit, dispose='delete' ) goto 30 end if write( outunit, 2005, err=39, iostat=stat ) - buffer( i : j-1 ) 2005 format( a ) if ( curr - using2 .ge. saveblocks ) using2 = 0 end do close( outunit ) goto 99 c create a binary file 30 using = 0 using2 = 0 open( outunit, name=out( :olen ), type='new', - recl=blocklen, recordtype='fixed', defaultfile='.', - carriagecontrol='none', err=39 ) do while ( blocks .gt. 0 ) call next_block blocks = blocks - 1 write( outunit, 3001, err=39, iostat=stat ) block( curr ) 3001 format( a ) end do close( outunit ) goto 99 c got an error creating the file: skip it. 38 type *, 'Error creating ', out( :olen ), ' skipping...' goto 40 c got an error writing the file: skip the rest of it. 39 type *, 'Error writing ', out( :olen ), ' skipping...' close( outunit, dispose='delete' ) c skip the file 40 using = 0 using2 = 0 do i = 1, blocks call next_block if ( eof ) goto 990 end do goto 10 c successfully copied file to disk: enter it in the names file 99 if ( naming ) write( nameunit, 2000 ) out( :olen ), - fname( :flen ) 2000 format( a, ' -> ', a ) end do c end of tape: close it and exit! 899 close( inunit ) call exit c c fatal errors c 900 type *, 'Error parsing command line' call exit 920 type *, 'Error opening listing file, ', fname( :flen ) call exit 930 type *, 'Error opening names file, ', fname( :flen ) call exit 990 type *, 'Premature end of tape while reading ', fname( :flen ) call exit end $ eod $! $ write sys$output "creating TAR.HLP" $ create TAR.HLP $ deck 1 TAR Invokes the tape archive reader to read unix-format tapes. Format: TAR tape-name[:] 2 Parameter tape-name[:] Specifies the device name of the tape drive the archive is mounted on. The archive must be mounted foreign. If the /FILE qualifier is specified, this parameter is interpreted as the file name for the archive. 2 Command_Qualifiers /BINARY Specifies that the files extracted should be put into fixed-length-512- byte-record files and that no interpretation should be preformed on the contents. /EXTRACT Specifies that the files in the archive should be copied into the directory, or subdirectories (depending on the /FLATTEN qualifier). /FILE Specifies that, instead of a tape, the archive is contained in a normal file. /FLATTEN (D) Specifies that files extracted from the archive should be put in the default directory even when the files would normally be put in subdirectories. This qualifier is on by default because the program is incapable of creating subdirectories to put the extracted files in, so unless they exist already, /NOFLATTEN in a pure loss. /INQUIRE Tells the program to ask the user what to do with each file it has been told to extract. The program prompts with the filename followed by a list of options. The options are: y - extract the file normally n - skip the file t - extract the file in text (not binary) mode b - extract the file in binary mode q - exit the program The y option is equivalent t or b depending on whether the /BINARY qualifier was given. /LIST /LIST=filename (default = sys$output:) Tells the program to create a list of all of the files on the tape. If the /VERBOSE qualifier is also specified, the list contains more than just the file names. /NAMES /NAMES=filename (default = sys$output:) If files are extracted, the program creates a file giving the names of the files on the tape and the VMS filenames they were mapped into when extracted. /SECOND_CHANCE (D) This specifies that if a file is being extracted in text mode, and a line longer then 512 bytes in encountered sufficiently near the beginning of the file, it should be re-extracted in binary mode. If negated, files with long lines are discarded in text mode. /VERBOSE This specifies that lists should contain more information than just the filename. 2 Bugs Here's a list of some of the more noticable bugs and deficiencies: - It can't write tar tapes. - It can't operate on only some of the files on a tape. - Verbose listings contain the date in seconds since 1970 or