home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1994 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1994.iso
/
netsrcs
/
vms.tar
< prev
next >
Wrap
Internet Message Format
|
1986-09-07
|
50KB
From ramin@rtgvax.UUCP Sat Sep 6 19:18:04 1986
Path: beno!seismo!uwvax!husc6!panda!genrad!decvax!decwrl!amdcad!cae780!leadsv!rtgvax!ramin
From: ramin@rtgvax.UUCP
Newsgroups: net.decus
Subject: Reading TAR from VMS
Message-ID: <91@rtgvax.UUCP>
Date: 6 Sep 86 23:18:04 GMT
Organization: Erewhon Travel
Lines: 1607
Keywords: Summaries, *ACTUAL PROGRAMS* (yow!)
Posted: Sat Sep 6 19:18:04 1986
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 so,
rather than any reasonable format.
- It can't create subdirectories to put files in. (that's why
/FLATTEN is the default)
- Error recovery and reporting could use improvement.
- probably others I can't think of at the moment.
If you discover more bugs, fix them, or just have suggestions, mail
them to Gordon Davisson ({ihnp4|decvax}!uw-beaver!uw-june!gordon,
gordon@uw-june.ARPA, or gordon@uwaphast.BITNET).
$ eod
***************************************************************************
From: lll-lcc!ucdavis!vega!ccrdave (Lord Kahless)
I received this program from somebody, who received this program
from somebody. I don't know if it works because I've been to busy
to test it. Just substitute out the X@X@'s and go for it. Tell
me how it works...
X@X@From: ALCOR::CCRDAN "DAN GOLD" 11-AUG-1986 10:01
X@X@To: CCRDAVE
X@X@Subj:
X@X@
X@X@From ucbvax!sdcsvax.ucsd.edu!gr66@sdcc12 Sun Aug 10 13:41:14 1986
X@X@Received: by deneb.UCDAVIS.EDU (4.12/4.7)
X@X@ id AA28769; Sun, 10 Aug 86 13:40:07 pdt
X@X@From: ucbvax!sdcsvax.ucsd.edu!gr66@sdcc12
X@X@Received: by ucdavis.UCDAVIS.EDU (4.12/4.7)
X@X@ id AA24315; Sun, 10 Aug 86 13:41:25 pdt
X@X@Received: by ucbvax.Berkeley.EDU (5.53/1.14)
X@X@ id AA08804; Sun, 10 Aug 86 13:14:35 PDT
X@X@Received: by sdcsvax.ucsd.edu (5.31/4.42)
X@X@ id AA20134; Sun, 10 Aug 86 13:15:05 PDT hops=0
X@X@Received: by sdcc12.ARPA (5.5/4.41)
X@X@ id AA17718; Sun, 10 Aug 86 13:14:43 PDT
X@X@Date: Sun, 10 Aug 86 13:14:43 PDT
X@X@Message-Id: <8608102014.AA17718@sdcc12.ARPA>
X@X@To: ucdavis!deneb!ccrdan
X@X@Status: R
X@X@
X@X@-----------------------------------------------------------------
X@X@
X@X@Dan Gold:
X@X@
X@X@ Here are the 7 files I received in response to my tar read/write
X@X@program request. This is a DECUS program from Fall, 1985 I think.i
X@X@As TAR.HLP explains, it does not write TAR tapes
X@X@(just reads them) and has a no. of shortcomings. I tried it and
X@X@it works nicely. I plan to improve on it a bit so if you
X@X@ask later I may have more to send you. Send any questions you have
X@X@about bugs to gordon (address in TAR.HLP).
X@X@
X@X@steve piper
X@X@gr66%sdcc12@sdcsvax.ARPA
X@X@
X@X@TAR.COM
X@X@-------
X@X@
X@X@$ fortran tar
X@X@$ fortran cvt
X@X@$ fortran tapeio
X@X@$ link tar,cvt,tapeio
X@X@
X@X@TAR.CLD
X@X@-------
X@X@
X@X@!**************************************TAR**************************************
X@X@define verb TAR
X@X@ image u$dir:TAR
X@X@ parameter P1 , label=TAPE , prompt="Tape drive"
X@X@ value (required,type=$infile)
X@X@ qualifier FILE
X@X@ qualifier EXTRACT
X@X@ qualifier BINARY
X@X@ qualifier INQUIRE
X@X@ qualifier SECOND_CHANCE
X@X@ default
X@X@ qualifier NAMES
X@X@ value (default="sys$output:",type=$outfile)
X@X@ qualifier LIST
X@X@ value (default="sys$output:",type=$outfile)
X@X@ qualifier VERBOSE
X@X@ qualifier FLATTEN
X@X@ default
X@X@
X@X@TAR.FOR
X@X@-------
X@X@
X@X@c
X@X@c This is tar for VMS, by Gordon Davisson (gordon@uw-june). It is
X@X@c not based on any liscenced software, and is completely in the
X@X@c public domain.
X@X@c
X@X@c Version 1.0, Gordon Davisson, July 24 1985
X@X@c revised by G.D. July 29 1985 to use io$_rewind right and not abuse rms$_eof
X@X@c revised by G.D. Oct 17 1985 to make sure tape is mounted
X@X@c
X@X@ program tar
X@X@
X@X@ parameter bell = char( 7 ), lf = char( 10 )
X@X@ external cli$_present, cli$_negated, cli$_locpres, cli$_locneg,
X@X@ - cli$_absent, cli$_defaulted, cli$_normal,
X@X@ - cli$_comma, cli$_concat
X@X@ include 'tapeio.dck/list'
X@X@ character fname*100, out*128, pstr*9, prot*3, link*1, tmp*1
X@X@ integer*2 i, j, start, finish, flen, olen, files,
X@X@ - stuff1, stuff2, stuff3, iosb( 2 )
X@X@ integer*4 size, blocks, time, stat,
X@X@ - cli$get_value, cli$present, sys$assign, sys$qiow
X@X@ logical*1 listing, naming, extracting, binary, inquiring,
X@X@ - verbose, second_chance, flatten, absent
X@X@
X@X@ absent( stat ) = ( stat .eq. %loc( cli$_absent ) .or.
X@X@ - stat .eq. %loc( cli$_negated ))
X@X@c
X@X@c parse command line
X@X@c
X@X@c file -- read from normal file, not a tape
X@X@ stat = cli$present( 'file' )
X@X@ if ( absent( stat )) then
X@X@ tape_file = .true.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ tape_file = .false.
X@X@ end if
X@X@
X@X@c p1 -- tape drive name
X@X@ stat = cli$get_value( 'tape', fname, flen )
X@X@ if ( .not. stat ) goto 900
X@X@ call open_tape( fname( :flen ))
X@X@
X@X@c p2 -- files to extract/list/whatever. NOT IMPLEMENTED
X@X@c files = 0
X@X@c stat = cli$get_value( 'match', fname, flen )
X@X@c do while ( .not. absent( stat ))
X@X@c if ( .not. stat ) goto 900
X@X@c type *, 'File selector: ', fname( :flen )
X@X@c files = files + 1
X@X@c stat = cli$get_value( 'match', fname, flen )
X@X@c end do
X@X@
X@X@c extract -- copy files to disk
X@X@ stat = cli$present( 'extract' )
X@X@ if ( absent( stat )) then
X@X@ extracting = .false.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ extracting = .true.
X@X@ end if
X@X@
X@X@c binary -- copy to disk in block mode
X@X@ stat = cli$present( 'binary' )
X@X@ if ( absent( stat )) then
X@X@ binary = .false.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ binary = .true.
X@X@ end if
X@X@
X@X@c inquire -- ask what to do to each file
X@X@ stat = cli$present( 'inquire' )
X@X@ if ( absent( stat )) then
X@X@ inquiring = .false.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ inquiring = .true.
X@X@ end if
X@X@
X@X@c second_chance -- try to recognize binary files and save them as such
X@X@ stat = cli$present( 'second_chance' )
X@X@ if ( absent( stat )) then
X@X@ second_chance = .false.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ second_chance = .true.
X@X@ end if
X@X@
X@X@c list -- list files on tape
X@X@ stat = cli$get_value( 'list', fname, flen )
X@X@ if ( absent( stat )) then
X@X@ listing = .false.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ open( listunit, err=920, name=fname( :flen ), type='new',
X@X@ - defaultfile='tar.lis', carriagecontrol='list' )
X@X@ listing = .true.
X@X@ end if
X@X@
X@X@c verbose -- make a verbose list
X@X@ stat = cli$present( 'verbose' )
X@X@ if ( absent( stat )) then
X@X@ verbose = .false.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ verbose = .true.
X@X@ end if
X@X@
X@X@c flatten -- extract all files to the current directory
X@X@ stat = cli$present( 'flatten' )
X@X@ if ( absent( stat )) then
X@X@ flatten = .false.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ flatten = .true.
X@X@ end if
X@X@
X@X@c names -- make a list of what unix filenames mapped to what VMS filenames
X@X@ stat = cli$get_value( 'names', fname, flen )
X@X@ if ( absent( stat )) then
X@X@ naming = .false.
X@X@ else if ( .not. stat ) then
X@X@ goto 900
X@X@ else
X@X@ open( nameunit, err=930, name=fname( :flen ), type='new',
X@X@ - defaultfile='tar.nam', carriagecontrol='list' )
X@X@ naming = .true.
X@X@ end if
X@X@
X@X@c
X@X@c file loop: executed for each file in the archive
X@X@c
X@X@ do while ( .true. )
X@X@ 10 using = 0
X@X@ using2 = 0
X@X@ call next_block
X@X@ if ( eof .or. block( curr ) (1:1) .eq. char( 0 )) goto 899
X@X@
X@X@c start parsing out a file entry -- parse the header
X@X@ read( block( curr ), 1001 ) fname, prot, stuff1, stuff2,
X@X@ - size, time, stuff3, link
X@X@ 1001 format( a100, 3x, a3, 2x, 2(o6,2x), 2(o11,1x), o6, 2x, a1 )
X@X@ blocks = ( size + blocklen - 1 ) / blocklen
X@X@ flen = index( fname, char( 0 )) - 1
X@X@ if ( flen .lt. 0 ) flen = len( fname )
X@X@
X@X@c add it to the list
X@X@ if ( listing .and. verbose ) then
X@X@ call cvt_prot( prot( 1:1 ), pstr( 1:3 ))
X@X@ call cvt_prot( prot( 2:2 ), pstr( 4:6 ))
X@X@ call cvt_prot( prot( 3:3 ), pstr( 7:9 ))
X@X@ write( listunit, 2001 ) pstr, stuff1, stuff2, size,
X@X@ - time, fname( :flen )
X@X@ 2001 format( a9, i3, '/', i3, i7, i11, 1x, a )
X@X@ else if ( listing ) then
X@X@ write( listunit, 2002 ) fname( :flen )
X@X@ 2002 format( a )
X@X@ end if
X@X@
X@X@c ignore links
X@X@ if ( link .eq. '1' ) goto 10
X@X@
X@X@c skip if not extracting
X@X@ if ( .not. extracting ) goto 40
X@X@
X@X@c figure out what to do with the file
X@X@ if ( inquiring ) then
X@X@ call lib$get_input( tmp, fname( :flen ) // ': [ynbtq]' )
X@X@ do while ( index( ' yYnNbBtTqQ', tmp ) .eq. 0 )
X@X@ call lib$get_input( tmp,
X@X@ - bell // fname( :flen ) // ': [ynbtq]' )
X@X@ end do
X@X@ call str$upcase( tmp, tmp )
X@X@ if ( tmp .eq. 'Q' ) goto 899
X@X@ else
X@X@ tmp = 'Y'
X@X@ end if
X@X@
X@X@ if ( tmp .eq. 'Y' .or. tmp .eq. ' ' ) then
X@X@ tmp = 'T'
X@X@ if ( binary ) tmp = 'B'
X@X@ else if ( tmp .eq. 'N' ) then
X@X@ goto 40
X@X@ end if
X@X@
X@X@c parse file name
X@X@ call cvt_dir_uv( fname( :flen ), out, olen )
X@X@ if ( flatten ) then
X@X@ i = index( out( :olen ), ']' )
X@X@ out = out( i+1:olen )
X@X@ olen = olen - i
X@X@ end if
X@X@ if ( tmp .eq. 'B' ) goto 30
X@X@
X@X@c create a text file
X@X@ 20 open( outunit, name=out( :olen ), type='new', recl=maxrecl,
X@X@ - defaultfile='.', carriagecontrol='list', err=38 )
X@X@ if ( size .le. 0 ) then
X@X@ close( outunit )
X@X@ goto 99
X@X@ end if
X@X@
X@X@c copy the file to disk
X@X@ if ( second_chance ) using2 = curr
X@X@ call next_block
X@X@ blocks = blocks - 1
X@X@ start = 1
X@X@ do while ( size .gt. 0 )
X@X@ using = curr
X@X@ finish = index( block( curr ) ( start: ), lf )
X@X@ do while ( finish .eq. 0 .and. blocks .gt. 0 .and.
X@X@ - curr - using + 1 .lt. recblocks )
X@X@ call next_block
X@X@ blocks = blocks - 1
X@X@ if ( eof ) goto 990
X@X@ finish = index( block( curr ), lf )
X@X@ end do
X@X@ if ( finish .eq. 0 ) finish = 2 * blocklen + 1
X@X@ if ( using .eq. curr ) finish = finish + start - 1
X@X@ i = start + blocklen * (using-1)
X@X@ j = finish + blocklen * (curr-1)
X@X@ start = finish + 1
X@X@ size = size - j + i - 1
X@X@ if ( size .lt. 0 ) then
X@X@ j = j + size
X@X@ size = 0
X@X@ end if
X@X@ if ( using2 .ne. 0 .and. j - i .gt. maxrecl ) then
X@X@ type *, 'Giving ', fname( :flen ), ' a second chance...'
X@X@ blocks = blocks + curr - using2
X@X@ curr = using2
X@X@ using = 0
X@X@ using2 = 0
X@X@ close( outunit, dispose='delete' )
X@X@ goto 30
X@X@ end if
X@X@ write( outunit, 2005, err=39, iostat=stat )
X@X@ - buffer( i : j-1 )
X@X@2005 format( a )
X@X@ if ( curr - using2 .ge. saveblocks ) using2 = 0
X@X@ end do
X@X@
X@X@ close( outunit )
X@X@ goto 99
X@X@
X@X@c create a binary file
X@X@ 30 using = 0
X@X@ using2 = 0
X@X@ open( outunit, name=out( :olen ), type='new',
X@X@ - recl=blocklen, recordtype='fixed', defaultfile='.',
X@X@ - carriagecontrol='none', err=39 )
X@X@
X@X@ do while ( blocks .gt. 0 )
X@X@ call next_block
X@X@ blocks = blocks - 1
X@X@ write( outunit, 3001, err=39, iostat=stat ) block( curr )
X@X@ 3001 format( a )
X@X@ end do
X@X@ close( outunit )
X@X@ goto 99
X@X@
X@X@c got an error creating the file: skip it.
X@X@ 38 type *, 'Error creating ', out( :olen ), ' skipping...'
X@X@ goto 40
X@X@
X@X@c got an error writing the file: skip the rest of it.
X@X@ 39 type *, 'Error writing ', out( :olen ), ' skipping...'
X@X@ close( outunit, dispose='delete' )
X@X@
X@X@c skip the file
X@X@ 40 using = 0
X@X@ using2 = 0
X@X@ do i = 1, blocks
X@X@ call next_block
X@X@ if ( eof ) goto 990
X@X@ end do
X@X@ goto 10
X@X@
X@X@c successfully copied file to disk: enter it in the names file
X@X@ 99 if ( naming ) write( nameunit, 2000 ) out( :olen ),
X@X@ - fname( :flen )
X@X@ 2000 format( a, ' -> ', a )
X@X@
X@X@ end do
X@X@
X@X@c end of tape: close it and exit!
X@X@ 899 close( inunit )
X@X@ call exit
X@X@
X@X@c
X@X@c fatal errors
X@X@c
X@X@ 900 type *, 'Error parsing command line'
X@X@ call exit
X@X@
X@X@ 920 type *, 'Error opening listing file, ', fname( :flen )
X@X@ call exit
X@X@
X@X@ 930 type *, 'Error opening names file, ', fname( :flen )
X@X@ call exit
X@X@
X@X@ 990 type *, 'Premature end of tape while reading ', fname( :flen )
X@X@ call exit
X@X@
X@X@ end
X@X@
X@X@
X@X@
X@X@TAPEIO.FOR
X@X@----------
X@X@
X@X@c
X@X@c this routine accesses, checks, and rewinds the specified tape (or file,
X@X@c if tape_file is true.
X@X@c
X@X@ subroutine open_tape( name )
X@X@
X@X@ include 'tapeio.dck/list'
X@X@ include '($iodef)/nolist'
X@X@ include '($dvidef)/nolist'
X@X@ include '($devdef)/nolist'
X@X@ character*(*) name
X@X@
X@X@ integer*2 iosb( 2 ), devreq_w( 2 )
X@X@ integer*4 stat, devreq( 4 ), devchar, sys$assign, sys$qiow,
X@X@ - sys$getdvi
X@X@
X@X@ equivalence ( devreq, devreq_w )
X@X@ data devreq_w, devreq( 3 ), devreq( 4 )
X@X@ - / 4, dvi$_devchar, 0, 0 /
X@X@
X@X@ if ( tape_file ) then
X@X@ stat = sys$assign( name, channel,, )
X@X@ if ( .not. stat ) goto 900
X@X@ devreq( 2 ) = %loc( devchar )
X@X@ stat = sys$getdvi( , channel,, devreq, iosb,,, )
X@X@ if ( .not. stat ) goto 900
X@X@ stat = iosb( 1 )
X@X@ if ( .not. stat ) goto 900
X@X@ if ( .not. btest( devchar, dev$v_avl )) goto 910
X@X@ if ( .not. btest( devchar, dev$v_for )) goto 920
X@X@ stat = sys$qiow( , %val( channel ), %val( io$_rewind ),
X@X@ - iosb,,,,,,,, )
X@X@ if ( .not. stat ) goto 930
X@X@ stat = iosb( 1 )
X@X@ if ( .not. stat ) goto 930
X@X@ else
X@X@ open( inunit, err=950, name=name,
X@X@ - type='old', readonly )
X@X@ end if
X@X@
X@X@ return
X@X@
X@X@c
X@X@c fatal errors
X@X@c
X@X@ 900 type *, 'Error accessing tape, ', name( :flen )
X@X@ call exit( stat )
X@X@ 910 type *, 'Tape offline or not available.'
X@X@ call exit
X@X@ 920 type *, 'Tape must be mounted /foreign.'
X@X@ call exit
X@X@ 930 type *, 'Error rewinding tape.'
X@X@ call exit( stat )
X@X@
X@X@ 950 type *, 'Error opening input file, ', name( :flen )
X@X@ call exit
X@X@
X@X@ end
X@X@
X@X@c
X@X@c this routine makes sure the next block is available, reading it from
X@X@c tape if necessary.
X@X@c
X@X@ subroutine next_block
X@X@ include 'tapeio.dck'
X@X@ integer*2 blen, u, i, iosb( 4 )
X@X@ integer*4 stat, sys$qiow
X@X@ data curr, blen / 0, 0 /
X@X@
X@X@ eof = .false.
X@X@ curr = curr + 1
X@X@ if ( curr .le. blen / blocklen ) return
X@X@
X@X@ if ( using2 .le. 0 ) then
X@X@ u = using
X@X@ else if ( using .le. 0 ) then
X@X@ u = using2
X@X@ else
X@X@ u = min( using, using2 )
X@X@ end if
X@X@
X@X@ if ( u .gt. blen / blocklen ) then
X@X@ type *, 'Internal error. Call the debugger.'
X@X@ call exit
X@X@ else if ( u .gt. 1 ) then
X@X@ buffer( 1 : blen - blocklen*(u-1)) =
X@X@ - buffer( 1+blocklen*(u-1) : blen )
X@X@ blen = blen - blocklen*(u-1)
X@X@ curr = curr - u + 1
X@X@ using = using - u + 1
X@X@ using2 = using2 - u + 1
X@X@ else if ( u .lt. 1 ) then
X@X@ blen = 0
X@X@ curr = 1
X@X@ end if
X@X@
X@X@ do while ( curr .gt. blen / blocklen )
X@X@ if ( tape_file ) then
X@X@ stat = sys$qiow( , %val( channel ), %val( io$_readlblk ),
X@X@ - iosb,,, %ref( buffer( blen+1: )), %val( maxlen-blen )
X@X@ - ,,,, )
X@X@ if ( .not. stat ) then
X@X@ type *, 'Error reading from tape'
X@X@ call exit( stat )
X@X@ else if ( .not. iosb( 1 )) then
X@X@ type *, 'Error reading from tape'
X@X@ call exit( iosb( 1 ))
X@X@ else if ( iosb( 2 ) .eq. 0 ) then
X@X@ goto 99
X@X@ endif
X@X@ blen = blen + iosb( 2 )
X@X@ else
X@X@ read( inunit, 10, end=99 ) i, buffer( blen+1: )
X@X@ 10 format( q, a )
X@X@ blen = blen + i
X@X@ end if
X@X@ if ( blen .gt. maxlen ) then
X@X@ type *, 'Blocking factor too large.'
X@X@ call exit
X@X@ end if
X@X@ end do
X@X@ return
X@X@
X@X@99 curr = curr - 1
X@X@ eof = .true.
X@X@ return
X@X@ end
X@X@
X@X@
X@X@
X@X@TAPEIO.DCK
X@X@----------
X@X@c
X@X@c parameters:
X@X@c blocklen is the size of the units tar works with
X@X@c saveblocks is the number of blocks into the file saved for a second chance
X@X@c maxrecl is the maximum length of record a text can have
X@X@c maxblockfactor is the maximum blocking factor this program can deal with
X@X@c
X@X@ parameter blocklen = 512, saveblocks = 5, maxrecl = 512,
X@X@ - maxblockfactor = 20
X@X@
X@X@c secondary parameters calculated from those above
X@X@ parameter recblocks = 2 + maxrecl/blocklen,
X@X@ - maxblocks = maxblockfactor + saveblocks + recblocks,
X@X@ - maxlen = blocklen*maxblocks
X@X@
X@X@c these are numbers for fortran units to be used for various files
X@X@ parameter inunit = 1, outunit = 2, listunit = 3, nameunit = 4
X@X@
X@X@c
X@X@c variables:
X@X@c
X@X@c i/o control stuff
X@X@ integer*2 channel
X@X@ logical*1 tape_file
X@X@
X@X@c this is the buffer records get read into
X@X@ character buffer*( maxlen ), block( maxblocks )*( blocklen )
X@X@ equivalence ( buffer, block )
X@X@
X@X@c control info for the buffer
X@X@ integer*2 using, using2, curr
X@X@ logical*1 eof
X@X@
X@X@
X@X@ common /commonbuf/ buffer
X@X@ common /commonints/ using, using2, curr, eof, tape_file, channel
X@X@
X@X@
X@X@CVT.FOR
X@X@-------
X@X@
X@X@c
X@X@c this subroutine converts a complete filespec (directory+file) name from
X@X@c unix format to VMS
X@X@c
X@X@ subroutine cvt_dir_uv( unix, vms, vlen )
X@X@
X@X@ parameter reserved = 10
X@X@ character*(*) unix, vms
X@X@ integer*2 vlen, i, j
X@X@
X@X@ vms( 1:1 ) = '['
X@X@ vlen = 1
X@X@ i = 1
X@X@ if ( unix( 1:1 ) .eq. '/' ) i = 2
X@X@ j = index( unix( i: ), '/' )
X@X@ do while ( j .ne. 0 )
X@X@ vms( vlen+1:vlen+1 ) = '.'
X@X@ call cvt_string_uv( unix( i : i+j-2 ), vms( vlen+2: ), k )
X@X@ i = i + j
X@X@ j = index( unix( i: ), '/' )
X@X@ vlen = vlen + k + 1
X@X@ if ( vlen + reserved .gt. len( vms )) then
X@X@ vlen = len( vms ) - reserved
X@X@ if ( vms( vlen:vlen ) .eq. '.' ) vlen = vlen - 1
X@X@ do while ( j .ne. 0 )
X@X@ i = i + j
X@X@ j = index( unix( i: ), '/' )
X@X@ end do
X@X@ end if
X@X@ end do
X@X@
X@X@ if ( vlen .eq. 1 ) then
X@X@ vlen = 0
X@X@ else
X@X@ vlen = vlen + 1
X@X@ vms( vlen:vlen ) = ']'
X@X@ end if
X@X@
X@X@ call cvt_file_uv( unix( i: ), vms( vlen+1: ), k )
X@X@ vlen = vlen + k
X@X@ return
X@X@
X@X@ end
X@X@
X@X@c
X@X@c this subroutine converts an individual file name from unix format to VMS
X@X@c
X@X@ subroutine cvt_file_uv( unix, vms, vlen )
X@X@
X@X@ parameter mlen1 = 64, mlen2 = 64
X@X@c parameter mlen1 = 9, mlen2 = 3 ! for version 3 and before
X@X@ character*(*) unix, vms
X@X@ integer*2 vlen, i, j
X@X@
X@X@ i = index( unix, '.' )
X@X@ if ( i .eq. 0 ) i = len( unix ) + 1
X@X@
X@X@ call cvt_string_uv( unix( :i-1 ), vms, j )
X@X@ if ( j .gt. mlen1 ) j = mlen1
X@X@ vlen = j + 1
X@X@ if ( vlen .gt. len( vms )) vlen = len( vms )
X@X@ vms( vlen:vlen ) = '.'
X@X@
X@X@ if ( i .ge. len( unix )) return
X@X@
X@X@ call cvt_string_uv( unix( i+1: ), vms( vlen+1: ), j )
X@X@ if ( j .gt. mlen2 ) j = mlen2
X@X@ vlen = vlen + j
X@X@ return
X@X@
X@X@ end
X@X@
X@X@c
X@X@c this subroutine converts a string to characters that can appear in
X@X@c VMS filenames
X@X@c
X@X@c if you're using a version 3 or pervious VMS system, you'll have to
X@X@c rewrite this to avoid _ and $.
X@X@c
X@X@ subroutine cvt_string_uv( unix, vms, vlen )
X@X@
X@X@ character*(*) unix, vms, c*1
X@X@ integer*2 vlen, i
X@X@
X@X@ vms = unix
X@X@ vlen = min( len( unix ), len( vms ))
X@X@ do i = 1, vlen
X@X@ c = vms( i:i )
X@X@ if ( 'A' .le. c .and. c .le. 'Z' .or.
X@X@ - '0' .le. c .and. c .le. '9' .or.
X@X@ - c .eq. '_' .or. c .eq. '$' ) then
X@X@ continue
X@X@ else if ( 'a' .le. c .and. c .le. 'z' ) then
X@X@ vms( i:i ) = char( ichar( c ) - 32 )
X@X@ else if ( c .eq. '-' ) then
X@X@ vms( i:i ) = '_'
X@X@ else
X@X@ vms( i:i ) = '$'
X@X@ end if
X@X@ end do
X@X@
X@X@ return
X@X@
X@X@ end
X@X@
X@X@c
X@X@c this souroutine converts an octal digit to a 3-character protection mask
X@X@c
X@X@ subroutine cvt_prot( c, out )
X@X@
X@X@ character c*1, out*3, mask( 8 )*3
X@X@ data mask / '---', '--x', '-w-', '-wx',
X@X@ - 'r--', 'r-x', 'rw-', 'rwx' /
X@X@
X@X@ out = mask( ichar( c ) - ichar( '0' ) + 1 )
X@X@ return
X@X@
X@X@ end
X@X@
X@X@
X@X@
X@X@TAR.HLP
X@X@-------
X@X@
X@X@
X@X@1 TAR
X@X@ Invokes the tape archive reader to read unix-format tapes.
X@X@
X@X@ Format:
X@X@
X@X@ TAR tape-name[:]
X@X@2 Parameter
X@X@
X@X@ tape-name[:]
X@X@
X@X@ Specifies the device name of the tape drive the archive is mounted on.
X@X@ The archive must be mounted foreign.
X@X@
X@X@ If the /FILE qualifier is specified, this parameter is interpreted as
X@X@ the file name for the archive.
X@X@2 Command_Qualifiers
X@X@
X@X@/BINARY
X@X@
X@X@ Specifies that the files extracted should be put into fixed-length-512-
X@X@ byte-record files and that no interpretation should be preformed on
X@X@ the contents.
X@X@
X@X@/EXTRACT
X@X@
X@X@ Specifies that the files in the archive should be copied into the
X@X@ directory, or subdirectories (depending on the /FLATTEN qualifier).
X@X@
X@X@/FILE
X@X@
X@X@ Specifies that, instead of a tape, the archive is contained in a normal
X@X@ file.
X@X@
X@X@/FLATTEN (D)
X@X@
X@X@ Specifies that files extracted from the archive should be put in the
X@X@ default directory even when the files would normally be put in
X@X@ subdirectories.
X@X@
X@X@ This qualifier is on by default because the program is incapable of
X@X@ creating subdirectories to put the extracted files in, so unless they
X@X@ exist already, /NOFLATTEN in a pure loss.
X@X@
X@X@/INQUIRE
X@X@
X@X@ Tells the program to ask the user what to do with each file it has been
X@X@ told to extract. The program prompts with the filename followed by a
X@X@ list of options. The options are:
X@X@
X@X@ y - extract the file normally
X@X@ n - skip the file
X@X@ t - extract the file in text (not binary) mode
X@X@ b - extract the file in binary mode
X@X@ q - exit the program
X@X@
X@X@ The y option is equivalent t or b depending on whether the /BINARY
X@X@ qualifier was given.
X@X@
X@X@/LIST
X@X@
X@X@ /LIST=filename (default = sys$output:)
X@X@
X@X@ Tells the program to create a list of all of the files on the tape.
X@X@ If the /VERBOSE qualifier is also specified, the list contains more
X@X@ than just the file names.
X@X@
X@X@/NAMES
X@X@
X@X@ /NAMES=filename (default = sys$output:)
X@X@
X@X@ If files are extracted, the program creates a file giving the names
X@X@ of the files on the tape and the VMS filenames they were mapped into
X@X@ when extracted.
X@X@
X@X@/SECOND_CHANCE (D)
X@X@
X@X@ This specifies that if a file is being extracted in text mode, and
X@X@ a line longer then 512 bytes in encountered sufficiently near the
X@X@ beginning of the file, it should be re-extracted in binary mode.
X@X@
X@X@ If negated, files with long lines are discarded in text mode.
X@X@
X@X@/VERBOSE
X@X@
X@X@ This specifies that lists should contain more information than just
X@X@ the filename.
X@X@
X@X@2 Bugs
X@X@ Here's a list of some of the more noticable bugs and deficiencies:
X@X@ - It can't write tar tapes.
X@X@ - It can't operate on only some of the files on a tape.
X@X@ - Verbose listings contain the date in seconds since 1970 or so,
X@X@ rather than any reasonable format.
X@X@ - It can't create subdirectories to put files in. (that's why
X@X@ /FLATTEN is the default)
X@X@ - Error recovery and reporting could use improvement.
X@X@ - probably others I can't think of at the moment.
X@X@
X@X@ If you discover more bugs, fix them, or just have suggestions, mail
X@X@ them to Gordon Davisson ({ihnp4|decvax}!uw-beaver!uw-june!gordon, or
X@X@ gordon@uw-june.ARPA).
X@X@
X@X@ I'll probably fix some of these eventually, in which case I'll post
X@X@ the new version to net.sources.
X@X@----------------------------------------------------------------
X@X@