mirror of
https://github.com/open-simh/simtools.git
synced 2026-02-14 20:05:57 +00:00
Add RSTSFLX V2.6. This is a file system access utility for RSTS
file systems. It supports reading and writing as well as a number
of other operations, such as octal dump, file system initialize,
and file system check ("clean").
This was originally maintained as a Subversion repository at
svn://akdesign.dyndns.org/flx/branches/V2.6.
as suggested by Timothe Litt on the SIMH mailing list.
This commit is contained in:
31
.gitignore
vendored
31
.gitignore
vendored
@@ -2,3 +2,34 @@
|
|||||||
*~
|
*~
|
||||||
*.bak
|
*.bak
|
||||||
*.o
|
*.o
|
||||||
|
config11/config11
|
||||||
|
converters/asc/asc
|
||||||
|
converters/decsys/decsys
|
||||||
|
converters/dtos8cvt/dtos8cvt
|
||||||
|
converters/gt7cvt/gt7cvt
|
||||||
|
converters/hpconvert/hpconvert
|
||||||
|
converters/indent/indent
|
||||||
|
converters/littcvt/littcvt
|
||||||
|
converters/m8376/m8376
|
||||||
|
converters/mt2tpc/mt2tpc
|
||||||
|
converters/mtcvt23/mtcvtv23
|
||||||
|
converters/mtcvtfix/mtcvtfix
|
||||||
|
converters/mtcvtodd/mtcvtodd
|
||||||
|
converters/noff/noff
|
||||||
|
converters/sfmtcvt/sfmtcvt
|
||||||
|
converters/strrem/strrem
|
||||||
|
converters/strsub/strsub
|
||||||
|
converters/tar2mt/tar2mt
|
||||||
|
converters/tp512cvt/tp512cvt
|
||||||
|
converters/tpc2mt/tpc2mt
|
||||||
|
crossassemblers/hpasm/hpasm
|
||||||
|
crossassemblers/macro1/macro1
|
||||||
|
crossassemblers/macro7/macro7
|
||||||
|
crossassemblers/macro8x/macro8x
|
||||||
|
extracters/ckabstape/ckabstape
|
||||||
|
extracters/mmdir/mmdir
|
||||||
|
extracters/mtdump/mtdump
|
||||||
|
extracters/rawcopy/RawCopy
|
||||||
|
extracters/rstsflx/flx
|
||||||
|
extracters/sdsdump/sdsdump
|
||||||
|
extracters/tpdump/tpdump
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ all:
|
|||||||
cd mmdir && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
cd mmdir && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
||||||
cd mtdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
cd mtdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
||||||
cd rawcopy && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
cd rawcopy && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
||||||
|
cd rstsflx && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
||||||
cd sdsdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
cd sdsdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
||||||
cd tpdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
cd tpdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)"
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ clean:
|
|||||||
cd mmdir && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
cd mmdir && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
||||||
cd mtdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
cd mtdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
||||||
cd rawcopy && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
cd rawcopy && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
||||||
|
cd rstsflx && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
||||||
cd sdsdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
cd sdsdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
||||||
cd tpdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
cd tpdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" clean
|
||||||
|
|
||||||
@@ -29,6 +31,7 @@ install:
|
|||||||
cd mmdir && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
cd mmdir && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
||||||
cd mtdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
cd mtdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
||||||
cd rawcopy && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
cd rawcopy && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
||||||
|
cd rstsflx && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
||||||
cd sdsdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
cd sdsdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
||||||
cd tpdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
cd tpdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" install
|
||||||
|
|
||||||
@@ -37,5 +40,6 @@ uninstall:
|
|||||||
cd mmdir && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
cd mmdir && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
||||||
cd mtdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
cd mtdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
||||||
cd rawcopy && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
cd rawcopy && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
||||||
|
cd rstsflx && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
||||||
cd sdsdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
cd sdsdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
||||||
cd tpdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
cd tpdump && $(MAKE) CFLAGS="$(CFLAGS)" BIN="$(BIN)" INSTALL="$(INSTALL)" CC="$(CC)" uninstall
|
||||||
|
|||||||
7
extracters/rstsflx/BUGS
Normal file
7
extracters/rstsflx/BUGS
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
open bugs:
|
||||||
|
- delete does not honor priv (erase on delete) bit
|
||||||
|
- no readline support in dos
|
||||||
|
- filename completion does host file system completion, which is usually
|
||||||
|
the wrong thing
|
||||||
|
- "put" should pre-extend the output file if in binary copy mode.
|
||||||
|
- need error checking on I/O
|
||||||
68
extracters/rstsflx/HISTORY
Normal file
68
extracters/rstsflx/HISTORY
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
Changes for V2.6:
|
||||||
|
16.04.27 A couple of bugfixes. Changed license to BSD.
|
||||||
|
|
||||||
|
Changes for V2.5:
|
||||||
|
00.08.24 Readline support for DOS now appears to be working,
|
||||||
|
thanks to a newer version of DJGPP. It needs to
|
||||||
|
be checked out a bit more, though, and there
|
||||||
|
still seem to be some oddities.
|
||||||
|
|
||||||
|
Changes for V2.4:
|
||||||
|
00.01.16 Added upper limit check on INIT to hook command so
|
||||||
|
we don't try to hook an INIT that extends into the
|
||||||
|
space needed for the bootstrap. This duplicates
|
||||||
|
a check that exists in hook.sav.
|
||||||
|
00.01.18 Have "clean" display current dir and filename
|
||||||
|
even if not -verbose, but all on a single line.
|
||||||
|
00.01.23 Fix calculation of RE count in fileseek, which was
|
||||||
|
causing disk block out of range errors sometimes.
|
||||||
|
|
||||||
|
Changes for V2.3:
|
||||||
|
00.01.02 Fixed eof calculation for RMS fixed files (-rf switch)
|
||||||
|
Added support for RX50 format 5.25 inch floppy access
|
||||||
|
in Linux. Added code to get size for raw disks
|
||||||
|
under Linux, so the -Size switch is no longer needed.
|
||||||
|
Changed date display format to use 4 digit years, and
|
||||||
|
fix some Y2K bugs. :-(
|
||||||
|
00.01.04 Fixed an elusive malloc bug.
|
||||||
|
00.01.08 Fixed RX50 I/O.
|
||||||
|
|
||||||
|
Changes for V2.2:
|
||||||
|
99.12.02 Bugfix in RMS mode "get" for 32 bit int targets.
|
||||||
|
Use fgets instead of gets in scancmd.
|
||||||
|
|
||||||
|
Changes for V2.0:
|
||||||
|
|
||||||
|
- bugfix in protect command: allow file protection code changes even
|
||||||
|
if P bit is set (as RSTS does)
|
||||||
|
|
||||||
|
- bugfix in rename: disallow rename/replace if new file name == old
|
||||||
|
name (previous code would delete the file and then crash)
|
||||||
|
|
||||||
|
- bugfix in hook command for environments with 32-bit integers
|
||||||
|
|
||||||
|
- fix platform.h so it may work better in Alphas (not tested for lack
|
||||||
|
of hardware)
|
||||||
|
|
||||||
|
- change abort handler to use setjmp/longjmp so failure no longer
|
||||||
|
exits but goes back to command prompt if in prompting mode
|
||||||
|
|
||||||
|
- added -noprotect as synonym for -unprotect
|
||||||
|
|
||||||
|
- bugfix in list -summary: print correct ppns in per-directory summary
|
||||||
|
line.
|
||||||
|
|
||||||
|
- added clean (rebuild)
|
||||||
|
|
||||||
|
- added -odt and -offset to hook command.
|
||||||
|
|
||||||
|
- bugfix in hook command to set clustersize (for disks whose
|
||||||
|
clustersize is not always the same)
|
||||||
|
|
||||||
|
- bugfix in quota update if doing multiple directories since start of
|
||||||
|
program
|
||||||
|
|
||||||
|
- allow [n,*] and [*,*] for gfd and mfd in get and dump commands
|
||||||
|
|
||||||
|
- use GNU readline package, with command line recall including history
|
||||||
|
file.
|
||||||
32
extracters/rstsflx/LICENSE
Normal file
32
extracters/rstsflx/LICENSE
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
License for RSTSFLX
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Copyright (c) 1994-2016, Paul Koning.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
86
extracters/rstsflx/Makefile
Normal file
86
extracters/rstsflx/Makefile
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# *** NOTE ***
|
||||||
|
# This makefile is set up for Linux. It will need some (small) changes to
|
||||||
|
# build under something else. See notes in comments below, marked with ***
|
||||||
|
|
||||||
|
VERSION = 2.5
|
||||||
|
|
||||||
|
# objects
|
||||||
|
OBJS=\
|
||||||
|
rstsflx.o \
|
||||||
|
fip.o \
|
||||||
|
rtime.o \
|
||||||
|
filename.o \
|
||||||
|
doget.o \
|
||||||
|
dolist.o \
|
||||||
|
doalloc.o \
|
||||||
|
docomp.o \
|
||||||
|
dotype.o \
|
||||||
|
doput.o \
|
||||||
|
dodump.o \
|
||||||
|
dodelete.o \
|
||||||
|
dorename.o \
|
||||||
|
dorts.o \
|
||||||
|
doprot.o \
|
||||||
|
dodir.o \
|
||||||
|
doident.o \
|
||||||
|
doinit.o \
|
||||||
|
dohook.o \
|
||||||
|
scancmd.o \
|
||||||
|
doclean.o \
|
||||||
|
fileio.o \
|
||||||
|
diskio.o \
|
||||||
|
absio.o
|
||||||
|
|
||||||
|
# Flags and the like
|
||||||
|
|
||||||
|
# *** change the two lines below as needed for your C compiler.
|
||||||
|
CC ?= gcc
|
||||||
|
OPTIMIZE ?= -O2 -g2
|
||||||
|
LDFLAGS ?= -g2
|
||||||
|
|
||||||
|
DEFINES =
|
||||||
|
CFLAGS = $(OPTIMIZE) $(DEFINES) $(EXTRAFLAGS)
|
||||||
|
|
||||||
|
KITNAME = flx-$(VERSION)
|
||||||
|
DIR = flx
|
||||||
|
|
||||||
|
# Rules
|
||||||
|
|
||||||
|
S = $(OBJS:.o=.c)
|
||||||
|
SRCS = $(S:absio.c=unxabsio.c)
|
||||||
|
|
||||||
|
# *** comment out or delete this first rule if not building on DOS
|
||||||
|
#flx.exe: flx
|
||||||
|
# strip flx
|
||||||
|
# coff2exe -s /djgpp/bin/go32.exe flx
|
||||||
|
|
||||||
|
flx: $(OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -o flx $(OBJS) $(EXTRAOBJS) -lreadline -lncurses $(EXTRAFLAGS)
|
||||||
|
|
||||||
|
# *** the rule below builds absio.o. You need to use as source file
|
||||||
|
# *** an appropriate file; in Unix that's probably unxabsio.c but check
|
||||||
|
# *** the source file to be sure.
|
||||||
|
|
||||||
|
absio.o: unxabsio.c
|
||||||
|
$(CC) -c -o absio.o $(CFLAGS) $<
|
||||||
|
|
||||||
|
# general build rule for all other object files:
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
kit:
|
||||||
|
rm -f *~
|
||||||
|
cd ..; tar cvzf $(KITNAME).tar.gz \
|
||||||
|
$(DIR)/README $(DIR)/COPYING $(DIR)/BUGS $(DIR)/HISTORY \
|
||||||
|
$(DIR)/Makefile* $(DIR)/*.c $(DIR)/*.h \
|
||||||
|
$(DIR)/*.doc $(DIR)/*.pdf $(DIR)/fdprm
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o flx flx.exe flx.dep
|
||||||
|
|
||||||
|
|
||||||
|
flx.dep:
|
||||||
|
gcc -MM $(SRCS) > flx.dep
|
||||||
|
|
||||||
|
# the one below is created by make depend
|
||||||
|
include flx.dep
|
||||||
133
extracters/rstsflx/Makefile.dos
Normal file
133
extracters/rstsflx/Makefile.dos
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# *** NOTE ***
|
||||||
|
# This makefile is set up for DOS (DJGPP). It will need some (small)
|
||||||
|
# changes to build under Unix. See notes in comments below, marked with ***
|
||||||
|
|
||||||
|
# sources
|
||||||
|
# *** note the first one, that's the absolute I/O source module. Change
|
||||||
|
# *** this to the one appropriate for your OS, for example unxabsio.c
|
||||||
|
# *** in the case of Unix.
|
||||||
|
|
||||||
|
SRCS=\
|
||||||
|
djabsio.c \
|
||||||
|
rstsflx.c \
|
||||||
|
fip.c \
|
||||||
|
rtime.c \
|
||||||
|
filename.c \
|
||||||
|
doget.c \
|
||||||
|
dolist.c \
|
||||||
|
doalloc.c \
|
||||||
|
docomp.c \
|
||||||
|
dotype.c \
|
||||||
|
doput.c \
|
||||||
|
dodump.c \
|
||||||
|
dodelete.c \
|
||||||
|
dorename.c \
|
||||||
|
dorts.c \
|
||||||
|
doprot.c \
|
||||||
|
dodir.c \
|
||||||
|
doident.c \
|
||||||
|
doinit.c \
|
||||||
|
dohook.c \
|
||||||
|
scancmd.c \
|
||||||
|
fileio.c \
|
||||||
|
diskio.c
|
||||||
|
|
||||||
|
# prototype header files (none for rstsflx.c and scancmd.c)
|
||||||
|
PROTOS=\
|
||||||
|
rstsflx.h \
|
||||||
|
platform.h \
|
||||||
|
fip.h \
|
||||||
|
rtime.h \
|
||||||
|
filename.h \
|
||||||
|
doget.h \
|
||||||
|
dolist.h \
|
||||||
|
doalloc.h \
|
||||||
|
docomp.h \
|
||||||
|
dotype.h \
|
||||||
|
doput.h \
|
||||||
|
dodump.h \
|
||||||
|
dodelete.h \
|
||||||
|
dorename.h \
|
||||||
|
dorts.h \
|
||||||
|
doprot.h \
|
||||||
|
dodir.h \
|
||||||
|
doident.h \
|
||||||
|
doinit.h \
|
||||||
|
doinit.h \
|
||||||
|
scancmd.h \
|
||||||
|
fileio.h \
|
||||||
|
diskio.h
|
||||||
|
|
||||||
|
# objects
|
||||||
|
OBJS=\
|
||||||
|
rstsflx.o \
|
||||||
|
fip.o \
|
||||||
|
rtime.o \
|
||||||
|
filename.o \
|
||||||
|
doget.o \
|
||||||
|
dolist.o \
|
||||||
|
doalloc.o \
|
||||||
|
docomp.o \
|
||||||
|
dotype.o \
|
||||||
|
doput.o \
|
||||||
|
dodump.o \
|
||||||
|
dodelete.o \
|
||||||
|
dorename.o \
|
||||||
|
dorts.o \
|
||||||
|
doprot.o \
|
||||||
|
dodir.o \
|
||||||
|
doident.o \
|
||||||
|
doinit.o \
|
||||||
|
dohook.o \
|
||||||
|
scancmd.o \
|
||||||
|
doclean.o \
|
||||||
|
fileio.o \
|
||||||
|
diskio.o \
|
||||||
|
absio.o
|
||||||
|
|
||||||
|
# Flags and the like
|
||||||
|
|
||||||
|
# *** change the three lines below as needed for your C compiler.
|
||||||
|
CC= gcc
|
||||||
|
CFLAGS= -O3 -Wall
|
||||||
|
LFLAGS=
|
||||||
|
|
||||||
|
# Rules
|
||||||
|
|
||||||
|
# *** comment out or delete this first rule if not building on DOS
|
||||||
|
#flx.exe: flx
|
||||||
|
# strip flx
|
||||||
|
# coff2exe flx
|
||||||
|
|
||||||
|
flx.exe: $(OBJS)
|
||||||
|
$(CC) -o flx.exe $(OBJS) -lreadline $(LFLAGS)
|
||||||
|
|
||||||
|
# *** the rule below builds absio.o. You need to use as source file
|
||||||
|
# *** an appropriate file; in Unix that's probably unxabsio.c but check
|
||||||
|
# *** the source file to be sure.
|
||||||
|
|
||||||
|
absio.o: djabsio.c
|
||||||
|
$(CC) -c -o absio.o $(CFLAGS) $<
|
||||||
|
|
||||||
|
# general build rule for all other object files:
|
||||||
|
.c.o:
|
||||||
|
$(CC) -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
kit:
|
||||||
|
tar cvzf ../flx.tar.gz flx.exe \
|
||||||
|
Makefile* *.c *.h *.doc *.ps *.txt *.html \
|
||||||
|
README COPYING BUGS HISTORY
|
||||||
|
zip ../flx.zip flx.exe \
|
||||||
|
Makefile* *.c *.h *.doc *.ps *.txt *.html \
|
||||||
|
README COPYING BUGS HISTORY
|
||||||
|
|
||||||
|
clean:
|
||||||
|
del *.o
|
||||||
|
del flx
|
||||||
|
del flx.exe
|
||||||
|
|
||||||
|
depend:
|
||||||
|
gcc -MM *.c > flx.dep
|
||||||
|
|
||||||
|
# the one below is created by make depend
|
||||||
|
include flx.dep
|
||||||
25
extracters/rstsflx/README
Normal file
25
extracters/rstsflx/README
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
README file for FLX 1/11/2000
|
||||||
|
|
||||||
|
What you have here is the set of sources needed to build FLX, a
|
||||||
|
Makefile to do it, and documentation (in PostScript and the source in
|
||||||
|
MS Word format).
|
||||||
|
|
||||||
|
Note on the Makefile: it has been used both with Mips Ultrix "cc" and
|
||||||
|
with gcc (with DOS and with Linux), but "make proto" only works with
|
||||||
|
cc since gcc doesn't support the -protoi switch. Don't worry about
|
||||||
|
that unless you change the sources in a way that affects the procedure
|
||||||
|
prototype declarations. (If you do, edit the .h file of the same name
|
||||||
|
as the .c file to reflect the changed prototypes.)
|
||||||
|
|
||||||
|
As far as I know, everything that's described in flx.ps should work.
|
||||||
|
Let me know if you find problems. (I'll admit that I haven't tested
|
||||||
|
all the cases. For example, RDS0.0 support has had limited testing.
|
||||||
|
And I don't have a "large" disk to test large DCS support!)
|
||||||
|
|
||||||
|
I've had very little feedback on this program. If you use it, even
|
||||||
|
if you have no comments on it, I'd appreciate a short note. And of
|
||||||
|
course if you do have comments, bug reports, or suggestions, then
|
||||||
|
definitely let me know!
|
||||||
|
|
||||||
|
paul koning
|
||||||
|
ni1d@arrl.net
|
||||||
6
extracters/rstsflx/absio.h
Normal file
6
extracters/rstsflx/absio.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
extern void absname (const char *rname);
|
||||||
|
extern int absopen (const char *rname, const char *mode);
|
||||||
|
extern void absseek (long block);
|
||||||
|
extern long absread (long sec, long count, void *buffer);
|
||||||
|
extern long abswrite (long sec, long count, void *buffer);
|
||||||
|
extern void absclose (void);
|
||||||
42
extracters/rstsflx/borabsio.c
Normal file
42
extracters/rstsflx/borabsio.c
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/* absread and abswrite services for use with Borland C implementation
|
||||||
|
*
|
||||||
|
* Paul Koning 95.01.17 Dummy module (no absio in TC++ for Windows)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "absio.h"
|
||||||
|
|
||||||
|
/* this routine is called to scan a supplied container file/device
|
||||||
|
* name. If the name refers to a real disk, then absflag is set
|
||||||
|
* and rsize is set to the device size. Otherwise, no action is taken.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void absname (const char *rname)
|
||||||
|
{
|
||||||
|
if (rname[strlen(rname) - 1] == ':') { /* device name alone */
|
||||||
|
printf ("Absolute I/O not supported\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int absopen (const char *rname, const char *mode)
|
||||||
|
{
|
||||||
|
return (1); /* should never get here... */
|
||||||
|
}
|
||||||
|
|
||||||
|
void absseek (long block) { } /* nothing to do */
|
||||||
|
|
||||||
|
void absclose () { } /* nothing to do */
|
||||||
|
|
||||||
|
long absread (long sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
return (0); /* should never get here... */
|
||||||
|
}
|
||||||
|
|
||||||
|
long abswrite (long sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
return (0); /* should never get here... */
|
||||||
|
}
|
||||||
|
|
||||||
262
extracters/rstsflx/diskio.c
Normal file
262
extracters/rstsflx/diskio.c
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
/* subroutines to do rsts disk (logical block) I/O */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "absio.h"
|
||||||
|
|
||||||
|
#define DEFDEVICE "rsts.dsk"
|
||||||
|
|
||||||
|
#define NOLAST 0
|
||||||
|
#define LASTREAD 1
|
||||||
|
#define LASTWRITE 2
|
||||||
|
|
||||||
|
#ifndef S_ISCHR
|
||||||
|
#define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *name; /* Name of the disk */
|
||||||
|
long tsize; /* Total container size */
|
||||||
|
long rsize; /* Size RSTS uses */
|
||||||
|
int dec166; /* TRUE if disk has factor bad block table */
|
||||||
|
} diskent;
|
||||||
|
|
||||||
|
int dcs; /* device clustersize */
|
||||||
|
long diskblocks; /* device block count */
|
||||||
|
const char *rname; /* file name of disk/container */
|
||||||
|
const char *rssize; /* and associated size */
|
||||||
|
long rsize; /* explicitly supplied size (for real disks) */
|
||||||
|
int absflag; /* doing absolute I/O to real disk if non-zero */
|
||||||
|
FILE *rstsfile; /* rsts disk or container file */
|
||||||
|
|
||||||
|
int lastio; /* what type of I/O, if any, was last done */
|
||||||
|
long nextblk; /* next block after end of last I/O */
|
||||||
|
|
||||||
|
const diskent sizetbl[] = {
|
||||||
|
{ "rx50", 800, 800, FALSE },
|
||||||
|
{ "rf11", 1024, 1024, FALSE },
|
||||||
|
{ "rs03", 1024, 1024, FALSE },
|
||||||
|
{ "rs04", 2048, 2048, FALSE },
|
||||||
|
{ "rk05", 4800, 4800, FALSE },
|
||||||
|
{ "rl01", 10240, 10220, TRUE },
|
||||||
|
{ "rl02", 20480, 20460, TRUE },
|
||||||
|
{ "rk06", 27126, 27104, TRUE },
|
||||||
|
{ "rk07", 53790, 53768, TRUE },
|
||||||
|
{ "rp04", 171798, 171796, FALSE },
|
||||||
|
{ "rp05", 171798, 171796, FALSE },
|
||||||
|
{ "rp06", 340670, 340664, FALSE },
|
||||||
|
{ "rp07", 1008000, 1007950, TRUE },
|
||||||
|
{ "rm02", 131680, 131648, TRUE },
|
||||||
|
{ "rm03", 131680, 131648, TRUE },
|
||||||
|
{ "rm05", 500384, 500352, TRUE },
|
||||||
|
{ "rm80", 251328, 242575, TRUE },
|
||||||
|
{ NULL, 0, 0, 0 }};
|
||||||
|
|
||||||
|
/* getsize takes as input a container file size specifier, which is either
|
||||||
|
* a decimal string or a disk type name, and returns the corresponding
|
||||||
|
* size. In the case of disk names, it returns both the size as RSTS
|
||||||
|
* knows it, and the full hardware-defined size. In addition, it returns
|
||||||
|
* a flag indicating whether that type has a bad block table.
|
||||||
|
* In the case of a numeric size, it looks for a match in the table
|
||||||
|
* (against either RSTS size or "full" size) and returns what the
|
||||||
|
* table entry specifies. If no match is found, it returns the
|
||||||
|
* specified value for both and the dec166 flag is false.
|
||||||
|
* If the size specifier is invalid, the RSTS size is returned as zero
|
||||||
|
* and the other two return values are undefined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void getsize (const char *name, long *tsize, long *rsize, int *dec166)
|
||||||
|
{
|
||||||
|
const diskent *d;
|
||||||
|
char *n, *n2, *pp;
|
||||||
|
|
||||||
|
if (isdigit (*name)) /* numeric size given */
|
||||||
|
{
|
||||||
|
*rsize = strtoul (name, &pp, 10); /* scan size */
|
||||||
|
if (*pp != '\0') *rsize = 0;
|
||||||
|
*tsize = *rsize;
|
||||||
|
*dec166 = FALSE;
|
||||||
|
for (d = sizetbl; d->name != NULL; d++)
|
||||||
|
if (d->rsize == *rsize || d->tsize == *rsize)
|
||||||
|
{
|
||||||
|
*tsize = d->tsize;
|
||||||
|
*rsize = d->rsize;
|
||||||
|
*dec166 = d->dec166;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((n = (char *) malloc (strlen (name) + 1)) == NULL) rabort(NOMEM);
|
||||||
|
strcpy (n, name);
|
||||||
|
for (n2 = n; *n2; n2++) *n2 = tolower (*n2);
|
||||||
|
for (d = sizetbl; d->name != NULL; d++)
|
||||||
|
if (strcmp (d->name, n) == 0) break;
|
||||||
|
free (n);
|
||||||
|
*tsize = d->tsize;
|
||||||
|
*rsize = d->rsize;
|
||||||
|
*dec166 = d->dec166;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* adjsize takes as input a container file size. it returns the
|
||||||
|
* corresponding RSTS size, based on a match against a table of
|
||||||
|
* known disk sizes. if it finds a match, it returns the RSTS
|
||||||
|
* size given in the table; otherwise it returns the value that
|
||||||
|
* was passed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long adjsize (long tsize)
|
||||||
|
{
|
||||||
|
const diskent *d;
|
||||||
|
|
||||||
|
for (d = sizetbl; d->name != NULL; d++)
|
||||||
|
if (d->tsize == tsize)
|
||||||
|
return d->rsize;
|
||||||
|
return tsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setrname ()
|
||||||
|
{
|
||||||
|
long t1;
|
||||||
|
int t2;
|
||||||
|
|
||||||
|
if ((rname = sw.rstsdevice) == NULL)
|
||||||
|
if ((rname = defdevice) == NULL)
|
||||||
|
if ((rname = getenv ("RSTSDISK")) == NULL)
|
||||||
|
rname = DEFDEVICE;
|
||||||
|
if ((rssize = sw.disksize) == NULL)
|
||||||
|
if ((rssize = defsize) == NULL)
|
||||||
|
if ((rssize = getenv ("RSTSDISKSIZE")) == NULL)
|
||||||
|
rssize = NULL;
|
||||||
|
rsize = 0;
|
||||||
|
absflag = FALSE;
|
||||||
|
if (rssize != NULL) {
|
||||||
|
getsize (rssize, &t1, &rsize, &t2); /* scan size */
|
||||||
|
if (rsize == 0) {
|
||||||
|
printf ("Invalid device size %s\n", rssize);
|
||||||
|
return; /* and quit */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
absname (rname); /* see if name is special */
|
||||||
|
if (absflag && rsize == 0) {
|
||||||
|
printf ("Disk size must be specified explicitly for disk %s\n",
|
||||||
|
rname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ropen (const char *mode)
|
||||||
|
{
|
||||||
|
long d;
|
||||||
|
struct stat sbuf;
|
||||||
|
|
||||||
|
fiblk = -1; /* indicate no valid FIBUF */
|
||||||
|
lastio = NOLAST; /* and no previous I/O */
|
||||||
|
womsat = FALSE; /* SATT is clean */
|
||||||
|
setrname ();
|
||||||
|
if (absflag) { /* open real disk */
|
||||||
|
if (absopen (rname, mode)) {
|
||||||
|
printf ("Error opening RSTS device %s\n", rname);
|
||||||
|
perror (progname); /* report any details */
|
||||||
|
rabort (NOMSG);
|
||||||
|
}
|
||||||
|
diskblocks = rsize; /* set block count */
|
||||||
|
} else { /* not absolute disk */
|
||||||
|
if ((rstsfile = fopen (rname, mode)) == NULL) {
|
||||||
|
printf ("Error opening RSTS device %s\n", rname);
|
||||||
|
perror (progname); /* report any details */
|
||||||
|
rabort (NOMSG);
|
||||||
|
}
|
||||||
|
if (fstat (fileno(rstsfile), &sbuf)) { /* get info about disk/file */
|
||||||
|
printf ("Can't stat RSTS device %s", rname);
|
||||||
|
perror (progname);
|
||||||
|
fclose (rstsfile); /* close it */
|
||||||
|
rabort (NOMSG);
|
||||||
|
}
|
||||||
|
diskblocks = UP(sbuf.st_size,BLKSIZE) / BLKSIZE;
|
||||||
|
if (diskblocks == 0) {
|
||||||
|
if (!S_ISCHR(sbuf.st_mode) &&
|
||||||
|
!S_ISBLK(sbuf.st_mode))
|
||||||
|
{
|
||||||
|
printf ("Null RSTS container file %s\n", rname);
|
||||||
|
fclose (rstsfile);
|
||||||
|
rabort (NOMSG);
|
||||||
|
}
|
||||||
|
if (rsize == 0) {
|
||||||
|
printf ("Size not specified for RSTS disk %s\n", rname);
|
||||||
|
fclose (rstsfile);
|
||||||
|
rabort (NOMSG);
|
||||||
|
}
|
||||||
|
diskblocks = rsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diskblocks = adjsize (diskblocks); /* adjust for bad block tbl */
|
||||||
|
d = (diskblocks - 1) >> 16; /* high order bits of last LBN */
|
||||||
|
dcs = 1; /* compute DCS */
|
||||||
|
while (d) {
|
||||||
|
d >>= 1;
|
||||||
|
dcs <<= 1;
|
||||||
|
}
|
||||||
|
if (dcs > 64) rabort(BADDCS); /* Sorry, disk too big! */
|
||||||
|
}
|
||||||
|
|
||||||
|
void rseek (long block)
|
||||||
|
{
|
||||||
|
if (block >= diskblocks) rabort(BADBLK);
|
||||||
|
if (absflag) absseek (block);
|
||||||
|
else fseek (rstsfile, block * BLKSIZE, SEEK_SET);
|
||||||
|
if (sw.debug != NULL)
|
||||||
|
printf ("seek to: %ld\n", block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rread (long block, long size, void *buffer)
|
||||||
|
{
|
||||||
|
long iosize;
|
||||||
|
|
||||||
|
if (lastio != LASTREAD || nextblk != block) {
|
||||||
|
rseek (block);
|
||||||
|
lastio = LASTREAD;
|
||||||
|
}
|
||||||
|
if (absflag) {
|
||||||
|
if (absread (block, size, buffer))
|
||||||
|
iosize = 0;
|
||||||
|
else iosize = size;
|
||||||
|
}
|
||||||
|
else iosize = fread (buffer, 1, size, rstsfile);
|
||||||
|
if (sw.debug != NULL)
|
||||||
|
printf ("size requested: %ld, read: %ld\n", size, iosize);
|
||||||
|
if (iosize != size) rabort(DISKIO);
|
||||||
|
nextblk = block + size / BLKSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rwrite (long block, long size, void *buffer)
|
||||||
|
{
|
||||||
|
long iosize;
|
||||||
|
|
||||||
|
if (lastio != LASTWRITE || nextblk != block) {
|
||||||
|
rseek (block);
|
||||||
|
lastio = LASTWRITE;
|
||||||
|
}
|
||||||
|
if (absflag) {
|
||||||
|
if (abswrite (block, size, buffer))
|
||||||
|
iosize = 0;
|
||||||
|
else iosize = size;
|
||||||
|
}
|
||||||
|
else iosize = fwrite (buffer, 1, size, rstsfile);
|
||||||
|
if (iosize != size) rabort(DISKIO);
|
||||||
|
nextblk = block + size / BLKSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rclose ()
|
||||||
|
{
|
||||||
|
if (absflag) absclose ();
|
||||||
|
else fclose (rstsfile);
|
||||||
|
}
|
||||||
8
extracters/rstsflx/diskio.h
Normal file
8
extracters/rstsflx/diskio.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
extern void getsize (const char *name, long *tsize, long *rsize, int *dec166);
|
||||||
|
extern long adjsize (long size);
|
||||||
|
extern void setrname(void);
|
||||||
|
extern void ropen(const char * mode);
|
||||||
|
extern void rseek(long block);
|
||||||
|
extern void rread(long block , long size , void * buffer);
|
||||||
|
extern void rwrite(long block , long size , void * buffer);
|
||||||
|
extern void rclose(void);
|
||||||
304
extracters/rstsflx/djabsio.c
Normal file
304
extracters/rstsflx/djabsio.c
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
/* absread and abswrite services for use with DJGPP GNU C implementation
|
||||||
|
*
|
||||||
|
* Paul Koning 94.10.16
|
||||||
|
* 94.11.18 added bios i/o
|
||||||
|
* 94.11.21 dos i/o for hard disk, bios i/o for floppy
|
||||||
|
* 94.12.19 add retry for bios I/O
|
||||||
|
* 95.01.05 update for generalized abs i/o in flx
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bios.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <go32.h>
|
||||||
|
#include <dpmi.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "absio.h"
|
||||||
|
|
||||||
|
#define tb _go32_info_block.linear_address_of_transfer_buffer
|
||||||
|
|
||||||
|
#define BIOSBUF (_go32_info_block.size_of_transfer_buffer)
|
||||||
|
/* size of djgpp bios disk I/O buffer */
|
||||||
|
#define BIOSMAX (18 * BLKSIZE) /* max size in biosdisk() call */
|
||||||
|
#define BIOSRESET 0 /* error reset */
|
||||||
|
#define BIOSREAD 2 /* bios disk read function code */
|
||||||
|
#define BIOSWRITE 3 /* bios disk write function code */
|
||||||
|
#define BIOSTRIES 4 /* retry count */
|
||||||
|
#define ABSREAD 0x25 /* abs read int code */
|
||||||
|
#define ABSWRITE 0x26 /* abs write int code */
|
||||||
|
#define BIOS_DATA_SEG 0x0040 /* BIOS data segment number */
|
||||||
|
#define BIOS_DSK_STATE 0x0090 /* offset to drive 0 media state */
|
||||||
|
#define DISK_STATE(d) ((BIOS_DATA_SEG << 4) + BIOS_DSK_STATE + ((d) - 1))
|
||||||
|
|
||||||
|
#define BIOS_DSK_360K 0x74 /* 360kb media established */
|
||||||
|
#define BIOS_DSK_RX50 0x54 /* RX50 media established in drive */
|
||||||
|
/* (same as 360kb except single steps */
|
||||||
|
/* for 96 tpi media) */
|
||||||
|
|
||||||
|
static int secsize = 0;
|
||||||
|
static int param_segment = 0;
|
||||||
|
static unsigned short int dosparam[5];
|
||||||
|
static int rxflag = 0; /* set if accessing 5.25 inch floppy */
|
||||||
|
static int gdrive = -1; /* drive to which geometry data applies */
|
||||||
|
static int drive; /* disk unit number currently open */
|
||||||
|
static int sectors, heads, cylinders, drives;
|
||||||
|
static _go32_dpmi_seginfo param_info;
|
||||||
|
|
||||||
|
/* The param_buffer is used to hold the dos abs disk I/O parameter block
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void free_param_buffer()
|
||||||
|
{
|
||||||
|
_go32_dpmi_free_dos_memory(¶m_info);
|
||||||
|
param_segment = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alloc_param_buffer()
|
||||||
|
{
|
||||||
|
if (param_segment) return;
|
||||||
|
param_info.size = UP(sizeof(param_info),16) / 16;
|
||||||
|
if (_go32_dpmi_allocate_dos_memory(¶m_info)) {
|
||||||
|
param_segment = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
param_segment = param_info.rm_segment;
|
||||||
|
atexit(free_param_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert dos style drive number to bios style number */
|
||||||
|
|
||||||
|
static int biosdrive (int drive)
|
||||||
|
{
|
||||||
|
if (drive < 3) return (drive - 1);
|
||||||
|
else return ((drive - 3) + 0x80); /* need to do partitions */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do bios I/O with retries */
|
||||||
|
|
||||||
|
static int biosdiskr (int func, int drive, int track, int cyl,
|
||||||
|
int sec, int count, void *buffer, int dparam)
|
||||||
|
{
|
||||||
|
int tries, status;
|
||||||
|
|
||||||
|
for (tries = 0; tries < BIOSTRIES; tries++) {
|
||||||
|
if (dparam) dosmemput (&dparam, 1, DISK_STATE(drive));
|
||||||
|
status = biosdisk (func, biosdrive (drive), track, cyl,
|
||||||
|
sec, count, buffer);
|
||||||
|
if (status == 0) break;
|
||||||
|
|
||||||
|
/* strictly speaking one should do error classification
|
||||||
|
* at this point...
|
||||||
|
*/
|
||||||
|
biosdisk (BIOSRESET, biosdrive (drive), 0, 0, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
return (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getgeom (int drive)
|
||||||
|
{
|
||||||
|
_go32_dpmi_registers r;
|
||||||
|
|
||||||
|
gdrive = drive;
|
||||||
|
memset(&r, 0, sizeof(r));
|
||||||
|
r.h.ah = 8;
|
||||||
|
r.h.dl = biosdrive (drive);
|
||||||
|
_go32_dpmi_simulate_int(0x13, &r);
|
||||||
|
heads = r.h.dh + 1;
|
||||||
|
drives = r.h.dl;
|
||||||
|
cylinders = r.h.ch + ((r.h.cl >> 6) << 8) + 1;
|
||||||
|
sectors = r.h.cl & 0x3f;
|
||||||
|
if (drive < 3 && (r.h.bl & 0x0f) == 2) /* floppy && drive = 1.2MB */
|
||||||
|
rxflag = 1;
|
||||||
|
else rxflag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert block number to cylinder, head, sector for RT11-RX50.
|
||||||
|
* This is different for RT11 than for Rainbow DOS:
|
||||||
|
* For DOS, for cylinders 2 through 79, the sectors are interleaved 2:1.
|
||||||
|
* (DOS capability is not supported in this RT11 version).
|
||||||
|
* For RT11, all sectors are interleaved 2:1, and each subsequent
|
||||||
|
* track has the first logical block offset by 2 more sectors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void makechs_rx50 (int block, int *trk, int *sec)
|
||||||
|
{
|
||||||
|
int t, s;
|
||||||
|
|
||||||
|
t = block / 10;
|
||||||
|
s = block % 10 + 1;
|
||||||
|
if (s < 6) s = (s - 1) * 2 + 1;
|
||||||
|
else s = (s - 5) * 2;
|
||||||
|
s += t * 2;
|
||||||
|
while (s > 10) s -= 10;
|
||||||
|
t++;
|
||||||
|
if (t == 80) t = 0; /* wrap around last 10 blocks */
|
||||||
|
*trk = t;
|
||||||
|
*sec = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do single block disk I/O to DEC RX50 floppy */
|
||||||
|
static int rx50io (int func, int drive, int dsksec, void *buffer)
|
||||||
|
{
|
||||||
|
byte oldstate;
|
||||||
|
int cyl, sec;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
alloc_param_buffer();
|
||||||
|
|
||||||
|
/* save old state and set up for RX50 I/O */
|
||||||
|
dosmemget (DISK_STATE(drive), 1, &oldstate);
|
||||||
|
makechs_rx50 (dsksec, &cyl, &sec);
|
||||||
|
status = biosdiskr (func, drive, 0, cyl, sec, 1, buffer, BIOS_DSK_RX50);
|
||||||
|
|
||||||
|
/* restore BIOS state as it was on entry */
|
||||||
|
dosmemput (&oldstate, 1, DISK_STATE(drive));
|
||||||
|
return (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do bios disk I/O call
|
||||||
|
* if this is a 5.25" floppy, we do the required magic to read it as
|
||||||
|
* a DEC RX50 format floppy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static long biosio (int func, int drive, long dsksec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
long track, sec, cyl;
|
||||||
|
long tcount, status;
|
||||||
|
|
||||||
|
if (drive != gdrive) getgeom (drive);
|
||||||
|
while (count) {
|
||||||
|
if (rxflag) {
|
||||||
|
tcount = BLKSIZE;
|
||||||
|
status = rx50io (func, drive, dsksec, buffer);
|
||||||
|
} else {
|
||||||
|
tcount = count;
|
||||||
|
if (tcount > BIOSMAX) tcount = BIOSMAX;
|
||||||
|
sec = dsksec % sectors;
|
||||||
|
if ((sectors - sec) * BLKSIZE < tcount)
|
||||||
|
tcount = (sectors - sec) * BLKSIZE;
|
||||||
|
sec++; /* weird 1-based numbering */
|
||||||
|
track = (dsksec / sectors) % heads;
|
||||||
|
cyl = dsksec / (sectors * heads);
|
||||||
|
status = biosdiskr (func, drive, track, cyl,
|
||||||
|
sec, tcount / BLKSIZE, buffer, 0);
|
||||||
|
}
|
||||||
|
if (status) return (status);
|
||||||
|
count -= tcount;
|
||||||
|
buffer += tcount;
|
||||||
|
dsksec += (tcount / BLKSIZE);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do absolute dos disk read/write
|
||||||
|
* arguments:
|
||||||
|
* function code (0x25 = read, 0x26 = write)
|
||||||
|
* drive number (1 = a:, etc)
|
||||||
|
* starting sector number
|
||||||
|
* byte count (must be multiple of sector size)
|
||||||
|
* buffer pointer
|
||||||
|
*/
|
||||||
|
|
||||||
|
static long dosio (int func, int drive, int sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
long tcount;
|
||||||
|
_go32_dpmi_registers r;
|
||||||
|
|
||||||
|
while (count) {
|
||||||
|
tcount = count;
|
||||||
|
if (tcount > BIOSBUF) tcount = BIOSBUF;
|
||||||
|
alloc_param_buffer();
|
||||||
|
dosparam[0] = sec & 0xffff;
|
||||||
|
dosparam[1] = sec >> 16;
|
||||||
|
dosparam[2] = (tcount / secsize) & 0xffff;
|
||||||
|
dosparam[3] = (unsigned int) tb & 15;
|
||||||
|
dosparam[4] = (unsigned int) tb >> 4;
|
||||||
|
dosmemput(dosparam, sizeof(dosparam), param_segment << 4);
|
||||||
|
if (func == ABSWRITE)
|
||||||
|
dosmemput(buffer, tcount, tb);
|
||||||
|
memset(&r, 0, sizeof(r));
|
||||||
|
r.h.al = drive - 1; /* 0-based numbering here */
|
||||||
|
r.x.ds = param_segment;
|
||||||
|
r.x.bx = 0;
|
||||||
|
r.x.cx = -1;
|
||||||
|
_go32_dpmi_simulate_int(func, &r);
|
||||||
|
if (func == ABSREAD)
|
||||||
|
dosmemget(tb, tcount, buffer);
|
||||||
|
if (r.x.flags & 1)
|
||||||
|
return (r.h.al);
|
||||||
|
count -= tcount;
|
||||||
|
buffer += tcount;
|
||||||
|
sec += (tcount / secsize);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return size of specified disk, in blocks. Saves sector size in a local
|
||||||
|
* static variable as a side effect. A flag is set if the disk is a
|
||||||
|
* 5.25 inch floppy.
|
||||||
|
* Note: this must be called before any abs I/O is done.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int disksize (int drive)
|
||||||
|
{
|
||||||
|
_go32_dpmi_registers r;
|
||||||
|
|
||||||
|
if (drive >= 3) { /* hard disk */
|
||||||
|
memset(&r, 0, sizeof(r));
|
||||||
|
r.h.ah = 0x1c;
|
||||||
|
r.h.dl = drive;
|
||||||
|
_go32_dpmi_simulate_int(0x21, &r);
|
||||||
|
secsize = r.x.cx;
|
||||||
|
return (r.h.al * r.x.dx * secsize / BLKSIZE);
|
||||||
|
} else {
|
||||||
|
getgeom (drive);
|
||||||
|
secsize = 512;
|
||||||
|
return (cylinders * heads * sectors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this routine is called to scan a supplied container file/device
|
||||||
|
* name. If the name refers to a real disk, then absflag is set
|
||||||
|
* and rsize is set to the device size. Otherwise, no action is taken.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void absname (const char *rname)
|
||||||
|
{
|
||||||
|
if (rname[strlen(rname) - 1] == ':') { /* device name alone */
|
||||||
|
absflag = TRUE;
|
||||||
|
drive = tolower (rname[0]) - 'a' + 1; /* set drive number */
|
||||||
|
rsize = disksize (drive);
|
||||||
|
if (sw.debug != NULL)
|
||||||
|
printf ("disk size for drive %d is %ld\n", drive, rsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int absopen (const char *rname, const char *mode)
|
||||||
|
{
|
||||||
|
return (0); /* always ok, nothing to do */
|
||||||
|
}
|
||||||
|
|
||||||
|
void absseek (long block) { } /* nothing to do */
|
||||||
|
|
||||||
|
void absclose () { } /* nothing to do */
|
||||||
|
|
||||||
|
long absread (long sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
if (drive >= 3) /* hard disk */
|
||||||
|
return (dosio (ABSREAD, drive, sec, count, buffer));
|
||||||
|
else
|
||||||
|
return (biosio (BIOSREAD, drive, sec, count, buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
long abswrite (long sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
if (drive >= 3) /* hard disk */
|
||||||
|
return (dosio (ABSWRITE, drive, sec, count, buffer));
|
||||||
|
else
|
||||||
|
return (biosio (BIOSWRITE, drive, sec, count, buffer));
|
||||||
|
}
|
||||||
|
|
||||||
58
extracters/rstsflx/doalloc.c
Normal file
58
extracters/rstsflx/doalloc.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* handler for the "allocation" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "doalloc.h"
|
||||||
|
#include "fip.h"
|
||||||
|
|
||||||
|
void doalloc (int argc, char **argv) /* show allocated clusters */
|
||||||
|
{
|
||||||
|
byte *s;
|
||||||
|
int bit, szb;
|
||||||
|
long first, used, unused, biggest, size;
|
||||||
|
long n;
|
||||||
|
|
||||||
|
rmount (); /* mount the disk R/O */
|
||||||
|
findsat (); /* look up satt.sys */
|
||||||
|
s = sattbufp;
|
||||||
|
szb = (diskblocks - dcs) / pcs; /* satt bits actually used */
|
||||||
|
bit = 1;
|
||||||
|
n = 0; /* start looking at PCN = 0 */
|
||||||
|
used = unused = biggest = 0; /* nothing used, nor unused */
|
||||||
|
if (sw.bswitch == NULL) printf ("\nFree pack cluster number ranges:\n");
|
||||||
|
for (;;) {
|
||||||
|
for ( ; n < szb; n++) {
|
||||||
|
if (bit > 0x80) {
|
||||||
|
bit = 1;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if ((*s & bit) == 0) break;
|
||||||
|
used++; /* count allocated clusters */
|
||||||
|
bit <<= 1;
|
||||||
|
}
|
||||||
|
if (n == szb) break;
|
||||||
|
first = n;
|
||||||
|
for ( ; n < szb; n++) {
|
||||||
|
if (bit > 0x80) {
|
||||||
|
bit = 1;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if (*s & bit) break;
|
||||||
|
unused++; /* count free clusters */
|
||||||
|
bit <<= 1;
|
||||||
|
}
|
||||||
|
size = (n - first) * pcs;
|
||||||
|
if (size > biggest) biggest = size;
|
||||||
|
if (sw.bswitch == NULL) {
|
||||||
|
printf ("%6ld - %-6ld (%ld blocks)\n", first, n - 1, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf ("Blocks used: %ld, free: %ld, max contiguous free: %ld\n",
|
||||||
|
used * pcs, unused * pcs, biggest);
|
||||||
|
free (sattbufp); /* release the satt memory copy */
|
||||||
|
rumount (); /* done with the disk */
|
||||||
|
}
|
||||||
|
|
||||||
1
extracters/rstsflx/doalloc.h
Normal file
1
extracters/rstsflx/doalloc.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern void doalloc(int argc , char ** argv);
|
||||||
1794
extracters/rstsflx/doclean.c
Normal file
1794
extracters/rstsflx/doclean.c
Normal file
File diff suppressed because it is too large
Load Diff
1
extracters/rstsflx/doclean.h
Normal file
1
extracters/rstsflx/doclean.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern void doclean (int argc , char ** argv);
|
||||||
62
extracters/rstsflx/docomp.c
Normal file
62
extracters/rstsflx/docomp.c
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/* handler for the "compress" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "docomp.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "fip.h"
|
||||||
|
|
||||||
|
void docomp (int argc, char **argv) /* zero unused clusters */
|
||||||
|
{
|
||||||
|
byte *s;
|
||||||
|
int bit, szb;
|
||||||
|
long first, size, iosize;
|
||||||
|
long n;
|
||||||
|
|
||||||
|
rmountrw (); /* mount the disk R/W */
|
||||||
|
memset (iobuf, 0, iobufsize); /* clear out I/O buffer */
|
||||||
|
s = sattbufp;
|
||||||
|
szb = (diskblocks - dcs) / pcs; /* satt bits actually used */
|
||||||
|
bit = 1;
|
||||||
|
n = 0; /* start looking at PCN = 0 */
|
||||||
|
for (;;) {
|
||||||
|
for ( ; n < szb; n++) { /* scan past allocated clusters */
|
||||||
|
if (bit > 0x80) {
|
||||||
|
bit = 1;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if ((*s & bit) == 0) break;
|
||||||
|
bit <<= 1;
|
||||||
|
}
|
||||||
|
if (n == szb) break;
|
||||||
|
first = n;
|
||||||
|
for ( ; n < szb; n++) { /* find length of free area */
|
||||||
|
if (bit > 0x80) {
|
||||||
|
bit = 1;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if (*s & bit) break;
|
||||||
|
bit <<= 1;
|
||||||
|
}
|
||||||
|
size = (n - first) * pcs;
|
||||||
|
first = pcntolbn(first); /* get starting lbn */
|
||||||
|
if (sw.verbose != NULL) {
|
||||||
|
printf ("clearing %ld..%ld\015", first, first + size - 1);
|
||||||
|
fflush (stdout);
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
iosize = size * BLKSIZE;
|
||||||
|
if (iosize > iobufsize) iosize = iobufsize;
|
||||||
|
rwrite (first, iosize, iobuf);
|
||||||
|
size -= iobufsize / BLKSIZE;
|
||||||
|
if (size <= 0) break;
|
||||||
|
first += iobufsize / BLKSIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.verbose != NULL) printf ("\n");
|
||||||
|
rumountrw (); /* done with the disk */
|
||||||
|
}
|
||||||
|
|
||||||
1
extracters/rstsflx/docomp.h
Normal file
1
extracters/rstsflx/docomp.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern void docomp(int argc , char ** argv);
|
||||||
28
extracters/rstsflx/dodelete.c
Normal file
28
extracters/rstsflx/dodelete.c
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* handler for the "delete" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "dodelete.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
void dodel2 (firqb *f)
|
||||||
|
{
|
||||||
|
if (protfile (f)) return; /* quit if protected file */
|
||||||
|
delfile (f); /* now really delete the file */
|
||||||
|
if (sw.verbose != NULL) {
|
||||||
|
printcurname (f);
|
||||||
|
printf (" deleted\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dodelete (int argc, char **argv)
|
||||||
|
{
|
||||||
|
rmountrw (); /* mount r/w */
|
||||||
|
dofiles (argc, argv, dodel2, NOTNULL);
|
||||||
|
rumountrw (); /* done with r/w */
|
||||||
|
}
|
||||||
4
extracters/rstsflx/dodelete.h
Normal file
4
extracters/rstsflx/dodelete.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
extern void dodel2(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void dodelete(int argc , char ** argv);
|
||||||
128
extracters/rstsflx/dodir.c
Normal file
128
extracters/rstsflx/dodir.c
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/* handler for the mkdir" and "rmdir" commands */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "dodir.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
|
||||||
|
void domkdir (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
firqb f;
|
||||||
|
int newclu;
|
||||||
|
char *p;
|
||||||
|
word link, ulink, alink, qlink;
|
||||||
|
uattr *u;
|
||||||
|
ua_qt2 *q;
|
||||||
|
|
||||||
|
if (argc == 0) {
|
||||||
|
printf ("Usage: %s mkdir dir...\n", progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rmountrw ();
|
||||||
|
if (sw.clusiz == NULL) {
|
||||||
|
newclu = pcs;
|
||||||
|
if (newclu > 16) newclu = 16;
|
||||||
|
} else {
|
||||||
|
newclu = strtol (sw.clusiz, &p, 10);
|
||||||
|
if (newclu < 0) {
|
||||||
|
newclu = -newclu;
|
||||||
|
if (newclu < pcs) {
|
||||||
|
newclu = pcs;
|
||||||
|
if (newclu > 16) newclu = 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*p != '\0' || (newclu < pcs && newclu < 16)
|
||||||
|
|| newclu > 16 ||
|
||||||
|
(newclu & (-newclu)) != newclu) {
|
||||||
|
rumountrw (); /* dismount first */
|
||||||
|
printf ("Invalid clustersize %s\n", sw.clusiz);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (n = 0; n < argc; n++) {
|
||||||
|
if (!parse (argv[n], &f) || f.flags != f_ppn) {
|
||||||
|
printf ("Invalid PPN %s\n", argv[n]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (initfilescan (&f, gfdatrtbl)) {
|
||||||
|
printf ("Directory [%d,%d] already exists\n",
|
||||||
|
f.cproj, f.cprog);
|
||||||
|
} else {
|
||||||
|
f.cproj = f.proj; /* set up for makedir */
|
||||||
|
f.cprog = f.prog;
|
||||||
|
if (makedir (&f, newclu)) {
|
||||||
|
if (sw.user != NULL) {
|
||||||
|
fbread (curgfd + gfdatrtbl);
|
||||||
|
link = fibufw[f.cprog];
|
||||||
|
readlktbl (link);
|
||||||
|
alink = use(gfdne,k)->ulnk;
|
||||||
|
if ((ulink = getent ()) == 0)
|
||||||
|
printf ("No room to mark account as user account\n");
|
||||||
|
else {
|
||||||
|
readlk (ulink);
|
||||||
|
u = use(uattr,k);
|
||||||
|
u->ulnk = alink;
|
||||||
|
u->uatyp = aa_pas;
|
||||||
|
MARKF;
|
||||||
|
if ((qlink = getent ()) == 0) {
|
||||||
|
printf ("No room for second quota block\n");
|
||||||
|
qlink = ulink;
|
||||||
|
} else {
|
||||||
|
readlk (qlink);
|
||||||
|
q = use(ua_qt2,k);
|
||||||
|
q->ulnk = ulink;
|
||||||
|
q->uatyp = aa_qt2;
|
||||||
|
q->a2_job = 255U;
|
||||||
|
q->a2_rib = 4;
|
||||||
|
q->a2_msg = 12;
|
||||||
|
MARKF;
|
||||||
|
}
|
||||||
|
readlk (link);
|
||||||
|
use(gfdne,k)->ulnk = qlink;
|
||||||
|
MARKF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.verbose != NULL)
|
||||||
|
printf ("Account [%d,%d] created\n",
|
||||||
|
f.proj, f.prog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rumountrw ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dormdir (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
firqb f;
|
||||||
|
word ne;
|
||||||
|
|
||||||
|
if (argc == 0) {
|
||||||
|
printf ("Usage: %s rmdir dir...\n", progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rmountrw ();
|
||||||
|
for (n = 0; n < argc; n++) {
|
||||||
|
if (!parse (argv[n], &f) || (f.flags & ~f_ppnw) != f_ppn) {
|
||||||
|
printf ("Invalid PPN %s\n", argv[n]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((ne = initfilescan (&f, gfdatrtbl)) == 0) {
|
||||||
|
printf ("No PPNs matching ");
|
||||||
|
printfqbppn (&f);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
if (remdir (&f, ne) && sw.verbose != NULL)
|
||||||
|
printf ("Account [%d,%d] deleted\n",
|
||||||
|
f.cproj, f.cprog);
|
||||||
|
} while ((ne = nextppn (&f, gfdatrtbl)) != 0);
|
||||||
|
}
|
||||||
|
rumountrw ();
|
||||||
|
}
|
||||||
2
extracters/rstsflx/dodir.h
Normal file
2
extracters/rstsflx/dodir.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
extern void domkdir(int argc , char ** argv);
|
||||||
|
extern void dormdir(int argc , char ** argv);
|
||||||
134
extracters/rstsflx/dodump.c
Normal file
134
extracters/rstsflx/dodump.c
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/* handler for the "dump" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "dodump.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
long startblk, endblk;
|
||||||
|
|
||||||
|
static byte toprint (byte c)
|
||||||
|
{
|
||||||
|
if (c > 31 && c < 127) return (c);
|
||||||
|
if (c > 159 ) return (c);
|
||||||
|
return ('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dumpbuf (firqb *f, word16 *buf, long count, long firstbyte)
|
||||||
|
{
|
||||||
|
int b;
|
||||||
|
long off, block;
|
||||||
|
char r50[4];
|
||||||
|
|
||||||
|
for (off = 0; off < count; off += 16, buf += 8) {
|
||||||
|
if ((off & (BLKSIZE - 1)) == 0) {
|
||||||
|
block = (firstbyte + off) / BLKSIZE + startblk;
|
||||||
|
if (f != NULL) {
|
||||||
|
printf ("\nFile: ");
|
||||||
|
printcurname (f);
|
||||||
|
} else printf ("\nRSTS disk");
|
||||||
|
printf (" block %ld\n", block);
|
||||||
|
}
|
||||||
|
if (sw.hex != NULL) {
|
||||||
|
printf ("%03lx/ ", off & (BLKSIZE - 1));
|
||||||
|
for (b = 0; b < 8; b++) printf ("%04x ", buf[b]);
|
||||||
|
} else {
|
||||||
|
printf ("%03lo/ ", off & (BLKSIZE - 1));
|
||||||
|
for (b = 0; b < 8; b++) printf ("%06o ", buf[b]);
|
||||||
|
}
|
||||||
|
for (b = 0; b < 8; b++) printf ("%c%c", toprint (buf[b] & 0xff), toprint (buf[b] >> 8));
|
||||||
|
if (sw.wide != NULL) {
|
||||||
|
for (b = 0; b < 8; b++) {
|
||||||
|
r50toascii (buf[b], r50, TRUE);
|
||||||
|
printf (" %s", r50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dumpfile (firqb *f)
|
||||||
|
{
|
||||||
|
long iocount, totalbytes, end2;
|
||||||
|
|
||||||
|
if (startblk >= f->size) return; /* nothing to do */
|
||||||
|
end2 = endblk;
|
||||||
|
if (end2 > f->size) end2 = f->size; /* get end for this file */
|
||||||
|
initrandom (f); /* set up for random read */
|
||||||
|
fileseek (f, startblk); /* and seek to start vbn */
|
||||||
|
totalbytes = 0;
|
||||||
|
while (TRUE) {
|
||||||
|
iocount = (end2 - startblk) * BLKSIZE - totalbytes;
|
||||||
|
if (iocount > iobufsize) iocount = iobufsize;
|
||||||
|
if (iocount <= 0) return;
|
||||||
|
iocount = seqio (f, iocount, rread, iobuf);
|
||||||
|
if (iocount == 0) return; /* exit if EOF */
|
||||||
|
dumpbuf (f, (word16 *) iobuf, iocount, totalbytes);
|
||||||
|
totalbytes += iocount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dumpdisk (void)
|
||||||
|
{
|
||||||
|
long lbn, iocount, totalbytes;
|
||||||
|
|
||||||
|
if (endblk > diskblocks) endblk = diskblocks;
|
||||||
|
totalbytes = 0;
|
||||||
|
for (lbn = startblk; lbn < endblk; lbn += iobufsize / BLKSIZE) {
|
||||||
|
iocount = (endblk - lbn) * BLKSIZE;
|
||||||
|
if (iocount > iobufsize) iocount = iobufsize;
|
||||||
|
if (iocount <= 0) return;
|
||||||
|
rread (lbn, iocount, iobuf);
|
||||||
|
dumpbuf (NULL, (word16 *) iobuf, iocount, totalbytes);
|
||||||
|
totalbytes += iocount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "dump" will dump the disk NFS, or a directory (UFD), or a file. If no
|
||||||
|
* name is specified, you get NFS disk. In that case, there need not be
|
||||||
|
* any meaningful file structure on the disk. If a PPN is specified but no
|
||||||
|
* file name, you get the UFD; if a filename is given, you get that file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void dodump (int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (sw.start == NULL) startblk = 0; /* start at the bottom */
|
||||||
|
else {
|
||||||
|
if (*sw.start == '0') startblk = strtoul (sw.start, &p, 8);
|
||||||
|
else startblk = strtoul (sw.start, &p, 10);
|
||||||
|
if (*p != '\0') {
|
||||||
|
printf ("Invalid start block %s\n", sw.start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.end == NULL) endblk = 1L << 23; /* dump everything */
|
||||||
|
else {
|
||||||
|
if (*sw.end == '0') endblk = strtoul (sw.end, &p, 8);
|
||||||
|
else endblk = strtoul (sw.end, &p, 10);
|
||||||
|
if (*p != '\0') {
|
||||||
|
printf ("Invalid end block %s\n", sw.end);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endblk++; /* make end + 1 */
|
||||||
|
if (argc == 0) {
|
||||||
|
ropen (DREADMODE); /* open the disk */
|
||||||
|
dumpdisk (); /* do NFS dump */
|
||||||
|
rclose (); /* now close it */
|
||||||
|
} else {
|
||||||
|
rmount (); /* mount R/O */
|
||||||
|
dofiles (argc, argv, dumpfile, NULLISNULL);
|
||||||
|
rumount (); /* done with the disk */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1
extracters/rstsflx/dodump.h
Normal file
1
extracters/rstsflx/dodump.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern void dodump(int argc , char ** argv);
|
||||||
193
extracters/rstsflx/doget.c
Normal file
193
extracters/rstsflx/doget.c
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/* handler for the "get" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#if (defined(__MSDOS__) && !defined(__unix__))
|
||||||
|
#include <dir.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "doget.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
#ifndef S_IRWXU
|
||||||
|
#define S_IRWXU (S_IREAD+S_IWRITE+S_IEXEC)
|
||||||
|
#endif
|
||||||
|
#ifndef S_IRWXG
|
||||||
|
#define S_IRWXG 0
|
||||||
|
#endif
|
||||||
|
#ifndef S_IRWXO
|
||||||
|
#define S_IRWXO 0
|
||||||
|
#endif
|
||||||
|
#ifndef S_ISDIR
|
||||||
|
#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define mkdirmode (S_IRWXU | S_IRWXG | S_IRWXO) /* mode for new directory */
|
||||||
|
|
||||||
|
static int concat; /* concatenating to one file */
|
||||||
|
static struct stat sbuf;
|
||||||
|
static char *on, *on2;
|
||||||
|
static FILE *of;
|
||||||
|
static byte cproj, cprog;
|
||||||
|
static long matches, tmatches;
|
||||||
|
static int binmode; /* true if doing binary copy */
|
||||||
|
static const char *openmode;
|
||||||
|
static long filebytes, tbytes;
|
||||||
|
|
||||||
|
static void dogetfile (firqb *f) {
|
||||||
|
struct stat sbuf2;
|
||||||
|
char tmpname[FILENAME_MAX];
|
||||||
|
char dirname[FILENAME_MAX];
|
||||||
|
char rname[NAMELEN];
|
||||||
|
|
||||||
|
if (!concat) {
|
||||||
|
if (S_ISDIR(sbuf.st_mode)) {
|
||||||
|
if (f->stat & us_ufd)
|
||||||
|
sprintf (rname, "%03d%03d.dir", f->cproj, f->cprog);
|
||||||
|
else {
|
||||||
|
readlk (f->nlink);
|
||||||
|
r50filename (use(ufdne,k)->unam,
|
||||||
|
rname, FALSE);
|
||||||
|
}
|
||||||
|
if (sw.tree != NULL) {
|
||||||
|
if (cproj != f->cproj || cprog != f->cprog) {
|
||||||
|
cproj = f->cproj;
|
||||||
|
cprog = f->cprog;
|
||||||
|
sprintf (dirname, "%s/%03d%03d", on, cproj, cprog);
|
||||||
|
if (stat (dirname, &sbuf2)) {
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
printf ("Can't stat %s\n", dirname);
|
||||||
|
perror (progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef __unix__
|
||||||
|
if (mkdir (dirname, mkdirmode)) {
|
||||||
|
#else
|
||||||
|
if (mkdir (dirname)) {
|
||||||
|
#endif
|
||||||
|
printf ("Can't mkdir %s\n", dirname);
|
||||||
|
perror (progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf (tmpname, "%s/%s", dirname, rname);
|
||||||
|
} else sprintf (tmpname, "%s/%s", on, rname);
|
||||||
|
on2 = tmpname;
|
||||||
|
} else on2 = on;
|
||||||
|
|
||||||
|
/* open mode rule for copying to individual files:
|
||||||
|
* if -b is specified, use binary mode
|
||||||
|
* if -a is specified, use ascii mode
|
||||||
|
* else (no mode switch), the choice depends on the
|
||||||
|
* RMS file attributes, if any, of the input file:
|
||||||
|
* non-RMS files:
|
||||||
|
* if extension indicates text file, use ascii mode
|
||||||
|
* else use binary mode
|
||||||
|
* directory: use binary mode
|
||||||
|
* RMS sequential files:
|
||||||
|
* if fixed length records, recordsize a multiple of 512, use binary mode
|
||||||
|
* else use ascii mode
|
||||||
|
* Other RMS organizations, use binary mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (sw.bswitch != NULL) binmode = TRUE;
|
||||||
|
else if (sw.ascii != NULL) binmode = FALSE;
|
||||||
|
else {
|
||||||
|
if (f->stat & us_ufd) binmode = TRUE;
|
||||||
|
else if (NULLINK(f->rmslink))
|
||||||
|
binmode = !textfile (f->cname);
|
||||||
|
else {
|
||||||
|
if ((f->recfmt & fa_org) == fo_seq) {
|
||||||
|
if ((f->recfmt & fa_rfm) == rf_fix
|
||||||
|
&& (f->recsiz & 511) == 0)
|
||||||
|
binmode = TRUE;
|
||||||
|
else binmode = FALSE;
|
||||||
|
} else binmode = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (binmode) openmode = "wb";
|
||||||
|
else openmode = "w";
|
||||||
|
if (sw.debug != NULL)
|
||||||
|
printf ("get mode %s\n", openmode);
|
||||||
|
of = fopen (on2, openmode);
|
||||||
|
if (of == NULL) {
|
||||||
|
printf ("can't create %s\n", on2);
|
||||||
|
perror (progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matches++; /* found another */
|
||||||
|
tmatches++;
|
||||||
|
filebytes = getfile (of, f, binmode);
|
||||||
|
tbytes += filebytes;
|
||||||
|
if (!concat) fclose (of);
|
||||||
|
if (sw.verbose != NULL) {
|
||||||
|
printcurname (f);
|
||||||
|
if (concat && tmatches > 1)
|
||||||
|
printf (" =>> %s (%ld bytes) in ", on, filebytes);
|
||||||
|
else printf (" => %s (%ld bytes) in ", on2, filebytes);
|
||||||
|
if (binmode) printf ("block mode\n");
|
||||||
|
else printf ("line mode\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doget (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
firqb f;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf ("Usage: %s get file... dest\n", progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
on = argv[--argc]; /* for convenience */
|
||||||
|
cproj = cprog = 0; /* no current PPN yet */
|
||||||
|
tmatches = 0; /* total matches */
|
||||||
|
tbytes = 0; /* and total bytes */
|
||||||
|
if (stat (on, &sbuf)) { /* stat the output spec */
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
printf ("can't stat %s\n", on);
|
||||||
|
perror (progname); /* report any details */
|
||||||
|
return; /* and give up right now */
|
||||||
|
} else sbuf.st_mode = 0; /* not found -> not a dir */
|
||||||
|
}
|
||||||
|
s = strlen (on);
|
||||||
|
if (on[s - 1] == '/') on[s - 1] = '\0';
|
||||||
|
on2 = on;
|
||||||
|
/* concatenating if output is a filespec (not a directory spec)
|
||||||
|
* and input spec is wildcard, or multiple input specs
|
||||||
|
*/
|
||||||
|
parse (argv[1], &f); /* parse first argument for wildcards */
|
||||||
|
concat = (!S_ISDIR(sbuf.st_mode) &&
|
||||||
|
(((f.flags & F_WILD) != 0) || argc >= 2));
|
||||||
|
if (concat) { /* create now if concatenating */
|
||||||
|
if (sw.bswitch == NULL) {
|
||||||
|
openmode = "w"; /* ascii mode */
|
||||||
|
binmode = FALSE;
|
||||||
|
} else {
|
||||||
|
openmode = "wb"; /* binary mode */
|
||||||
|
binmode = TRUE;
|
||||||
|
}
|
||||||
|
if ((of = fopen (on, openmode)) == NULL) {
|
||||||
|
printf ("can't create %s\n", on);
|
||||||
|
perror (progname); /* report any details */
|
||||||
|
return; /* and give up right now */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rmount (); /* mount the disk */
|
||||||
|
dofiles (argc, argv, dogetfile, NULLISNULL);
|
||||||
|
if (concat) fclose (of);
|
||||||
|
if (sw.verbose != NULL && matches != 0)
|
||||||
|
printf ("Total files: %ld, total bytes: %ld\n", tmatches, tbytes);
|
||||||
|
rumount (); /* done with the disk */
|
||||||
|
}
|
||||||
|
|
||||||
1
extracters/rstsflx/doget.h
Normal file
1
extracters/rstsflx/doget.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern void doget(int argc , char ** argv);
|
||||||
350
extracters/rstsflx/dohook.c
Normal file
350
extracters/rstsflx/dohook.c
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
/* handler for the "hook" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "silfmt.h"
|
||||||
|
#include "dohook.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
|
||||||
|
typedef struct { /* boot data pointer in boot block */
|
||||||
|
word16 lbn[2]; /* block number, LSW first */
|
||||||
|
word16 wcnt; /* word count */
|
||||||
|
} bdesc;
|
||||||
|
|
||||||
|
typedef struct { /* header of boot block */
|
||||||
|
word16 nop; /* nop required for boot */
|
||||||
|
word16 setup_br; /* go do setup and relocation code */
|
||||||
|
word16 trap4_vec[2]; /* if trap to 4, halt @ 6 w/ 10 in lights */
|
||||||
|
word16 trap10_vec[2]; /* if trap to 10, halt @ 12 w/ 14 in lights */
|
||||||
|
word16 clustr; /* 14 cluster size */
|
||||||
|
word16 csr; /* 16 csr base */
|
||||||
|
word16 devnam; /* 20 device name */
|
||||||
|
word16 jmp; /* 22 jump to start address */
|
||||||
|
word16 transfer; /* 24 transfer address (set by hook) */
|
||||||
|
byte unit; /* 26 unit # in bits <2:0> (set by boot) */
|
||||||
|
byte flags; /* 27 flags (definitions are in inidfn) */
|
||||||
|
word16 unit_csr; /* 30 unit # in bits for csr (set by boot) */
|
||||||
|
byte rc, wc; /* 32 read and write codes */
|
||||||
|
word16 function; /* 34 function code: read */
|
||||||
|
word16 blknum[2]; /* 36-40 block number to read, also spec func. */
|
||||||
|
word16 memadr[2]; /* 42-44 memory address to read into */
|
||||||
|
word16 wcnt; /* 46 word count, also spec function parameter */
|
||||||
|
word16 reset; /* 50 do a device reset */
|
||||||
|
word16 read; /* 52 do a single transfer */
|
||||||
|
word16 spec; /* 54 do a magtape special function */
|
||||||
|
} bhdr;
|
||||||
|
|
||||||
|
int stbcnt, ovrcnt; /* SIL STB and OVR table entry count */
|
||||||
|
stbent *stb = NULL; /* pointer to STB buffer */
|
||||||
|
ovrent *ovr = NULL; /* pointer to OVR buffer */
|
||||||
|
|
||||||
|
/* note 0 rather than NULL because NULL is generally defined wrong
|
||||||
|
* (causing a warning that is a nuisance though it does no harm)
|
||||||
|
*/
|
||||||
|
const char disks[][3] = { "dv","df","ds","dk","dl","dm",
|
||||||
|
"dp","db","dr","dz","dw","du",
|
||||||
|
0 };
|
||||||
|
|
||||||
|
long findsym (const char *sym)
|
||||||
|
{
|
||||||
|
word16 r50[2];
|
||||||
|
int n;
|
||||||
|
stbent *s;
|
||||||
|
ovrent *o;
|
||||||
|
|
||||||
|
cvtnametor50 (sym, r50); /* convert symbol to rad50 */
|
||||||
|
s = stb; /* point to start of stb */
|
||||||
|
for (n = 0; n < stbcnt; n++, s++)
|
||||||
|
{
|
||||||
|
if (s->name[0] == r50[0] && s->name[1] == r50[1])
|
||||||
|
{
|
||||||
|
if (s->ovnum >= ovrcnt)
|
||||||
|
{
|
||||||
|
printf ("Bad STB entry for %s\n", sym);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (s->ovnum == 0) return (s->value);
|
||||||
|
o = &ovr[s->ovnum];
|
||||||
|
return (s->value - o->base +
|
||||||
|
(o->offset[0] << 16) + o->offset[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setptr (long blk, long size, void *buf)
|
||||||
|
{
|
||||||
|
bdesc *b;
|
||||||
|
|
||||||
|
b = (bdesc *) buf; /* point to where descriptor goes */
|
||||||
|
b->wcnt = size / 2; /* set word count */
|
||||||
|
b->lbn[0] = blk & 0xffff; /* low order LBN */
|
||||||
|
b->lbn[1] = blk >> 16; /* and high order */
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SIL 074064 /* rad50 "SIL" */
|
||||||
|
|
||||||
|
int silchk (firqb *f, savsilindex *x)
|
||||||
|
{
|
||||||
|
word16 cs;
|
||||||
|
word16 *p;
|
||||||
|
|
||||||
|
p = &(x->si_sil);
|
||||||
|
if (*p != SIL) /* verify SIL marker */
|
||||||
|
{
|
||||||
|
printcurname (f);
|
||||||
|
printf (" is not a SIL\n");
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
cs = 0; /* initialize checksum */
|
||||||
|
do cs ^= *--p; /* XOR checksum of the rest */
|
||||||
|
while (p != (word16 *)x);
|
||||||
|
if (cs != 0)
|
||||||
|
{
|
||||||
|
printf ("checksum error in SIL ");
|
||||||
|
printcurname (f);
|
||||||
|
printf ("\n");
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
return (TRUE); /* it's ok */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read file data for some given byte address, and return a pointer to
|
||||||
|
* where it is. There's at least 512 valid bytes after that point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* this routine reads data from the file, doing the full count requested
|
||||||
|
* even if it requires multiple calls to seqio. (note that seqio only
|
||||||
|
* reads a single contiguous piece of file.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
void readfile (firqb *f, long count, void *buf)
|
||||||
|
{
|
||||||
|
long rcnt;
|
||||||
|
byte *b; /* workaround cc bug */
|
||||||
|
|
||||||
|
b = (byte *) buf;
|
||||||
|
while (count)
|
||||||
|
{
|
||||||
|
rcnt = seqio (f, count, rread, b);
|
||||||
|
if (rcnt == 0) return; /* eof??? */
|
||||||
|
b += rcnt; /* adjust by what we read */
|
||||||
|
count -= rcnt; /* and count also */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *getdata (firqb *f, long address)
|
||||||
|
{
|
||||||
|
fileseek (f, address / BLKSIZE); /* seek to the right start block */
|
||||||
|
readfile (f, BLKSIZE * 2, iobuf);
|
||||||
|
return (iobuf + (address % BLKSIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup ()
|
||||||
|
{
|
||||||
|
rumountrw ();
|
||||||
|
if (ovr != NULL) free (ovr);
|
||||||
|
ovr = NULL;
|
||||||
|
if (stb != NULL) free (stb);
|
||||||
|
stb = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dohook (int argc, char **argv)
|
||||||
|
{
|
||||||
|
savsilindex idx; /* SIL index buffer */
|
||||||
|
int n;
|
||||||
|
firqb hf; /* file to be hooked */
|
||||||
|
firqb bf; /* file where bootstraps are */
|
||||||
|
char *disk; /* bootstrap name */
|
||||||
|
byte bbuf[BLKSIZE]; /* boot block buffer */
|
||||||
|
bdesc *bd; /* pointer to current boot data desc */
|
||||||
|
bhdr *bh; /* pointer to boot header */
|
||||||
|
int dskio, dskioe, xxboot; /* symbols from SIL */
|
||||||
|
int dskidx; /* disk index for boot disk name */
|
||||||
|
void *btop; /* pointer to end of boot code */
|
||||||
|
short int xxent; /* xxboot table entry */
|
||||||
|
int pcoffset; /* offset to apply to entry point */
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (argc == 0) disk = "dl";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
disk = argv[0]; /* disk is first argument */
|
||||||
|
if (strlen (disk) != 2 ) {
|
||||||
|
printf ("Invalid disk name %s\n", disk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
disk[0] = tolower (disk[0]);
|
||||||
|
if (disk[0] == 'r') disk[0] = 'd';
|
||||||
|
disk[1] = tolower (disk[1]);
|
||||||
|
}
|
||||||
|
for (dskidx = 0; ; dskidx++)
|
||||||
|
{
|
||||||
|
if (disks[dskidx] == NULL)
|
||||||
|
{
|
||||||
|
printf ("Unknown disk name %s\n", disk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp (disks[dskidx], disk) == 0) break;
|
||||||
|
}
|
||||||
|
if (sw.odt != NULL) pcoffset = 2;
|
||||||
|
else if (sw.offset == NULL) pcoffset = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pcoffset = strtol (sw.offset, &p, 10);
|
||||||
|
if (*p != '\0' || (pcoffset & 1) != 0)
|
||||||
|
{
|
||||||
|
printf ("Invalid offset %s\n", sw.offset);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dskidx *= 2; /* make even (byte offset) */
|
||||||
|
rmountrw (); /* mount disk for read/write */
|
||||||
|
if (argc < 2) parse ("[0,1]init.sys", &hf);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!parse (argv[1], &hf) || hf.flags & F_WILD)
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
printf ("Invalid filespec %s\n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((hf.flags & f_ppn) == 0)
|
||||||
|
{
|
||||||
|
hf.proj = 0;
|
||||||
|
hf.prog = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argc < 3) memcpy (&bf, &hf, sizeof (firqb));
|
||||||
|
else {
|
||||||
|
if (!parse (argv[2], &bf) || bf.flags & F_WILD)
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
printf ("Invalid filespec %s\n", argv[2]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((bf.flags & f_ppn) == 0)
|
||||||
|
{
|
||||||
|
bf.proj = 0;
|
||||||
|
bf.prog = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (initfilescan (&bf, gfddcntbl) == 0 ||
|
||||||
|
nextfile (&bf) == 0)
|
||||||
|
{
|
||||||
|
printfqbname (&bf);
|
||||||
|
printf (" not found\n");
|
||||||
|
cleanup ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initrandom (&bf); /* set up random access to bootfile */
|
||||||
|
seqio (&bf, sizeof(idx), rread, &idx); /* read sil index */
|
||||||
|
if (!silchk (&bf, &idx))
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
return; /* quit if bad sil index */
|
||||||
|
}
|
||||||
|
stbcnt = idx.si_ent.se_stn; /* copy STB and OVR sizes */
|
||||||
|
ovrcnt = idx.si_ent.se_ovn;
|
||||||
|
if ((stb = (stbent *) malloc (UP(stbcnt * sizeof (stbent),BLKSIZE))) == NULL)
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
rabort(NOMEM);
|
||||||
|
}
|
||||||
|
if ((ovr = (ovrent *) malloc (UP(ovrcnt * sizeof (ovrent),BLKSIZE))) == NULL)
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
rabort(NOMEM);
|
||||||
|
}
|
||||||
|
fileseek (&bf, idx.si_ent.se_stb); /* read symbol table */
|
||||||
|
readfile (&bf, UP(stbcnt * sizeof (stbent),BLKSIZE), stb);
|
||||||
|
fileseek (&bf, idx.si_ent.se_ovb); /* read symbol table */
|
||||||
|
readfile (&bf, UP(ovrcnt * sizeof (ovrent),BLKSIZE), ovr);
|
||||||
|
memset (bbuf, 0, BLKSIZE); /* zero out boot buffer */
|
||||||
|
if ((xxboot = findsym ("xxboot")) < 0)
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
printf ("Symbol XXBOOT not found\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((dskioe = findsym ("dskioe")) < 0)
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
printf ("Symbol DSKIOE not found\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((dskio = findsym ("dskio")) < 0) dskio = dskioe - 72;
|
||||||
|
xxboot += dskidx; /* point to entry for selected disk */
|
||||||
|
xxent = *(short int *)(getdata (&bf, xxboot));
|
||||||
|
if (xxent == 0)
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
printf ("No bootstrap for %s\n", disk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xxboot += xxent; /* point to bootstrap */
|
||||||
|
bh = (bhdr *)(getdata (&bf, xxboot)); /* read it */
|
||||||
|
n = bh->wcnt; /* get bootstrap size in bytes */
|
||||||
|
memcpy (bbuf, bh, n); /* copy that into boot buffer */
|
||||||
|
memcpy (bbuf + n, getdata (&bf, dskio), dskioe - dskio);
|
||||||
|
/* append boot mainline */
|
||||||
|
btop = bbuf + n + (dskioe - dskio);
|
||||||
|
if (initfilescan (&hf, gfddcntbl) == 0 ||
|
||||||
|
nextfile (&hf) == 0)
|
||||||
|
{
|
||||||
|
printcurname (&hf);
|
||||||
|
printf (" not found\n");
|
||||||
|
}
|
||||||
|
openfile (&hf); /* set up to read file to hook */
|
||||||
|
seqio (&bf, sizeof(idx), rread, &idx); /* read sil index */
|
||||||
|
if (!silchk (&hf, &idx))
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
return; /* quit if bad sil index */
|
||||||
|
}
|
||||||
|
openfile (&hf); /* reset to start over at VBN 0 */
|
||||||
|
if (idx.usertop >= 0157000)
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
printcurname (&hf);
|
||||||
|
printf (" high limit is too high (%06o)\n", idx.usertop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = UP(idx.usertop + 2,BLKSIZE); /* compute byte count to boot */
|
||||||
|
((bhdr *) bbuf)->transfer = idx.initpc + pcoffset;
|
||||||
|
/* set transfer address in bootstrap */
|
||||||
|
((bhdr *) bbuf)->clustr = dcs; /* set clustersize */
|
||||||
|
bd = (bdesc *)(&bbuf[0772]); /* initialize boot desc pointer */
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
if (--bd < (bdesc *)btop) /* check for bootstrap full */
|
||||||
|
{
|
||||||
|
cleanup ();
|
||||||
|
printcurname (&hf);
|
||||||
|
printf (" is too fragmented to hook\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
n -= seqio (&hf, n, setptr, bd);
|
||||||
|
}
|
||||||
|
rwrite (0, BLKSIZE, bbuf); /* write boot block */
|
||||||
|
if (sw.verbose != NULL)
|
||||||
|
{
|
||||||
|
printcurname (&hf);
|
||||||
|
if (sw.offset == NULL && sw.odt == NULL)
|
||||||
|
printf (" hooked, start PC = %06o\n", idx.initpc);
|
||||||
|
else printf (" hooked, start PC = %06o, offset %d\n",
|
||||||
|
idx.initpc + pcoffset, pcoffset);
|
||||||
|
}
|
||||||
|
cleanup (); /* clean up now */
|
||||||
|
return; /* and we're done */
|
||||||
|
}
|
||||||
13
extracters/rstsflx/dohook.h
Normal file
13
extracters/rstsflx/dohook.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
extern long findsym(const char * sym);
|
||||||
|
extern void setptr(long blk , long size , void * buf);
|
||||||
|
extern int silchk(firqb * f , savsilindex * x);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void readfile(firqb * f , long count , void * buf);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void * getdata(firqb * f , long address);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void cleanup(void);
|
||||||
|
extern void dohook(int argc , char ** argv);
|
||||||
48
extracters/rstsflx/doident.c
Normal file
48
extracters/rstsflx/doident.c
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* handler for the "identify" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "doident.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "rtime.h"
|
||||||
|
|
||||||
|
void doident (int argc, char **argv) /* show pack id data */
|
||||||
|
{
|
||||||
|
packlabel *p;
|
||||||
|
char rdate[DATELEN];
|
||||||
|
char rtime[RTIMELEN];
|
||||||
|
|
||||||
|
rmount (); /* mount the disk R/O */
|
||||||
|
readdcn (1); /* get the pack label */
|
||||||
|
p = use(packlabel,0);
|
||||||
|
if (p->fill1 == -1
|
||||||
|
&& (pcs >= dcs)
|
||||||
|
&& ((pcs & (-pcs)) == pcs)) {
|
||||||
|
printf ("RSTS disk on %s -- \"%s\"\n", rname, pname);
|
||||||
|
printf (" Device clustersize: %d\n", dcs);
|
||||||
|
printf (" Pack clustersize: %d\n", pcs);
|
||||||
|
if (dcs > 1)
|
||||||
|
printf (" Device size: %ld (%ld DCNs)\n",
|
||||||
|
diskblocks, diskblocks / dcs);
|
||||||
|
else printf (" Device size: %ld\n", diskblocks);
|
||||||
|
printf (" Revision level: %d.%d\n", plevel >> 8, plevel & 0377);
|
||||||
|
if (plevel >= RDS12) {
|
||||||
|
cvtdate (p->mntdat, rdate);
|
||||||
|
cvttime (p->mnttim, rtime);
|
||||||
|
printf (" Last mount date: %s\n", rdate);
|
||||||
|
printf (" Last mount time: %s\n", rtime);
|
||||||
|
}
|
||||||
|
printf (" Pack flags: ");
|
||||||
|
if (p->pstat & uc_mnt) printf (" Dirty");
|
||||||
|
if (p->pstat & uc_pri) printf (" Private/system");
|
||||||
|
else printf (" Public");
|
||||||
|
if (p->pstat & uc_ro) printf (" Read-only");
|
||||||
|
if (p->pstat & uc_dlw) printf (" DLW");
|
||||||
|
if (p->pstat & uc_top) printf (" NFF");
|
||||||
|
printf ("\n");
|
||||||
|
} else printf ("Disk on %s does not appear to be a RSTS format disk\n", rname);
|
||||||
|
rumount (); /* done with disk */
|
||||||
|
}
|
||||||
|
|
||||||
1
extracters/rstsflx/doident.h
Normal file
1
extracters/rstsflx/doident.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern void doident(int argc , char ** argv);
|
||||||
387
extracters/rstsflx/doinit.c
Normal file
387
extracters/rstsflx/doinit.c
Normal file
@@ -0,0 +1,387 @@
|
|||||||
|
/* handler for the "initialize" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "doinit.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "filename.h"
|
||||||
|
|
||||||
|
#define MFDCLU 16
|
||||||
|
#define UFDCLU 16
|
||||||
|
#define DEC166COUNT 10 /* number of bad block tables */
|
||||||
|
|
||||||
|
int getclusize ()
|
||||||
|
{
|
||||||
|
int newclu;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (sw.clusiz == NULL) return (dcs);
|
||||||
|
else {
|
||||||
|
newclu = strtol (sw.clusiz, &p, 10);
|
||||||
|
if (newclu < 0) {
|
||||||
|
newclu = -newclu;
|
||||||
|
if (newclu < dcs) newclu = dcs;
|
||||||
|
}
|
||||||
|
if (*p != '\0' || newclu < dcs || newclu > 64 ||
|
||||||
|
(newclu & (-newclu)) != newclu) {
|
||||||
|
printf ("Invalid clustersize %s\n", sw.clusiz);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (newclu);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PSTAT (uc_dlw | uc_pri) /* pack flags to use */
|
||||||
|
#define MRECNT 20 /* max RE's for merge.sys */
|
||||||
|
|
||||||
|
const ufdlabel newmlabel = { 0, 0177777, {0, 0, 0, 0}, {255, 255}, MFD};
|
||||||
|
const word16 rstsrts[2] = { 001343, 077770 }; /* rad50 " RSTS " */
|
||||||
|
|
||||||
|
/* Dummy bootstrap */
|
||||||
|
|
||||||
|
const word16 dummyboot[] = {
|
||||||
|
0000240, /* NOP ; */
|
||||||
|
0000005, /* RESET ;UGH */
|
||||||
|
0000402, /* BR 5$ ;Go to the real code */
|
||||||
|
|
||||||
|
0000020,0153430,0000400,/* BOOTID 5$,<> ;Boot ID block, no controllers */
|
||||||
|
|
||||||
|
0005067,0000002, /* 5$: CLR 20$ ;COUNT DOWN MEMORY TO DELAY */
|
||||||
|
0005327, /* 10$: DEC (PC)+ ;CHURN */
|
||||||
|
0000000, /* 20$: .WORD 0 ; */
|
||||||
|
0001375, /* BNE 10$ ; */
|
||||||
|
0010700, /* MOV PC,R0 ;GETTA POSITION INDEPENDENT MESSAGE */
|
||||||
|
0062700,0000026, /* ADD #40$-.,R0 ;ADDRESS INTO R0 */
|
||||||
|
0105737,0177564, /* 30$: TSTB @#177564 ;CONSOLE READY ? */
|
||||||
|
0100375, /* BPL 30$ ;PATIENCE */
|
||||||
|
0112037,0177566, /* MOVB (R0)+,@#177566 ;TALK TO ME */
|
||||||
|
0105710, /* TSTB (R0) ;ANY MORE ? */
|
||||||
|
0001371, /* BNE 30$ ;YUP */
|
||||||
|
0000000, /* HALT ;NOPE */
|
||||||
|
0000751 /* BR DUMBOT ;DO IT AGAIN IF HE CONTINUES */
|
||||||
|
|
||||||
|
/* 40$: ;String starts here */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define dummytext "\a\a\r\nPlease boot from the system disk\r\n"
|
||||||
|
|
||||||
|
void doinit (int argc, char **argv)
|
||||||
|
{
|
||||||
|
long n, count, sattblks;
|
||||||
|
firqb f, packid;
|
||||||
|
long newclu, newsize, newrsize;
|
||||||
|
int dec166;
|
||||||
|
long newlevel, mfdclu, ufdlbn;
|
||||||
|
char *p;
|
||||||
|
char answer[20];
|
||||||
|
struct stat sbuf;
|
||||||
|
word dirne;
|
||||||
|
packlabel *l;
|
||||||
|
ufdae *a;
|
||||||
|
FILE *mf;
|
||||||
|
long mblocks, moblk, mbytes, mreoff;
|
||||||
|
word mprevre, mre;
|
||||||
|
|
||||||
|
if (argc == 0) {
|
||||||
|
printf ("Usage: %s initialize packid [level]\n", progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
packid.flags = 0;
|
||||||
|
if (*parsename (argv[0], &packid) != '\0' || (packid.flags & F_WILD)) {
|
||||||
|
printf ("Invalid pack id %s\n", argv[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (argc < 2) newlevel = RDS12;
|
||||||
|
else {
|
||||||
|
p = argv[1];
|
||||||
|
if (tolower (*p) == 'r') {
|
||||||
|
p++;
|
||||||
|
if (tolower (*p++) != 'd' || tolower (*p++) != 's') {
|
||||||
|
printf ("Invalid revision level %s\n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (*p == ' ') p++;
|
||||||
|
if (strcmp (p, "0") == 0) newlevel = RDS0;
|
||||||
|
else if (strcmp (p, "0.0") == 0) newlevel = RDS0;
|
||||||
|
else if (strcmp (p, "1.1") == 0) newlevel = RDS11;
|
||||||
|
else if (strcmp (p, "1.2") == 0) newlevel = RDS12;
|
||||||
|
else {
|
||||||
|
printf ("Invalid revision level %s\n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.merge != NULL) { /* merging another filesystem */
|
||||||
|
if (newlevel == RDS0) {
|
||||||
|
printf ("-merge not allowed for RDS 0.0\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((mf = fopen (sw.merge, "rb")) == NULL) {
|
||||||
|
printf ("Can't open merge file %s\n", sw.merge);
|
||||||
|
perror (progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fstat (fileno(mf), &sbuf)) { /* get info about input file */
|
||||||
|
printf ("Can't stat merge file %s", sw.merge);
|
||||||
|
perror (progname);
|
||||||
|
fclose (mf); /* close input */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mblocks = UP(sbuf.st_size,BLKSIZE) / BLKSIZE;
|
||||||
|
}
|
||||||
|
if (sw.create != NULL) {
|
||||||
|
getsize (sw.create, &newsize, &newrsize, &dec166);
|
||||||
|
if (newsize == 0 ||
|
||||||
|
newsize < 800 ||
|
||||||
|
newsize >= (1 << 23)) {
|
||||||
|
printf ("Invalid container size %s\n", sw.create);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
diskblocks = newsize; /* allow writing it all */
|
||||||
|
n = (newrsize - 1) >> 16; /* high order bits of last LBN */
|
||||||
|
dcs = 1; /* compute DCS */
|
||||||
|
while (n) {
|
||||||
|
n >>= 1;
|
||||||
|
dcs <<= 1;
|
||||||
|
}
|
||||||
|
if (dcs > 16 && newlevel != RDS12)
|
||||||
|
{
|
||||||
|
printf ("Large disk requires RDS 1.2\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newclu = getclusize ();
|
||||||
|
setrname (); /* set container name */
|
||||||
|
if (stat (rname, &sbuf)) {
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
printf ("Can't stat %s\n", rname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf ("Container file %s already exists\n", rname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((rstsfile = fopen (rname, DCREATEMODE)) == NULL) {
|
||||||
|
printf ("Error opening container file %s\n", rname);
|
||||||
|
perror (progname); /* report any details */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset (iobuf, 0, iobufsize); /* zero the entire buffer */
|
||||||
|
for (n = 0; n < newsize; n += iobufsize / BLKSIZE) {
|
||||||
|
count = iobufsize / BLKSIZE;
|
||||||
|
if (newsize - n < count) count = newsize - n;
|
||||||
|
rwrite (n, count * BLKSIZE, iobuf);
|
||||||
|
}
|
||||||
|
if (dec166) { /* set up bad block table */
|
||||||
|
word16 *w;
|
||||||
|
memset (iobuf, -1, BLKSIZE); /* set end marker */
|
||||||
|
w = (word16 *)iobuf;
|
||||||
|
*w++ = 031416; /* random serial number */
|
||||||
|
*w++ = 0; /* and high order */
|
||||||
|
*w++ = 0; /* reserved word */
|
||||||
|
*w = 0; /* mark as data pack */
|
||||||
|
for (n = 0; n < DEC166COUNT; n++)
|
||||||
|
rwrite (newrsize + n, BLKSIZE, iobuf);
|
||||||
|
}
|
||||||
|
diskblocks = newrsize;
|
||||||
|
} else {
|
||||||
|
ropen (DWRITEMODE);
|
||||||
|
if (dcs > 16 && newlevel != RDS12)
|
||||||
|
{
|
||||||
|
printf ("Large disk requires RDS 1.2\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newclu = getclusize ();
|
||||||
|
readlabel ();
|
||||||
|
if (use(packlabel,0)->fill1 == -1
|
||||||
|
&& (pcs >= dcs)
|
||||||
|
&& ((pcs & (-pcs)) == pcs)) {
|
||||||
|
printf ("Disk %s appears to be a RSTS format disk:\n", rname);
|
||||||
|
printf (" Clustersize: %d\n", pcs);
|
||||||
|
printf (" Revision: %d.%d\n", plevel >> 8, plevel & 0xff);
|
||||||
|
printf (" Pack label: %s\n", pname);
|
||||||
|
printf ("\nRe-initialize it (Y/N)? ");
|
||||||
|
} else printf ("Initialize %s (Y/N)? ", rname);
|
||||||
|
fgets (answer, sizeof (answer), stdin);
|
||||||
|
if (tolower(answer[0]) != 'y') return;
|
||||||
|
}
|
||||||
|
fiblk = dcntolbn(1);
|
||||||
|
memset (fibuf, 0, BLKSIZE); /* clear out fibuf to make an invalid pack */
|
||||||
|
fbwrite (); /* write that out */
|
||||||
|
pcs = newclu; /* set new PCS */
|
||||||
|
f.clusiz = pcs; /* clustersize for files */
|
||||||
|
plevel = newlevel; /* set up pack level being created */
|
||||||
|
if (plevel == RDS0) pflags = PSTAT;
|
||||||
|
else pflags = PSTAT | uc_new; /* and flags also */
|
||||||
|
pcns = (diskblocks - dcs) / pcs; /* compute PCN count */
|
||||||
|
sattblks = UP(pcns,BLKSIZE*8) / (BLKSIZE * 8); /* SATT size in blocks */
|
||||||
|
sattsize = sattblks * BLKSIZE; /* and in bytes */
|
||||||
|
sattlbn = 1 << 23; /* set a fake SATT LBN */
|
||||||
|
if ((sattbufp = (byte *) malloc (sattsize)) == NULL) rabort(NOMEM);
|
||||||
|
memset (sattbufp, 0xff, sattsize); /* first mark everything in use */
|
||||||
|
memset (sattbufp, 0, pcns / 8); /* make all real clusters free */
|
||||||
|
if (pcns & 7) sattbufp[pcns / 8] = 0xff << (pcns & 7); /* ditto any leftover bits */
|
||||||
|
satptr = 0; /* MFD/label goes at the start */
|
||||||
|
if (plevel == RDS0) { /* doing an old pack */
|
||||||
|
if (!extdir2 (0, MFDCLU, 0, &newmlabel)) rabort(INTERNAL);
|
||||||
|
mfddcn = clumap->uent[0]; /* remember MFD start */
|
||||||
|
if (sw.debug != NULL) printf ("mfd at %lo\n", mfddcn);
|
||||||
|
if (mfddcn != 1) rabort(INTERNAL);
|
||||||
|
curgfd = mfdlbn = dcntolbn(mfddcn);
|
||||||
|
f.cproj = f.cprog = 1; /* prepare to create [1,1] */
|
||||||
|
prevppnlink = nextppnlink = 0; /* nothing in the MFD yet */
|
||||||
|
if (!makedir (&f, MFDCLU)) rabort(INTERNAL); /* create MFD */
|
||||||
|
readlk2 (0); /* re-read MFD label */
|
||||||
|
dirne = use(packlabel,0)->ulnk; /* get [1,1] NE link */
|
||||||
|
readlk (dirne); /* read that */
|
||||||
|
use(gfdne,k)->uar = 1; /* fill in cluster pointer */
|
||||||
|
MARKF;
|
||||||
|
satptr = pcns / 2; /* put the rest in the middle */
|
||||||
|
} else { /* new (RDS1.1 or later) pack */
|
||||||
|
if (sw.merge != 0) { /* do the merge */
|
||||||
|
if (mblocks <= dcs) { /* merge fits in pack label */
|
||||||
|
*sattbufp = 0x01; /* mark first cluster (pack label) allocated */
|
||||||
|
} else {
|
||||||
|
if (getclu (pcs, UP(mblocks-dcs,pcs)) != 1) {
|
||||||
|
printf ("No room for merge data\n");
|
||||||
|
rabort(INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moblk = 0;
|
||||||
|
while ((mbytes = fread (iobuf, 1, iobufsize, mf)) != 0) {
|
||||||
|
mbytes = UP(mbytes, BLKSIZE);
|
||||||
|
rwrite (moblk, mbytes, iobuf);
|
||||||
|
moblk += mbytes / BLKSIZE;
|
||||||
|
}
|
||||||
|
if (sw.verbose != NULL)
|
||||||
|
printf ("merged %s (%ld blocks)\n",
|
||||||
|
sw.merge, mblocks);
|
||||||
|
} else *sattbufp = 0x01; /* mark first cluster (pack label) allocated */
|
||||||
|
satptr = pcns / 2; /* put the rest in the middle */
|
||||||
|
mfdclu = MFDCLU; /* default MFD clustersize */
|
||||||
|
if (pcs > mfdclu) mfdclu = pcs;
|
||||||
|
if (mfdclu > 16) mfdclu = 16; /* adjust it as needed */
|
||||||
|
if (!extdir2 (0, mfdclu, fd_new, &newmlabel)) rabort(INTERNAL);
|
||||||
|
mfddcn = clumap->uent[0]; /* remember MFD start */
|
||||||
|
if (sw.debug != NULL) printf ("mfd at %lo\n", mfddcn);
|
||||||
|
mfdlbn = dcntolbn(mfddcn); /* and LBN also */
|
||||||
|
curgfd = 0; /* no [0,*] GFD yet */
|
||||||
|
}
|
||||||
|
parse ("[0,1]badb.sys<63>", &f); /* set up firqb */
|
||||||
|
f.cproj = f.proj;
|
||||||
|
f.cprog = f.prog; /* current also */
|
||||||
|
memcpy (f.cname, f.name, NAMELEN);
|
||||||
|
if (!makedir (&f, UFDCLU)) rabort(INTERNAL); /* create [0,1] account */
|
||||||
|
dirne = initfilescan (&f, gfdatrtbl); /* look up [0,1] NE pointer */
|
||||||
|
if (sw.debug != NULL) printf ("[0,1] NE %o\n", dirne);
|
||||||
|
if ((ufdlbn = allocufd (dirne, &f)) == 0) rabort(INTERNAL);
|
||||||
|
/* allocate the UFD */
|
||||||
|
fbread (ufdlbn); /* get it into fibuf */
|
||||||
|
nextlink = prevlink = 0;
|
||||||
|
entptr = sizeof (ufdlabel); /* initialize pointers for crefile */
|
||||||
|
f.stat = us_nok; /* we want P set for badb.sys */
|
||||||
|
f.clusiz = pcs; /* default clustersize */
|
||||||
|
if (!crefile (&f, rstsrts, NULL, NULL)) rabort(INTERNAL);
|
||||||
|
parse ("[0,1]satt.sys<63>", &f); /* set up firqb for the second file */
|
||||||
|
f.cproj = f.proj;
|
||||||
|
f.cprog = f.prog; /* current also */
|
||||||
|
memcpy (f.cname, f.name, NAMELEN);
|
||||||
|
f.stat = us_nok | us_nox; /* P set and contiguous */
|
||||||
|
f.size = sattblks; /* we need this size */
|
||||||
|
f.clusiz = pcs; /* default clustersize */
|
||||||
|
if (!crefile (&f, rstsrts, NULL, NULL)) rabort(INTERNAL);
|
||||||
|
readlk (f.rlink); /* read first RE */
|
||||||
|
sattlbn = dcntolbn(use(ufdre,k)->uent[0]);
|
||||||
|
if (sw.merge != NULL && (mblocks -= dcs + pcs) > 0) {
|
||||||
|
moblk = 1 + pcs / dcs; /* first DCN for merge.sys */
|
||||||
|
parse ("[0,1]merge.sys<63>", &f);
|
||||||
|
f.cproj = f.proj;
|
||||||
|
f.cprog = f.prog; /* current also */
|
||||||
|
memcpy (f.cname, f.name, NAMELEN);
|
||||||
|
f.stat = us_nok | us_nox; /* P set and contiguous */
|
||||||
|
f.size = 0; /* don't allocate it now */
|
||||||
|
f.clusiz = pcs; /* clustersize is PCS */
|
||||||
|
if (!crefile (&f, rstsrts, NULL, NULL)) rabort(INTERNAL);
|
||||||
|
readlk (f.alink);
|
||||||
|
a = use(ufdae,k);
|
||||||
|
a->usiz = mblocks;
|
||||||
|
if (mblocks >> 16) { /* large file ! */
|
||||||
|
a->urts[0] = 0;
|
||||||
|
a->urts[1] = mblocks >> 16;
|
||||||
|
}
|
||||||
|
MARKF;
|
||||||
|
mprevre = 0;
|
||||||
|
mreoff = 0; /* fill RE from top */
|
||||||
|
while (mblocks > 0) {
|
||||||
|
if (mreoff == 0) { /* need a new RE */
|
||||||
|
if ((mre = getent ()) == 0) {
|
||||||
|
printf ("No room in [0,1] for merge.sys\n");
|
||||||
|
rabort(INTERNAL);
|
||||||
|
}
|
||||||
|
if (mprevre) {
|
||||||
|
readlk (mprevre);
|
||||||
|
use(ufdre,k)->ulnk = mre;
|
||||||
|
} else {
|
||||||
|
readlk (f.nlink);
|
||||||
|
use(ufdne,k)->uar = mre;
|
||||||
|
}
|
||||||
|
MARKF;
|
||||||
|
mprevre = mre; /* link to this next time */
|
||||||
|
}
|
||||||
|
readlk (mre);
|
||||||
|
use(ufdre,k)->uent[mreoff] = moblk;
|
||||||
|
moblk += pcs / dcs; /* advance to next cluster */
|
||||||
|
mblocks -= pcs; /* count down size to fill */
|
||||||
|
mreoff++;
|
||||||
|
if (mreoff > 6) mreoff = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rwrite (sattlbn, sattsize, sattbufp); /* now write the SATT data */
|
||||||
|
womsat = FALSE;
|
||||||
|
free (sattbufp); /* deallocate SATT */
|
||||||
|
checkwrite (); /* write FIBUF if needed */
|
||||||
|
if (sw.merge != NULL) { /* see if overwriting merge data */
|
||||||
|
fbread (0); /* read the boot block */
|
||||||
|
for (n = 0; n < BLKSIZE; n++) {
|
||||||
|
if (fibuf[n] != 0) {
|
||||||
|
printf ("Warning: non-zero merge file data in boot block\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fiblk = 0; /* build the dummy boot */
|
||||||
|
memset (fibuf, 0, BLKSIZE); /* clear it out */
|
||||||
|
memcpy (fibuf, dummyboot, sizeof (dummyboot));
|
||||||
|
memcpy (fibuf + sizeof (dummyboot), dummytext, sizeof (dummytext));
|
||||||
|
fbwrite (); /* and write it */
|
||||||
|
readdcn (1); /* re-read pack label */
|
||||||
|
if (sw.merge != NULL) { /* see if overwriting merge data */
|
||||||
|
for (n = 0; n < BLKSIZE; n++) {
|
||||||
|
if (fibuf[n] != 0) {
|
||||||
|
printf ("Warning: non-zero merge file data in pack label\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l = use(packlabel,0);
|
||||||
|
l->fill1 = 0177777;
|
||||||
|
l->ppcs = pcs; /* pack cluster size */
|
||||||
|
if (plevel > RDS0) { /* if new pack, set new fields: */
|
||||||
|
l->mdcn = mfddcn; /* MFD DCN */
|
||||||
|
l->plvl = newlevel; /* and rev level */
|
||||||
|
l->ulnk = 1; /* link field = 1 by convention */
|
||||||
|
l->mntdat = l->mnttim = 0; /* never mounted yet */
|
||||||
|
}
|
||||||
|
l->pstat = pflags; /* set pack flags */
|
||||||
|
cvtnametor50 (packid.name, l->pckid); /* set the pack label */
|
||||||
|
fbwrite (); /* write the pack label */
|
||||||
|
rclose (); /* and that's all! */
|
||||||
|
}
|
||||||
2
extracters/rstsflx/doinit.h
Normal file
2
extracters/rstsflx/doinit.h
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
extern int getclusize(void);
|
||||||
|
extern void doinit(int argc , char * argv[]);
|
||||||
218
extracters/rstsflx/dolist.c
Normal file
218
extracters/rstsflx/dolist.c
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/* handler for the "list" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "dolist.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "rtime.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
#define COLUMNS 5
|
||||||
|
|
||||||
|
long files, blocks, tfiles, tblocks;
|
||||||
|
byte curproj, curprog;
|
||||||
|
|
||||||
|
static void dolistfqb (firqb *f)
|
||||||
|
{
|
||||||
|
word utc;
|
||||||
|
ufdae *a;
|
||||||
|
ufdrms1 *r1;
|
||||||
|
ufdrms2 *r2;
|
||||||
|
int pos;
|
||||||
|
int line2;
|
||||||
|
char rts[RTSLEN];
|
||||||
|
char stat[4];
|
||||||
|
char credate[DATELEN], acdate[DATELEN], cretime[RTIMELEN];
|
||||||
|
char *sp;
|
||||||
|
|
||||||
|
if (sw.narrow != NULL) sw.bswitch = sw.narrow; /* -1 implies -b */
|
||||||
|
if (f->cproj != curproj || f->cprog != curprog)
|
||||||
|
{
|
||||||
|
if (curproj != 0 || curprog != 0)
|
||||||
|
{
|
||||||
|
if (sw.bswitch != NULL)
|
||||||
|
{
|
||||||
|
if (sw.narrow != NULL
|
||||||
|
|| files % COLUMNS == 0)
|
||||||
|
printf ("\n");
|
||||||
|
else printf ("\n\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf (" Total of %ld blocks in %ld files in [%d,%d]\n",
|
||||||
|
blocks, files, curproj, curprog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
files = 0;
|
||||||
|
blocks = 0;
|
||||||
|
curproj = f->cproj;
|
||||||
|
curprog = f->cprog;
|
||||||
|
if (sw.summary == NULL)
|
||||||
|
{
|
||||||
|
if (sw.bswitch != NULL)
|
||||||
|
{
|
||||||
|
if (sw.narrow == NULL)
|
||||||
|
printf ("[%d,%d]\n", curproj, curprog);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("\nDirectory of [%d,%d]\n"
|
||||||
|
" Name .Ext Size Prot Access"
|
||||||
|
" Creation Clu"
|
||||||
|
" RTS Pos\n",
|
||||||
|
curproj, curprog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
files++; /* accumulate totals */
|
||||||
|
tfiles++;
|
||||||
|
blocks += f->size;
|
||||||
|
tblocks += f->size;
|
||||||
|
if (sw.summary != NULL) return;
|
||||||
|
if (sw.bswitch != NULL) { /* brief listing */
|
||||||
|
if (sw.narrow != NULL || files % COLUMNS == 0)
|
||||||
|
printf ("%-10s\n", f->cname);
|
||||||
|
else printf ("%-10s ", f->cname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sp = stat; /* point to status buffer */
|
||||||
|
if (f->stat & us_nox) *sp++ = 'C';
|
||||||
|
if (f->stat & us_nok) *sp++ = 'P';
|
||||||
|
if (f->stat & us_plc) *sp++ = 'L';
|
||||||
|
*sp = '\0'; /* put in terminator */
|
||||||
|
readlk (f->alink); /* make sure we have the AE */
|
||||||
|
a = use(ufdae,k); /* and point to it */
|
||||||
|
cvtdate (a->udla, acdate); /* convert dates and time */
|
||||||
|
cvtdate (a->udc, credate);
|
||||||
|
utc = a->utc; /* save time (for flags) */
|
||||||
|
cvttime (utc, cretime);
|
||||||
|
if (a->urts[0] != 0)
|
||||||
|
r50toascii2 (a->urts, rts, TRUE);
|
||||||
|
else memcpy (rts, " ", RTSLEN);
|
||||||
|
if (f->size == 0)
|
||||||
|
printf ("%-10s%8ld%-3s <%3d> %11s %11s %8s %3d %-6s ----\n",
|
||||||
|
f->cname, f->size, stat, f->prot,
|
||||||
|
acdate, credate, cretime, f->clusiz, rts);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!readlk (f->rlink)) rabort (CORRUPT);
|
||||||
|
pos = use(ufdre,k)->uent[0]; /* Get first retrieval entry */
|
||||||
|
printf ("%-10s%8ld%-3s <%3d> %9s %9s %8s %3d %-6s %6d\n",
|
||||||
|
f->cname, f->size, stat, f->prot,
|
||||||
|
acdate, credate, cretime, f->clusiz, rts, pos);
|
||||||
|
}
|
||||||
|
if (sw.full != NULL) { /* full listing */
|
||||||
|
line2 = FALSE; /* no flags line yet */
|
||||||
|
if (f->nlink & ul_che)
|
||||||
|
{
|
||||||
|
line2 = TRUE;
|
||||||
|
printf (" cache:on");
|
||||||
|
if (f->alink & ul_che) printf (":seq");
|
||||||
|
else printf (":ran");
|
||||||
|
}
|
||||||
|
if (utc & (utc_ig | utc_bk))
|
||||||
|
{
|
||||||
|
if (line2) printf (" ");
|
||||||
|
line2 = TRUE;
|
||||||
|
if (utc & utc_ig) printf (" ignore");
|
||||||
|
if (utc & utc_bk) printf (" nobackup");
|
||||||
|
}
|
||||||
|
if (line2) printf ("\n");
|
||||||
|
if (readlk (f->rmslink)) { /* if RMS attributes present */
|
||||||
|
r1 = use(ufdrms1,k);
|
||||||
|
printf (" rfm:");
|
||||||
|
switch (r1->fa_typ & fa_rfm)
|
||||||
|
{
|
||||||
|
case rf_udf: printf ("ufd"); break;
|
||||||
|
case rf_fix: printf ("fix"); break;
|
||||||
|
case rf_var: printf ("var"); break;
|
||||||
|
case rf_vfc: printf ("vfc"); break;
|
||||||
|
case rf_stm: printf ("stm"); break;
|
||||||
|
}
|
||||||
|
switch (r1->fa_typ & fa_org)
|
||||||
|
{
|
||||||
|
case fo_seq: printf (":seq"); break;
|
||||||
|
case fo_rel: printf (":rel"); break;
|
||||||
|
case fo_idx: printf (":idx"); break;
|
||||||
|
}
|
||||||
|
if (r1->fa_typ & fa_rat)
|
||||||
|
{
|
||||||
|
printf (" rat");
|
||||||
|
if (r1->fa_typ & ra_ftn) printf (":ftn");
|
||||||
|
if (r1->fa_typ & ra_imp) printf (":imp");
|
||||||
|
if (r1->fa_typ & ra_spn) printf (":nospan");
|
||||||
|
}
|
||||||
|
printf (" rsz:%d size:%ld eof:%ld:%d",
|
||||||
|
r1->fa_rsz,
|
||||||
|
((long)(r1->fa_siz[0]) << 16) + r1->fa_siz[1],
|
||||||
|
((long)(r1->fa_eof[0]) << 16) + r1->fa_eof[1],
|
||||||
|
r1->fa_eofb);
|
||||||
|
if (readlk (r1->ulnk))
|
||||||
|
{
|
||||||
|
r2 = use(ufdrms2,k);
|
||||||
|
printf (" bkt:%d hdr:%d msz:%d ext:%d",
|
||||||
|
r2->fa_bkt, r2->fa_hsz,
|
||||||
|
r2->fa_msz, r2->fa_ext);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.oattr != NULL && readlk (f->rmslink))
|
||||||
|
{
|
||||||
|
r1 = use(ufdrms1,k);
|
||||||
|
printf (" %06o %06o %06o %06o %06o %06o %06o",
|
||||||
|
r1->fa_typ, r1->fa_rsz,
|
||||||
|
r1->fa_siz[0], r1->fa_siz[1],
|
||||||
|
r1->fa_eof[0], r1->fa_eof[1],
|
||||||
|
r1->fa_eofb);
|
||||||
|
if (readlk(r1->ulnk))
|
||||||
|
{
|
||||||
|
r2 = use(ufdrms2,k);
|
||||||
|
printf (" %03o %03o %06o %06o",
|
||||||
|
r2->fa_bkt, r2->fa_hsz,
|
||||||
|
r2->fa_msz, r2->fa_ext);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dolist (int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
{
|
||||||
|
argv[0] = "[*,*]";
|
||||||
|
argc = 1;
|
||||||
|
}
|
||||||
|
tfiles = 0;
|
||||||
|
tblocks = 0;
|
||||||
|
curproj = 0;
|
||||||
|
curprog = 0;
|
||||||
|
rmount (); /* mount the disk */
|
||||||
|
sw.query = NULL; /* force -query to be absent */
|
||||||
|
dofiles (argc, argv, dolistfqb, NULLISWILD);
|
||||||
|
if (tfiles != 0)
|
||||||
|
{
|
||||||
|
if (sw.bswitch != NULL)
|
||||||
|
{
|
||||||
|
if (sw.narrow == NULL && files % COLUMNS != 0)
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sw.summary == NULL)
|
||||||
|
printf (" Total of %ld blocks in %ld files\n",
|
||||||
|
blocks, files);
|
||||||
|
else printf (" Total of %ld blocks in %ld files in [%d,%d]\n",
|
||||||
|
blocks, files, curproj, curprog);
|
||||||
|
if (tfiles != files)
|
||||||
|
printf (" Grand total of %ld blocks in %ld files\n",
|
||||||
|
tblocks, tfiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rumount (); /* done with disk */
|
||||||
|
}
|
||||||
|
|
||||||
1
extracters/rstsflx/dolist.h
Normal file
1
extracters/rstsflx/dolist.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern void dolist(int argc , char ** argv);
|
||||||
54
extracters/rstsflx/doprot.c
Normal file
54
extracters/rstsflx/doprot.c
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/* handler for the "prot" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "doprot.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
void doprot2 (firqb *f)
|
||||||
|
{
|
||||||
|
ufdne *n;
|
||||||
|
|
||||||
|
readlk (f->nlink); /* read the NE for this file */
|
||||||
|
n = use(ufdne,k);
|
||||||
|
if (sw.prot != NULL) {
|
||||||
|
n->ustat |= us_nok; /* set no-kill bit */
|
||||||
|
if (sw.verbose != NULL) {
|
||||||
|
printcurname (f);
|
||||||
|
printf (" marked no-delete\n");
|
||||||
|
}
|
||||||
|
} else if (sw.unprot != NULL) {
|
||||||
|
n->ustat &= ~us_nok; /* clear no-kill bit */
|
||||||
|
if (sw.verbose != NULL) {
|
||||||
|
printcurname (f);
|
||||||
|
printf (" no longer marked marked no-delete\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((f->flags & f_prot) == 0) {
|
||||||
|
printf ("File ");
|
||||||
|
printcurname (f);
|
||||||
|
printf (" not changed, no protection specified\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
n->uprot = f->newprot;
|
||||||
|
if (sw.verbose != NULL) {
|
||||||
|
printf ("File ");
|
||||||
|
printcurname (f);
|
||||||
|
printf (" protection changed to <%d>\n", f->newprot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MARKF;
|
||||||
|
upddlw (f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doprot (int argc, char **argv)
|
||||||
|
{
|
||||||
|
rmountrw (); /* mount the disk */
|
||||||
|
dofiles (argc, argv, doprot2, NOTNULL);
|
||||||
|
rumountrw (); /* done with disk */
|
||||||
|
}
|
||||||
4
extracters/rstsflx/doprot.h
Normal file
4
extracters/rstsflx/doprot.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
extern void doprot2(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void doprot(int argc , char ** argv);
|
||||||
301
extracters/rstsflx/doput.c
Normal file
301
extracters/rstsflx/doput.c
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
/* handler for "put" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "doput.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *ext;
|
||||||
|
const char *rts;
|
||||||
|
} rtsent;
|
||||||
|
|
||||||
|
const rtsent rtstbl[] = {
|
||||||
|
{ "tsk", "...rsx" },
|
||||||
|
{ "sav", "rt11 " },
|
||||||
|
{ "4th", "forth " },
|
||||||
|
{ "bas", "basic " },
|
||||||
|
{ "tec", "teco " },
|
||||||
|
{ "com", "dcl " },
|
||||||
|
{ "alc", "algol " },
|
||||||
|
{ "wps", "wpsedt" },
|
||||||
|
{ NULL, NULL }};
|
||||||
|
|
||||||
|
/* check for extension match against runtime system runnable extensions.
|
||||||
|
* Return TRUE and rts name if a match, false and zeroes otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int checkrts (firqb *f, word16 *rtsname)
|
||||||
|
{
|
||||||
|
const rtsent *r;
|
||||||
|
|
||||||
|
for (r = rtstbl; r->ext != NULL; r++) {
|
||||||
|
if (strncmp (&(f->cname[7]), r->ext, 3) == 0) {
|
||||||
|
cvtnametor50 (r->rts, rtsname);
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rtsname[0] = rtsname[1] = 0;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void putname (void *name) {
|
||||||
|
fputs ((char *) name, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doput (int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *p, *pp;
|
||||||
|
FILE *inf;
|
||||||
|
long newsize;
|
||||||
|
int newclu;
|
||||||
|
word16 rtsname[2];
|
||||||
|
char *inspec, *outspec;
|
||||||
|
firqb outf;
|
||||||
|
firqb tmpf;
|
||||||
|
long savelbn;
|
||||||
|
int arg, j;
|
||||||
|
const char *mode;
|
||||||
|
int binmode;
|
||||||
|
char answer;
|
||||||
|
long bytes, totalbytes, files, insize;
|
||||||
|
word dirne;
|
||||||
|
byte defprot;
|
||||||
|
struct stat sbuf;
|
||||||
|
ufdrms1 rms1;
|
||||||
|
ufdrms1 *a1;
|
||||||
|
ufdrms2 rms2;
|
||||||
|
ufdrms2 *a2;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf ("Usage: %s put file... dest\n", progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
outspec = argv[--argc];
|
||||||
|
if (sw.size == NULL) newsize = 0;
|
||||||
|
else {
|
||||||
|
newsize = strtoul (sw.size, &p, 10);
|
||||||
|
if (*p != '\0') {
|
||||||
|
printf ("Invalid size %s\n", sw.size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.contig == NULL && newsize != 0) {
|
||||||
|
newsize = 0;
|
||||||
|
printf ("-size switch ignored, -contiguous not specified\n");
|
||||||
|
}
|
||||||
|
if (!parse (outspec, &outf)) {
|
||||||
|
printf ("Invalid destination spec %s\n", outspec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((outf.flags & f_name) == 0) {
|
||||||
|
for (j = 0; j < 6; j++) outf.name[j] = '?';
|
||||||
|
outf.flags |= f_name | f_namw;
|
||||||
|
}
|
||||||
|
if ((outf.flags & f_ext) == 0) {
|
||||||
|
outf.name[7] = '?';
|
||||||
|
outf.name[8] = '?';
|
||||||
|
outf.name[9] = '?';
|
||||||
|
outf.flags |= f_ext | f_extw;
|
||||||
|
}
|
||||||
|
if (sw.tree == NULL && (outf.flags & f_ppnw) != 0) {
|
||||||
|
printf ("Wildcard PPN without -tree not allowed in %s\n",
|
||||||
|
outspec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rmountrw (); /* mount disk R/W */
|
||||||
|
if (sw.clusiz == NULL) newclu = pcs;
|
||||||
|
else {
|
||||||
|
newclu = strtol (sw.clusiz, &p, 10);
|
||||||
|
if (newclu < 0) {
|
||||||
|
newclu = -newclu;
|
||||||
|
if (newclu < pcs) newclu = pcs;
|
||||||
|
}
|
||||||
|
if (*p != '\0' || newclu < pcs || newclu > 128 ||
|
||||||
|
(newclu & (-newclu)) != newclu) {
|
||||||
|
rumountrw (); /* remember to dismount */
|
||||||
|
printf ("Invalid clustersize %s\n", sw.clusiz);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.tree == NULL) {
|
||||||
|
if ((dirne = initfilescan (&outf, gfdatrtbl)) == 0) {
|
||||||
|
rumountrw (); /* remember to dismount */
|
||||||
|
printf ("Account does not exist %s\n", outspec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
readlk (dirne);
|
||||||
|
if ((savelbn = allocufd (dirne, &outf)) == 0) { /* allocate UFD if needed */
|
||||||
|
rumountrw (); /* remember to dismount */
|
||||||
|
printf ("No room to allocate UFD\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
files = 0;
|
||||||
|
totalbytes = 0;
|
||||||
|
for (arg = 0; arg < argc; arg++) {
|
||||||
|
inspec = argv[arg]; /* pick up a name */
|
||||||
|
mergename (inspec, &outf, sw.tree != NULL);
|
||||||
|
/* construct output name */
|
||||||
|
if (outf.cproj == 0 && outf.cprog == 0) {
|
||||||
|
printf ("Bad directory spec from input filespec %s\n", inspec);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
answer = doquery (putname, inspec);
|
||||||
|
if (answer == 'q') break;
|
||||||
|
if (answer == 'n') continue;
|
||||||
|
if (sw.ascii != NULL) binmode = FALSE;
|
||||||
|
else if (sw.bswitch != NULL) binmode = TRUE;
|
||||||
|
else binmode = !textfile (outf.cname);
|
||||||
|
if (binmode) mode = "rb";
|
||||||
|
else mode = "r";
|
||||||
|
if (sw.debug != NULL) printf ("put mode %s\n", mode);
|
||||||
|
if ((inf = fopen (inspec, mode)) == NULL) {
|
||||||
|
printf ("Can't open %s\n", inspec);
|
||||||
|
perror (progname);
|
||||||
|
continue; /* skip this one */
|
||||||
|
}
|
||||||
|
if (fstat (fileno(inf), &sbuf)) { /* get info about input file */
|
||||||
|
printf ("Can't stat input file %s", inspec);
|
||||||
|
perror (progname);
|
||||||
|
fclose (inf); /* close input */
|
||||||
|
continue; /* and carry on */
|
||||||
|
}
|
||||||
|
insize = UP(sbuf.st_size,BLKSIZE) / BLKSIZE;
|
||||||
|
if (sw.tree != NULL) {
|
||||||
|
memcpy (&tmpf, &outf, sizeof (firqb));
|
||||||
|
tmpf.proj = tmpf.cproj;
|
||||||
|
tmpf.prog = tmpf.cprog;
|
||||||
|
dirne = initfilescan (&tmpf, gfdatrtbl); /* does PPN exist yet? */
|
||||||
|
if (dirne == 0) {
|
||||||
|
if (!makedir (&outf, pcs)) {
|
||||||
|
printf ("Cannot create PPN [%d,%d]\n",
|
||||||
|
outf.cproj, outf.cprog);
|
||||||
|
fclose (inf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (plevel > RDS0) {
|
||||||
|
fbread (curgfd + gfdatrtbl);
|
||||||
|
dirne = fibufw[outf.cprog];
|
||||||
|
readlktbl (dirne);
|
||||||
|
} else {
|
||||||
|
dirne = prevppnlink;
|
||||||
|
readlk (dirne);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((savelbn = allocufd (dirne, &outf)) == 0) {
|
||||||
|
printf ("No room to allocate UFD [%d,%d]\n",
|
||||||
|
outf.cproj, outf.cprog);
|
||||||
|
fclose (inf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fbread (savelbn); /* read output directory */
|
||||||
|
readlk2 (0); /* read UFD label */
|
||||||
|
prevlink = 0; /* start there */
|
||||||
|
nextlink = use(ufdlabel,0)->ulnk; /* and initialize scan */
|
||||||
|
memcpy (&tmpf, &outf, sizeof (firqb));
|
||||||
|
memcpy (tmpf.name, outf.cname, NAMELEN);
|
||||||
|
if (nextfileindir (&tmpf)) { /* file exists... */
|
||||||
|
if (protfile (&tmpf)) {
|
||||||
|
fclose (inf); /* protected file, skip */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sw.prot != NULL) {
|
||||||
|
printf ("File ");
|
||||||
|
printcurname (&tmpf);
|
||||||
|
printf (" exist, not replaced\n");
|
||||||
|
fclose (inf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
delfile (&tmpf); /* now really delete the file */
|
||||||
|
fbread (savelbn); /* read output directory */
|
||||||
|
readlk2 (0); /* read UFD label */
|
||||||
|
prevlink = 0; /* start there */
|
||||||
|
nextlink = use(ufdlabel,0)->ulnk; /* and initialize scan */
|
||||||
|
memcpy (tmpf.name, outf.cname, NAMELEN);
|
||||||
|
nextfileindir (&tmpf); /* find end of directory */
|
||||||
|
}
|
||||||
|
outf.clusiz = newclu;
|
||||||
|
if (sw.contig == 0) outf.size = 0;
|
||||||
|
else {
|
||||||
|
if (newsize == 0) outf.size = insize;
|
||||||
|
else outf.size = newsize;
|
||||||
|
}
|
||||||
|
defprot = 60; /* default not runnable */
|
||||||
|
if (checkrts (&outf, rtsname)) {
|
||||||
|
if (newsize >> 16) { /* if large file */
|
||||||
|
printf ("warning: can't set rts for large file ");
|
||||||
|
printcurname (&outf);
|
||||||
|
outf.newprot &= ~up_run; /* never runnable */
|
||||||
|
} else defprot = 124; /* default is now runnable */
|
||||||
|
}
|
||||||
|
if ((outf.flags & f_prot) == 0) outf.newprot = defprot;
|
||||||
|
if (outf.size) outf.stat = us_nox;
|
||||||
|
else outf.stat = 0;
|
||||||
|
a1 = NULL; /* assume no attributes */
|
||||||
|
a2 = NULL;
|
||||||
|
memset (&rms1, 0, sizeof(rms1)); /* and clear them in case */
|
||||||
|
memset (&rms2, 0, sizeof(rms2));
|
||||||
|
if (sw.rmsvar != NULL || sw.rmsfix != NULL ||
|
||||||
|
sw.rmsstm != NULL) {
|
||||||
|
a1 = &rms1;
|
||||||
|
if (sw.rmsvar != NULL) {
|
||||||
|
a1->fa_typ = rf_var | fo_seq;
|
||||||
|
a2 = &rms2;
|
||||||
|
memset (&rms2, 0, sizeof(rms2));
|
||||||
|
a2->fa_msz = 512; /* dummy value */
|
||||||
|
}
|
||||||
|
if (sw.rmsstm != NULL) a1->fa_typ = rf_stm | fo_seq;
|
||||||
|
if (sw.rmsfix != NULL) {
|
||||||
|
a1->fa_typ = rf_fix | fo_seq;
|
||||||
|
a2 = &rms2;
|
||||||
|
a1->fa_rsz = strtoul (sw.rmsfix, &pp, 10);
|
||||||
|
if (*pp != '\0') a1->fa_rsz = 0;
|
||||||
|
a2->fa_msz = a1->fa_rsz;
|
||||||
|
insize = (insize / (a1->fa_rsz / BLKSIZE)) *
|
||||||
|
(a1->fa_rsz / BLKSIZE);
|
||||||
|
insize++;
|
||||||
|
}
|
||||||
|
a1->fa_siz[0] = a1->fa_eof[0] = insize >> 16;
|
||||||
|
a1->fa_siz[1] = a1->fa_eof[1] = insize & 0xffff;
|
||||||
|
a1->fa_eofb = 0;
|
||||||
|
}
|
||||||
|
if (crefile (&outf, rtsname, a1, a2)) {
|
||||||
|
bytes = putfile (inf, &outf, binmode);
|
||||||
|
if (bytes < 0 || (bytes == 0 && outf.size != 0)) {
|
||||||
|
bytes = -bytes;
|
||||||
|
printf ("Failure copying %s to ", inspec);
|
||||||
|
printcurname (&outf);
|
||||||
|
printf (" -- %ld bytes copied in ", bytes);
|
||||||
|
if (binmode) printf ("block mode\n");
|
||||||
|
else printf ("line mode\n");
|
||||||
|
} else if (sw.verbose) {
|
||||||
|
printf ("%s =>> ", inspec);
|
||||||
|
printcurname (&outf);
|
||||||
|
printf (" (%ld bytes) in ", bytes);
|
||||||
|
if (binmode) printf ("block mode\n");
|
||||||
|
else printf ("line mode\n");
|
||||||
|
}
|
||||||
|
files++;
|
||||||
|
totalbytes += bytes;
|
||||||
|
} else {
|
||||||
|
printf ("No room to create file ");
|
||||||
|
printcurname (&outf);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
fclose (inf);
|
||||||
|
}
|
||||||
|
if (sw.verbose != NULL)
|
||||||
|
printf ("Total files: %ld, total bytes: %ld\n", files, totalbytes);
|
||||||
|
rumountrw (); /* done with R/W disk */
|
||||||
|
}
|
||||||
1
extracters/rstsflx/doput.h
Normal file
1
extracters/rstsflx/doput.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
extern void doput(int argc , char ** argv);
|
||||||
96
extracters/rstsflx/dorename.c
Normal file
96
extracters/rstsflx/dorename.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/* handler for the "rename" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "dorename.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
firqb newf; /* new name */
|
||||||
|
|
||||||
|
void renamefile (firqb *f)
|
||||||
|
{
|
||||||
|
ufdne *n;
|
||||||
|
firqb tmpf;
|
||||||
|
word saveprev, savenext;
|
||||||
|
|
||||||
|
if (protfile (f)) return; /* quit if file protected */
|
||||||
|
mergename (f->cname, &newf, FALSE);
|
||||||
|
readlk2 (0); /* read UFD label */
|
||||||
|
saveprev = prevlink; /* save current scan pointers */
|
||||||
|
savenext = nextlink;
|
||||||
|
prevlink = 0; /* start there */
|
||||||
|
nextlink = use(ufdlabel,0)->ulnk; /* and initialize scan */
|
||||||
|
memcpy (&tmpf, &newf, sizeof (firqb));
|
||||||
|
memcpy (tmpf.name, newf.cname, NAMELEN);
|
||||||
|
if (nextfileindir (&tmpf)) /* file exists... */
|
||||||
|
{
|
||||||
|
if (f->nlink == tmpf.nlink)
|
||||||
|
{
|
||||||
|
printf ("New name matches old name ");
|
||||||
|
printcurname (f);
|
||||||
|
printf ("\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (protfile (&tmpf)) return; /* protected file, skip */
|
||||||
|
if (sw.replace == NULL)
|
||||||
|
{
|
||||||
|
printf ("Cannot rename ");
|
||||||
|
printcurname (f);
|
||||||
|
printf (" to %s -- file already exists\n", tmpf.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delfile (&tmpf); /* now really delete the file */
|
||||||
|
}
|
||||||
|
prevlink = saveprev; /* restore pointers */
|
||||||
|
nextlink = savenext;
|
||||||
|
readlk (f->nlink); /* read the NE */
|
||||||
|
n = use(ufdne,k);
|
||||||
|
cvtnameexttor50 (newf.cname, n->unam); /* write new RAD50 name into NE */
|
||||||
|
MARKF;
|
||||||
|
upddlw (f);
|
||||||
|
if (sw.verbose != NULL)
|
||||||
|
{
|
||||||
|
printcurname (f);
|
||||||
|
printf (" renamed to %s\n", newf.cname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dorename (int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *newname;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (--argc < 1)
|
||||||
|
{
|
||||||
|
printf ("Usage: %s rename file ... newname\n", progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newf.flags = 0; /* clear parse flags */
|
||||||
|
newname = argv[argc]; /* save name pointer */
|
||||||
|
if (*parsenameext (newname, &newf) != '\0')
|
||||||
|
{
|
||||||
|
printf ("Invalid new name %s\n", newname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((newf.flags & f_name) == 0)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 6; j++) newf.name[j] = '?';
|
||||||
|
newf.flags |= f_name | f_namw;
|
||||||
|
}
|
||||||
|
if ((newf.flags & f_ext) == 0)
|
||||||
|
{
|
||||||
|
newf.name[7] = '?';
|
||||||
|
newf.name[8] = '?';
|
||||||
|
newf.name[9] = '?';
|
||||||
|
newf.flags |= f_ext | f_extw;
|
||||||
|
}
|
||||||
|
rmountrw (); /* mount the disk */
|
||||||
|
dofiles (argc, argv, renamefile, NOTNULL);
|
||||||
|
rumountrw (); /* done with disk */
|
||||||
|
}
|
||||||
4
extracters/rstsflx/dorename.h
Normal file
4
extracters/rstsflx/dorename.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
extern void renamefile(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void dorename(int argc , char ** argv);
|
||||||
56
extracters/rstsflx/dorts.c
Normal file
56
extracters/rstsflx/dorts.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* handler for the "rts" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "dorts.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
char *rtsname; /* new rts in ascii */
|
||||||
|
word16 rtsr50[2]; /* and in rad50 */
|
||||||
|
|
||||||
|
void rtsfile (firqb *f)
|
||||||
|
{
|
||||||
|
ufdae *a;
|
||||||
|
|
||||||
|
if (protfile (f)) return; /* quit if file protected */
|
||||||
|
readlk (f->alink); /* read the AE */
|
||||||
|
a = use(ufdae,k);
|
||||||
|
if (a->urts[0] == 0 && a->urts[1] != 0) {
|
||||||
|
printcurname (f);
|
||||||
|
printf (" is a large file\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
a->urts[0] = rtsr50[0];
|
||||||
|
a->urts[1] = rtsr50[1];
|
||||||
|
MARKF;
|
||||||
|
upddlw (f);
|
||||||
|
if (sw.verbose != NULL) {
|
||||||
|
printcurname (f);
|
||||||
|
printf (" rts changed to %s\n", rtsname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dorts (int argc, char **argv)
|
||||||
|
{
|
||||||
|
firqb rtsf;
|
||||||
|
|
||||||
|
if (--argc < 1) {
|
||||||
|
printf ("Usage: %s rts file ... rts\n", progname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rtsf.flags = 0; /* clear parse flags */
|
||||||
|
rtsname = argv[argc]; /* save name pointer */
|
||||||
|
if (*parsename (rtsname, &rtsf) != '\0' || rtsf.flags != f_name) {
|
||||||
|
printf ("Invalid rts name %s\n", rtsname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cvtnametor50 (rtsf.name, rtsr50);
|
||||||
|
rmountrw (); /* mount the disk */
|
||||||
|
dofiles (argc, argv, rtsfile, NOTNULL);
|
||||||
|
rumountrw (); /* done with disk */
|
||||||
|
}
|
||||||
4
extracters/rstsflx/dorts.h
Normal file
4
extracters/rstsflx/dorts.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
extern void rtsfile(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void dorts(int argc , char ** argv);
|
||||||
337
extracters/rstsflx/dosabsio.c
Normal file
337
extracters/rstsflx/dosabsio.c
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
/* absread and abswrite services for use with DJGPP GNU C implementation
|
||||||
|
*
|
||||||
|
* Paul Koning 94.10.16
|
||||||
|
* 94.11.18 added bios i/o
|
||||||
|
* 94.11.21 dos i/o for hard disk, bios i/o for floppy
|
||||||
|
* 94.12.19 add retry for bios I/O
|
||||||
|
* 95.01.05 update for generalized abs i/o in flx
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bios.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <go32.h>
|
||||||
|
#include <dpmi.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "absio.h"
|
||||||
|
|
||||||
|
#define tb _go32_info_block.linear_address_of_transfer_buffer
|
||||||
|
|
||||||
|
#define BIOSBUF (_go32_info_block.size_of_transfer_buffer)
|
||||||
|
/* size of djgpp bios disk I/O buffer */
|
||||||
|
#define BIOSMAX (18 * BLKSIZE) /* max size in biosdisk() call */
|
||||||
|
#define BIOSRESET 0 /* error reset */
|
||||||
|
#define BIOSREAD 2 /* bios disk read function code */
|
||||||
|
#define BIOSWRITE 3 /* bios disk write function code */
|
||||||
|
#define BIOSTRIES 4 /* retry count */
|
||||||
|
#define ABSREAD 0x25 /* abs read int code */
|
||||||
|
#define ABSWRITE 0x26 /* abs write int code */
|
||||||
|
#define BIOS_DATA_SEG 0x0040 /* BIOS data segment number */
|
||||||
|
#define BIOS_DSK_STATE 0x0090 /* offset to drive 0 media state */
|
||||||
|
#define DISK_STATE ((BIOS_DATA_SEG << 4) + BIOS_DSK_STATE)
|
||||||
|
|
||||||
|
#define BIOS_DSK_360K 0x74 /* 360kb media established */
|
||||||
|
#define BIOS_DSK_RX50 0x54 /* RX50 media established in drive */
|
||||||
|
/* (same as 360kb except single steps */
|
||||||
|
/* for 96 tpi media) */
|
||||||
|
|
||||||
|
static int secsize = 0;
|
||||||
|
static int param_segment = 0;
|
||||||
|
static int rx_segment;
|
||||||
|
static _go32_dpmi_seginfo oldvec;
|
||||||
|
static _go32_dpmi_seginfo rx50table_vec;
|
||||||
|
static unsigned short int dosparam[5];
|
||||||
|
static int rxflag = 0; /* set if accessing 5.25 inch floppy */
|
||||||
|
static int gdrive = -1; /* drive to which geometry data applies */
|
||||||
|
static int drive; /* disk unit number currently open */
|
||||||
|
static int sectors, heads, cylinders, drives;
|
||||||
|
static _go32_dpmi_seginfo param_info;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disk parameter table for RX50 floppies in 1.2MB drive
|
||||||
|
* (set INT 1Eh vector to point to this)
|
||||||
|
*/
|
||||||
|
static byte dparm[] = { 0xDF,0x02, /* "specify" cmd bytes */
|
||||||
|
0x25, /* motor turn-on time */
|
||||||
|
2,10, /* 512 b/s, 10 sec/tk */
|
||||||
|
20, /* gap length */
|
||||||
|
-1, /* max transfer */
|
||||||
|
24, /* gap length (format) */
|
||||||
|
0xE5, /* fill byte (format) */
|
||||||
|
15, /* head settle time (ms) */
|
||||||
|
8 }; /* motor start time (1/8 sec) */
|
||||||
|
|
||||||
|
/* The param_buffer is used for two things:
|
||||||
|
* 1. to hold the dos abs disk I/O parameter block
|
||||||
|
* 2. to hold the rx50 disk parameter table data
|
||||||
|
* We put both into the same buffer, in separate segments.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void free_param_buffer()
|
||||||
|
{
|
||||||
|
_go32_dpmi_free_dos_memory(¶m_info);
|
||||||
|
param_segment = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alloc_param_buffer()
|
||||||
|
{
|
||||||
|
if (param_segment) return;
|
||||||
|
param_info.size = (UP(sizeof(param_info),16) +
|
||||||
|
UP(sizeof(dparm),16)) / 16;
|
||||||
|
if (_go32_dpmi_allocate_dos_memory(¶m_info)) {
|
||||||
|
param_segment = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
param_segment = param_info.rm_segment;
|
||||||
|
rx_segment = param_segment + UP(sizeof(param_info),16) / 16;
|
||||||
|
dosmemput(dparm, sizeof(dparm), rx_segment << 4);
|
||||||
|
rx50table_vec.rm_segment = rx_segment;
|
||||||
|
rx50table_vec.rm_offset = 0;
|
||||||
|
atexit(free_param_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert dos style drive number to bios style number */
|
||||||
|
|
||||||
|
static int biosdrive (int drive)
|
||||||
|
{
|
||||||
|
if (drive < 3) return (drive - 1);
|
||||||
|
else return ((drive - 3) + 0x80); /* need to do partitions */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do bios I/O with retries */
|
||||||
|
|
||||||
|
static int biosdiskr (int func, int drive, int track, int cyl,
|
||||||
|
int sec, int count, void *buffer)
|
||||||
|
{
|
||||||
|
int tries, status;
|
||||||
|
|
||||||
|
for (tries = 0; tries < BIOSTRIES; tries++) {
|
||||||
|
status = biosdisk (func, biosdrive (drive), track, cyl,
|
||||||
|
sec, count, buffer);
|
||||||
|
if (status == 0) break;
|
||||||
|
|
||||||
|
/* strictly speaking one should do error classification
|
||||||
|
* at this point...
|
||||||
|
*/
|
||||||
|
biosdisk (BIOSRESET, biosdrive (drive), 0, 0, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
return (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getgeom (int drive)
|
||||||
|
{
|
||||||
|
byte status[4];
|
||||||
|
|
||||||
|
gdrive = drive;
|
||||||
|
biosdisk (8, biosdrive (drive), 0, 0, 0, 1, status);
|
||||||
|
heads = status[3] + 1;
|
||||||
|
drives = status[2];
|
||||||
|
cylinders = status[1] + ((status[0] >> 6) << 8) + 1;
|
||||||
|
sectors = status[0] & 0x3f;
|
||||||
|
if (status[0] == 15 && status[1] == 79 & status[3] == 1)
|
||||||
|
rxflag = 1;
|
||||||
|
else rxflag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert block number to cylinder, head, sector for RT11-RX50.
|
||||||
|
* This is different for RT11 than for Rainbow DOS:
|
||||||
|
* For DOS, for cylinders 2 through 79, the sectors are interleaved 2:1.
|
||||||
|
* (DOS capability is not supported in this RT11 version).
|
||||||
|
* For RT11, all sectors are interleaved 2:1, and each subsequent
|
||||||
|
* track has the first logical block offset by 2 more sectors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void makechs_rx50 (int block, int *trk, int *sec)
|
||||||
|
{
|
||||||
|
int t, s;
|
||||||
|
|
||||||
|
t = block / 10;
|
||||||
|
s = block % 10 + 1;
|
||||||
|
if (s < 6) s = (s - 1) * 2 + 1;
|
||||||
|
else s = (s - 5) * 2;
|
||||||
|
s += t * 2;
|
||||||
|
while (s > 10) s -= 10;
|
||||||
|
t++;
|
||||||
|
if (t == 80) t = 0; /* wrap around last 10 blocks */
|
||||||
|
*trk = t;
|
||||||
|
*sec = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do single block disk I/O to DEC RX50 floppy */
|
||||||
|
static int rx50io (int func, int drive, int dsksec, void *buffer)
|
||||||
|
{
|
||||||
|
byte oldstate;
|
||||||
|
byte newstate = BIOS_DSK_RX50;
|
||||||
|
int cyl, sec;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
alloc_param_buffer();
|
||||||
|
|
||||||
|
/* save old state and set up for RX50 I/O */
|
||||||
|
_go32_dpmi_get_real_mode_interrupt_vector (0x1E, &oldvec);
|
||||||
|
_go32_dpmi_set_real_mode_interrupt_vector (0x1E, &rx50table_vec);
|
||||||
|
#ifdef NOT
|
||||||
|
dosmemget (DISK_STATE, 1, &oldstate);
|
||||||
|
dosmemput (&newstate, 1, DISK_STATE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
makechs_rx50 (dsksec, &cyl, &sec);
|
||||||
|
status = biosdiskr (func, drive, 0, cyl, sec, 1, buffer);
|
||||||
|
|
||||||
|
/* restore BIOS state as it was on entry */
|
||||||
|
_go32_dpmi_set_real_mode_interrupt_vector (0x1E, &oldvec);
|
||||||
|
#ifdef NOT
|
||||||
|
dosmemput (&oldstate, 1, DISK_STATE);
|
||||||
|
#endif
|
||||||
|
return (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do bios disk I/O call
|
||||||
|
* if this is a 5.25" floppy, we do the required magic to read it as
|
||||||
|
* a DEC RX50 format floppy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int biosio (int func, int drive, int dsksec, int count, void *buffer)
|
||||||
|
{
|
||||||
|
int track, sec, cyl;
|
||||||
|
int tcount, status;
|
||||||
|
|
||||||
|
if (drive != gdrive) getgeom (drive);
|
||||||
|
while (count) {
|
||||||
|
if (rxflag) {
|
||||||
|
tcount = BLKSIZE;
|
||||||
|
status = rx50io (func, drive, dsksec, buffer);
|
||||||
|
} else {
|
||||||
|
tcount = count;
|
||||||
|
if (tcount > BIOSMAX) tcount = BIOSMAX;
|
||||||
|
sec = dsksec % sectors;
|
||||||
|
if ((sectors - sec) * BLKSIZE < tcount)
|
||||||
|
tcount = (sectors - sec) * BLKSIZE;
|
||||||
|
sec++; /* weird 1-based numbering */
|
||||||
|
track = (dsksec / sectors) % heads;
|
||||||
|
cyl = dsksec / (sectors * heads);
|
||||||
|
status = biosdiskr (func, drive, track, cyl,
|
||||||
|
sec, tcount / BLKSIZE, buffer);
|
||||||
|
}
|
||||||
|
if (status) return (status);
|
||||||
|
count -= tcount;
|
||||||
|
buffer += tcount;
|
||||||
|
dsksec += (tcount / BLKSIZE);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do absolute dos disk read/write
|
||||||
|
* arguments:
|
||||||
|
* function code (0x25 = read, 0x26 = write)
|
||||||
|
* drive number (1 = a:, etc)
|
||||||
|
* starting sector number
|
||||||
|
* byte count (must be multiple of sector size)
|
||||||
|
* buffer pointer
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int dosio (int func, int drive, int sec, int count, void *buffer)
|
||||||
|
{
|
||||||
|
int bseg, bofs, xfer=0, before=0, tcount;
|
||||||
|
_go32_dpmi_registers r;
|
||||||
|
|
||||||
|
while (count) {
|
||||||
|
tcount = count;
|
||||||
|
if (tcount > BIOSBUF) tcount = BIOSBUF;
|
||||||
|
alloc_param_buffer();
|
||||||
|
dosparam[0] = sec & 0xffff;
|
||||||
|
dosparam[1] = sec >> 16;
|
||||||
|
dosparam[2] = (tcount / secsize) & 0xffff;
|
||||||
|
dosparam[3] = (unsigned int) tb & 15;
|
||||||
|
dosparam[4] = (unsigned int) tb >> 4;
|
||||||
|
dosmemput(dosparam, sizeof(dosparam), param_segment << 4);
|
||||||
|
if (func == ABSWRITE)
|
||||||
|
dosmemput(buffer, tcount, tb);
|
||||||
|
memset(&r, 0, sizeof(r));
|
||||||
|
r.h.al = drive - 1; /* 0-based numbering here */
|
||||||
|
r.x.ds = param_segment;
|
||||||
|
r.x.bx = 0;
|
||||||
|
r.x.cx = -1;
|
||||||
|
_go32_dpmi_simulate_int(func, &r);
|
||||||
|
if (func == ABSREAD)
|
||||||
|
dosmemget(tb, tcount, buffer);
|
||||||
|
if (r.x.flags & 1)
|
||||||
|
return (r.h.al);
|
||||||
|
count -= tcount;
|
||||||
|
buffer += tcount;
|
||||||
|
sec += (tcount / secsize);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return size of specified disk, in blocks. Saves sector size in a local
|
||||||
|
* static variable as a side effect. A flag is set if the disk is a
|
||||||
|
* 5.25 inch floppy.
|
||||||
|
* Note: this must be called before any abs I/O is done.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int disksize (int drive)
|
||||||
|
{
|
||||||
|
_go32_dpmi_registers r;
|
||||||
|
byte mid;
|
||||||
|
|
||||||
|
if (drive >= 3) { /* hard disk */
|
||||||
|
memset(&r, 0, sizeof(r));
|
||||||
|
r.h.ah = 0x1c;
|
||||||
|
r.h.dl = drive;
|
||||||
|
_go32_dpmi_simulate_int(0x21, &r);
|
||||||
|
secsize = r.x.cx;
|
||||||
|
return (r.h.al * r.x.dx * secsize / BLKSIZE);
|
||||||
|
} else {
|
||||||
|
getgeom (drive);
|
||||||
|
secsize = 512;
|
||||||
|
return (cylinders * heads * sectors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this routine is called to scan a supplied container file/device
|
||||||
|
* name. If the name refers to a real disk, then absflag is set
|
||||||
|
* and rsize is set to the device size. Otherwise, no action is taken.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void absname (const char *rname)
|
||||||
|
{
|
||||||
|
if (rname[strlen(rname) - 1] == ':') { /* device name alone */
|
||||||
|
absflag = TRUE;
|
||||||
|
drive = tolower (rname[0]) - 'a' + 1; /* set drive number */
|
||||||
|
rsize = disksize (drive);
|
||||||
|
if (sw.debug != NULL)
|
||||||
|
printf ("disk size for drive %d is %d\n", drive, rsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int absopen (const char *rname, const char *mode)
|
||||||
|
{
|
||||||
|
return (0); /* always ok, nothing to do */
|
||||||
|
}
|
||||||
|
|
||||||
|
void absseek (int block) { } /* nothing to do */
|
||||||
|
|
||||||
|
void absclose () { } /* nothing to do */
|
||||||
|
|
||||||
|
int absread (int sec, int count, void *buffer)
|
||||||
|
{
|
||||||
|
if (drive >= 3) /* hard disk */
|
||||||
|
return (dosio (ABSREAD, drive, sec, count, buffer));
|
||||||
|
else
|
||||||
|
return (biosio (BIOSREAD, drive, sec, count, buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
int abswrite (int sec, int count, void *buffer)
|
||||||
|
{
|
||||||
|
#ifdef NOT_YET
|
||||||
|
if (drive >= 3) /* hard disk */
|
||||||
|
return (dosio (ABSWRITE, drive, sec, count, buffer));
|
||||||
|
else
|
||||||
|
return (biosio (BIOSWRITE, drive, sec, count, buffer));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
3
extracters/rstsflx/dosabsio.h
Normal file
3
extracters/rstsflx/dosabsio.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
extern int absread (int drive, int sec, int count, void *buffer);
|
||||||
|
extern int abswrite (int drive, int sec, int count, void *buffer);
|
||||||
|
extern int disksize (int drive);
|
||||||
203
extracters/rstsflx/dosrxio.c
Normal file
203
extracters/rstsflx/dosrxio.c
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/* floppy disk I/O for DOS
|
||||||
|
*
|
||||||
|
* based on RXRTDVRA.ASM by Robert Morse and John Dudeck
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------
|
||||||
|
* IBM ROM BIOS Definitions
|
||||||
|
* ---------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DKOP_RUPT 013h /* interrupt to call ROM BIOS */
|
||||||
|
#define DKOP_RESET 000h /* reset controller */
|
||||||
|
#define DKOP_STATUS 001h /* read status from last operation */
|
||||||
|
#define DKOP_READ 002h /* read sectors */
|
||||||
|
#define DKOP_WRITE 003h /* write sectors */
|
||||||
|
#define DKOP_VERIFY 004h /* verify sectors */
|
||||||
|
#define DKOP_CHANGE 016h /* test changed status */
|
||||||
|
#define DKOP_SETTYPE 017h /* set media type in drive */
|
||||||
|
|
||||||
|
#define DKST_TIMEOUT 080h /* drive not ready */
|
||||||
|
#define DKST_BADSEEK 040h /* seek failed */
|
||||||
|
#define DKST_BADNEC 020h /* NEC controller failed */
|
||||||
|
#define DKST_BADCRC 010h /* read CRC error */
|
||||||
|
#define DKST_BADDMA 009h /* attempt to DMA over 64K boundary */
|
||||||
|
#define DKST_OVERRUN 008h /* DMA overrun */
|
||||||
|
#define DKST_CHANGED 006h /* media changed */
|
||||||
|
#define DKST_RNF 004h /* sector not found */
|
||||||
|
#define DKST_WRPROT 003h /* write-protected diskette */
|
||||||
|
#define DKST_ADRMARK 002h /* address mark not found */
|
||||||
|
#define DKST_BADCMD 001h /* invalid command */
|
||||||
|
|
||||||
|
|
||||||
|
#define BIOS_DATA_SEG 0040h
|
||||||
|
|
||||||
|
/* #define BIOSDATA segment at BIOS_DATA_SEG /* BIOS data segment-- */
|
||||||
|
|
||||||
|
#define bios_dsk_state (*(byte *)(0x0090)) /* drive 0 media state */
|
||||||
|
|
||||||
|
#define BIOS_DSK_360K 074h /* 360kb media established */
|
||||||
|
#define BIOS_DSK_RX50 054h /* RX50 media established in drive */
|
||||||
|
/* (same as 360kb except single steps */
|
||||||
|
/* for 96 tpi media) */
|
||||||
|
|
||||||
|
/* Convert block number to cylinder, head, sector for RT11-RX50.
|
||||||
|
* This is different for RT11 than for Rainbow DOS:
|
||||||
|
* For DOS, for cylinders 2 through 79, the sectors are interleaved 2:1.
|
||||||
|
* (DOS capability is not supported in this RT11 version).
|
||||||
|
* For RT11, all sectors are interleaved 2:1, and each subsequent
|
||||||
|
* track has the first logical block offset by 2 more sectors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void makechs_rx50 (int block, int *trk, int *sec)
|
||||||
|
{
|
||||||
|
int t, s;
|
||||||
|
|
||||||
|
t = block / 10;
|
||||||
|
s = block % 10 + 1;
|
||||||
|
if (s < 6) s = (s - 1) * 2 + 1;
|
||||||
|
else s = (s - 5) * 2;
|
||||||
|
s += t * 2;
|
||||||
|
while (s > 10) s -= 10;
|
||||||
|
t++;
|
||||||
|
*trk = t;
|
||||||
|
*sec = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
;Common routine for read, write and verify.
|
||||||
|
;
|
||||||
|
;Given: AL = operation code
|
||||||
|
; ES:DI = pointer to IOP, which contains
|
||||||
|
; iop_block = starting block number
|
||||||
|
; iop_bufptr = starting buffer address
|
||||||
|
; iop_count = number of blocks
|
||||||
|
;Returns: AX = IOP error code
|
||||||
|
; xx_count = number of requested blocks NOT transferred
|
||||||
|
|
||||||
|
do_readwrite:
|
||||||
|
mov es:iop_rwvoloff[di], offset vol_name
|
||||||
|
mov es:iop_rwvolseg[di], cs
|
||||||
|
|
||||||
|
mov xx_oper, al ;save operation code
|
||||||
|
|
||||||
|
mov ax, es:iop_block[di] ;set starting block number
|
||||||
|
|
||||||
|
test ax, ax ;JRD check for negative
|
||||||
|
jge do_rw1 ;JRD
|
||||||
|
xor ax, ax ;JRD
|
||||||
|
do_rw1:
|
||||||
|
push si ;JRD
|
||||||
|
mov si, bpb_pointer ;JRD
|
||||||
|
cmp ax, bpb_totsects[si] ;JRD test for too big
|
||||||
|
jle do_rw2 ;JRD
|
||||||
|
mov ax, bpb_totsects[si] ;JRD limit to maximum
|
||||||
|
do_rw2:
|
||||||
|
pop si ;JRD
|
||||||
|
|
||||||
|
mov xx_block, ax
|
||||||
|
mov ax, es:iop_count[di] ;set block count
|
||||||
|
mov xx_count, ax
|
||||||
|
test ax, ax
|
||||||
|
jz dorw_success ; quit if 0 sectors to do
|
||||||
|
|
||||||
|
mov ax, es:iop_bufoff[di] ;set starting buffer offset
|
||||||
|
mov xx_offset, ax ; and segment
|
||||||
|
mov ax, es:iop_bufseg[di]
|
||||||
|
mov xx_seg, ax
|
||||||
|
|
||||||
|
dorw_loop:
|
||||||
|
mov xx_retries, 5 ;set retry counter
|
||||||
|
dorw_again:
|
||||||
|
mov ax, BIOS_DATA_SEG ;set diskette status to single
|
||||||
|
mov es, ax ; stepping for 96 tpi
|
||||||
|
mov es:bios_dsk_state, BIOS_DSK_RX50
|
||||||
|
|
||||||
|
mov ax, xx_block ;load block number
|
||||||
|
call makechs_rx50 ; and convert to CHS
|
||||||
|
mov dl, PHYS_DRIVE_0 ;set drive number
|
||||||
|
mov ah, xx_oper ;operation code
|
||||||
|
mov al, 1 ;transfer 1 sector
|
||||||
|
les bx, xx_buf ;set ES:BX to buffer address
|
||||||
|
int DKOP_RUPT ;invoke ROM BIOS to do it
|
||||||
|
mov xx_status, ah ; and save returned status
|
||||||
|
test ah, ah ;test for error
|
||||||
|
jnz dorw_error ; break loop on error
|
||||||
|
|
||||||
|
inc xx_block ;advance to next block
|
||||||
|
add xx_offset, PHYS_BLKSIZE ;advance buffer pointer
|
||||||
|
dec xx_count ;count blocks
|
||||||
|
jnz dorw_loop ; and continue until done
|
||||||
|
dorw_success:
|
||||||
|
xor ax, ax ;set no-error code
|
||||||
|
ret
|
||||||
|
;Analyze read/write errors and either make another attempt or
|
||||||
|
;set the error code and return.
|
||||||
|
|
||||||
|
dorw_error:
|
||||||
|
mov al, IOPST_NOTRDY
|
||||||
|
test ah, DKST_TIMEOUT
|
||||||
|
jnz dorw_giveup
|
||||||
|
|
||||||
|
mov al, IOPST_SEEK
|
||||||
|
test ah, DKST_BADSEEK
|
||||||
|
jnz dorw_retry
|
||||||
|
|
||||||
|
mov al, IOPST_IOERR
|
||||||
|
test ah, DKST_BADNEC
|
||||||
|
jnz dorw_retry
|
||||||
|
|
||||||
|
cmp ah, DKST_OVERRUN
|
||||||
|
je dorw_retry
|
||||||
|
|
||||||
|
mov al, IOPST_CRC
|
||||||
|
cmp ah, DKST_BADCRC
|
||||||
|
je dorw_retry
|
||||||
|
|
||||||
|
mov al, IOPST_BADCMD
|
||||||
|
cmp ah, DKST_BADDMA
|
||||||
|
je dorw_giveup
|
||||||
|
|
||||||
|
cmp ah, DKST_BADCMD
|
||||||
|
je dorw_giveup
|
||||||
|
|
||||||
|
mov al, IOPST_BADCHNG
|
||||||
|
cmp ah, DKST_CHANGED
|
||||||
|
jne dorw_nochange
|
||||||
|
cmp open_count, 0
|
||||||
|
jg dorw_giveup ;error if change with any files open
|
||||||
|
jmp short dorw_reset ; else do it again
|
||||||
|
dorw_nochange:
|
||||||
|
mov al, IOPST_RNF
|
||||||
|
cmp ah, DKST_RNF
|
||||||
|
je dorw_retry
|
||||||
|
|
||||||
|
mov al, IOPST_WRPROT
|
||||||
|
cmp ah, DKST_WRPROT
|
||||||
|
je dorw_giveup
|
||||||
|
|
||||||
|
mov al, IOPST_UNKMEDIA
|
||||||
|
cmp ah, DKST_ADRMARK
|
||||||
|
je dorw_retry
|
||||||
|
|
||||||
|
mov al, IOPST_IOERR
|
||||||
|
jmp short dorw_giveup
|
||||||
|
dorw_retry:
|
||||||
|
dec xx_retries ;count retries
|
||||||
|
jle dorw_giveup
|
||||||
|
dorw_reset:
|
||||||
|
mov ah, DKOP_RESET ;reset the disk controller
|
||||||
|
int DKOP_RUPT
|
||||||
|
jmp dorw_again ; and try again
|
||||||
|
dorw_giveup:
|
||||||
|
mov ah, high IOPST_ERR ;complete the driver error return code
|
||||||
|
ret
|
||||||
|
|
||||||
|
int rxread (int block, int size, void *buffer)
|
||||||
|
{
|
||||||
|
return (rxio (DKOP_READ, block, size, buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
int rxwrite (int block, int size, void *buffer)
|
||||||
|
{
|
||||||
|
return (rxio (DKOP_WRITE, block, size, buffer));
|
||||||
|
}
|
||||||
28
extracters/rstsflx/dotype.c
Normal file
28
extracters/rstsflx/dotype.c
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/* handler for the "type" command */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "dotype.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
|
||||||
|
void typefile (firqb *f)
|
||||||
|
{
|
||||||
|
if (sw.verbose != NULL) {
|
||||||
|
printf ("\n----- ");
|
||||||
|
printcurname (f);
|
||||||
|
printf (" -----\n");
|
||||||
|
}
|
||||||
|
getfile (stdout, f, FALSE); /* put it on stdout */
|
||||||
|
}
|
||||||
|
|
||||||
|
void dotype (int argc, char **argv)
|
||||||
|
{
|
||||||
|
rmount (); /* mount the disk */
|
||||||
|
dofiles (argc, argv, typefile, NOTNULL);
|
||||||
|
rumount (); /* done with disk */
|
||||||
|
}
|
||||||
4
extracters/rstsflx/dotype.h
Normal file
4
extracters/rstsflx/dotype.h
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
extern void typefile(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void dotype(int argc , char ** argv);
|
||||||
29
extracters/rstsflx/fdprm
Normal file
29
extracters/rstsflx/fdprm
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# /etc/fdprm - floppy disk parameter table
|
||||||
|
|
||||||
|
# Common disk formats. Names are of the form
|
||||||
|
# actual media capacity/maximum drive capacity
|
||||||
|
# (Note: although 5.25" HD drives can format disks at 1.44M, they're listed
|
||||||
|
# as 1200 because that's the common maximum size.)
|
||||||
|
|
||||||
|
# size sec/t hds trk stre gap rate spec1 fmt_gap
|
||||||
|
360/360 720 9 2 40 0 0x2A 0x02 0xDF 0x50
|
||||||
|
1200/1200 2400 15 2 80 0 0x1B 0x00 0xDF 0x54
|
||||||
|
360/720 720 9 2 40 1 0x2A 0x02 0xDF 0x50
|
||||||
|
720/720 1440 9 2 80 0 0x2A 0x02 0xDF 0x50
|
||||||
|
720/1440 1440 9 2 80 0 0x2A 0x02 0xDF 0x50
|
||||||
|
360/1200 720 9 2 40 1 0x23 0x01 0xDF 0x50
|
||||||
|
720/1200 1440 9 2 80 0 0x23 0x01 0xDF 0x50
|
||||||
|
1440/1440 2880 18 2 80 0 0x1B 0x00 0xCF 0x6C
|
||||||
|
|
||||||
|
# Non-standard disk formats:
|
||||||
|
|
||||||
|
# BEWARE: They're incomplete and possibly incorrect. The only reason why
|
||||||
|
# they are in this file is to show how such formats are added.
|
||||||
|
|
||||||
|
1440/1200 2880 18 2 80 0 ???? ???? ???? ???? # ?????
|
||||||
|
1680/1440 3360 21 2 80 0 0x0C 0x00 0xCF 0x6C # ?????
|
||||||
|
|
||||||
|
# Add user-specific formats here
|
||||||
|
cbm1581 1600 10 2 80 2 0x2A 0x02 0xDF 0x2E
|
||||||
|
800/720 1600 10 2 80 0 0x2A 0x02 0xDF 0x2E
|
||||||
|
rx50 800 10 1 80 0 0x23 0x01 0xDF 0x50
|
||||||
592
extracters/rstsflx/fileio.c
Normal file
592
extracters/rstsflx/fileio.c
Normal file
@@ -0,0 +1,592 @@
|
|||||||
|
/* subroutines to do rsts file (virtual block) I/O */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "fip.h"
|
||||||
|
|
||||||
|
long totalbytes; /* total bytes transferred for get/put */
|
||||||
|
long curvbn; /* current file vbn (0-based) */
|
||||||
|
word curre; /* link of current RE */
|
||||||
|
word lastre; /* and last one seen */
|
||||||
|
int curreoff; /* offset into current RE */
|
||||||
|
int cluoff; /* offset into current file cluster */
|
||||||
|
int dcnperfcs; /* fcs / dcs */
|
||||||
|
|
||||||
|
|
||||||
|
static int rmseof (firqb *f, char *recp, long iocount)
|
||||||
|
{
|
||||||
|
long curblk;
|
||||||
|
int curbyt;
|
||||||
|
|
||||||
|
curblk = curvbn + (recp - iobuf - iocount) / BLKSIZE;
|
||||||
|
curbyt = (recp - iobuf) % BLKSIZE;
|
||||||
|
if (curblk > f->eofblk) return (TRUE);
|
||||||
|
return (curblk == f->eofblk && curbyt >= f->eofbyte);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* in each of the following "get a record" routines (one for each record
|
||||||
|
* format defined for RMS-11) the arguments are:
|
||||||
|
* f pointer to firqb struct
|
||||||
|
* len pointer to record length return variable
|
||||||
|
* eor pointer to end of record return variable (flag)
|
||||||
|
* iocount amount of data in I/O buffer (from last seqio call)
|
||||||
|
*
|
||||||
|
* len is set to the length of the record or partial record returned.
|
||||||
|
* the pointer to the record is the return value of the function.
|
||||||
|
* eor is set true if a whole record was transferred, and false if only
|
||||||
|
* a partial record is returned. (If eor is set, then a line delimiter
|
||||||
|
* should be added by the caller if it is not contained in the record
|
||||||
|
* itself.)
|
||||||
|
* If nothing was transferred (i.e., the caller should retry) then
|
||||||
|
* these functions return NULL. Otherwise they return a record pointer.
|
||||||
|
* Note that in the latter case the length may be zero, which means
|
||||||
|
* the record was an empty line.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *getfix (firqb *f, long *len, int *eor, long iocount)
|
||||||
|
{
|
||||||
|
long left; /* amount left in I/O buffer */
|
||||||
|
char *recp;
|
||||||
|
|
||||||
|
recp = f->currec;
|
||||||
|
left = &iobuf[iocount] - recp; /* compute what's left */
|
||||||
|
*eor = FALSE; /* default to not EOR */
|
||||||
|
if (left <= 0 || rmseof (f, recp, iocount)) {
|
||||||
|
*len = 0;
|
||||||
|
f->currec = NULL;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
if (left < f->recsiz) {
|
||||||
|
*len = left;
|
||||||
|
f->currec = NULL;
|
||||||
|
return (recp);
|
||||||
|
}
|
||||||
|
*len = f->recsiz;
|
||||||
|
f->currec += f->recsiz;
|
||||||
|
*eor = TRUE;
|
||||||
|
return (recp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *getvar (firqb *f, long *len, int *eor, long iocount)
|
||||||
|
{
|
||||||
|
char *recp;
|
||||||
|
word16 reclen;
|
||||||
|
word16 *reclenp;
|
||||||
|
long left;
|
||||||
|
|
||||||
|
recp = f->currec;
|
||||||
|
*eor = FALSE; /* default to not EOR */
|
||||||
|
left = (&iobuf[iocount] - recp);
|
||||||
|
if (left <= 0 || rmseof (f, recp, iocount)) {
|
||||||
|
*len = 0;
|
||||||
|
f->currec = NULL;
|
||||||
|
f->currecsiz = 0;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
if ((reclen = f->currecsiz) == 0) {
|
||||||
|
reclenp = (word16 *)recp;
|
||||||
|
reclen = *reclenp;
|
||||||
|
if (reclen == 0xffff) { /* end of data in block */
|
||||||
|
left &= -BLKSIZE; /* get what's left in remaining blocks */
|
||||||
|
if (left == 0) {
|
||||||
|
*len = 0;
|
||||||
|
f->currec = NULL;
|
||||||
|
f->currecsiz = 0;
|
||||||
|
return (NULL);
|
||||||
|
} else {
|
||||||
|
recp = &iobuf[iocount - left];
|
||||||
|
reclenp = (word16 *) recp;
|
||||||
|
reclen = *reclenp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
left -= 2; /* discount length field */
|
||||||
|
recp += 2; /* and skip it */
|
||||||
|
}
|
||||||
|
if (reclen > left) {
|
||||||
|
*len = left;
|
||||||
|
f->currecsiz = reclen - left; /* do this next time */
|
||||||
|
f->currec = NULL;
|
||||||
|
return (recp);
|
||||||
|
}
|
||||||
|
f->currec = recp + UP(reclen,2); /* point to where next count is */
|
||||||
|
f->currecsiz = 0; /* no partial record left to do */
|
||||||
|
*len = reclen;
|
||||||
|
*eor = TRUE;
|
||||||
|
return (recp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *getvfc (firqb *f, long *len, int *eor, long iocount)
|
||||||
|
{
|
||||||
|
char *recp;
|
||||||
|
word16 reclen;
|
||||||
|
word16 *reclenp;
|
||||||
|
long left, skip;
|
||||||
|
|
||||||
|
recp = f->currec;
|
||||||
|
*eor = FALSE; /* default to not EOR */
|
||||||
|
left = (&iobuf[iocount] - recp);
|
||||||
|
if ((reclen = f->currecsiz) != 0) skip = f->recskip;
|
||||||
|
else {
|
||||||
|
reclenp = (word16 *)recp;
|
||||||
|
reclen = *reclenp;
|
||||||
|
if (reclen == 0xffff) { /* end of data in block */
|
||||||
|
left &= -BLKSIZE; /* get what's left in remaining blocks */
|
||||||
|
if (left == 0) {
|
||||||
|
*len = 0;
|
||||||
|
f->currec = NULL;
|
||||||
|
f->currecsiz = 0;
|
||||||
|
return (NULL);
|
||||||
|
} else {
|
||||||
|
recp = &iobuf[iocount - left];
|
||||||
|
reclenp = (word16 *) recp;
|
||||||
|
reclen = *reclenp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
left -= 2; /* discount length field */
|
||||||
|
recp += 2; /* and skip it */
|
||||||
|
skip = f->rechdrsiz; /* skip over whole header */
|
||||||
|
}
|
||||||
|
if (reclen > left) {
|
||||||
|
f->currecsiz = reclen - left; /* do this next time */
|
||||||
|
if (left > skip) {
|
||||||
|
*len = left - skip;
|
||||||
|
f->recskip = 0; /* nothing to skip */
|
||||||
|
f->currec = NULL;
|
||||||
|
return (recp + skip);
|
||||||
|
} else {
|
||||||
|
*len = 0;
|
||||||
|
f->recskip = skip - left;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f->currec = recp + UP(reclen,2); /* point to where next count is */
|
||||||
|
f->currecsiz = 0; /* no partial record left to do */
|
||||||
|
*len = reclen - skip;
|
||||||
|
*eor = TRUE;
|
||||||
|
return (recp + skip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *getstm (firqb *f, long *len, int *eor, long iocount)
|
||||||
|
{
|
||||||
|
char *lfpos;
|
||||||
|
char *recp;
|
||||||
|
|
||||||
|
*eor = FALSE; /* default to not EOR */
|
||||||
|
while (f->currec < &iobuf[iocount])
|
||||||
|
if (*(f->currec)) break;
|
||||||
|
else f->currec++; /* skip nulls */
|
||||||
|
if (f->currec == &iobuf[iocount]) {
|
||||||
|
*len = 0;
|
||||||
|
f->currec = NULL;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
lfpos = (char *) memchr (f->currec, 012, &iobuf[iocount] - f->currec);
|
||||||
|
recp = f->currec;
|
||||||
|
if (lfpos == NULL || lfpos == f->currec) {
|
||||||
|
*len = &iobuf[iocount] - f->currec;
|
||||||
|
*eor = FALSE;
|
||||||
|
f->currec = NULL;
|
||||||
|
} else {
|
||||||
|
if (*(lfpos - 1) == '\015') *len = lfpos - f->currec - 1;
|
||||||
|
else *len = lfpos - f->currec;
|
||||||
|
*eor = TRUE;
|
||||||
|
f->currec = lfpos + 1;
|
||||||
|
}
|
||||||
|
return (recp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* note that a partial record may be returned; if so, eor is set to false */
|
||||||
|
|
||||||
|
static char *getrec (firqb *f, long *len, int *eor, long iocount) /* get next text record */
|
||||||
|
{
|
||||||
|
switch (f->recfmt & fa_rfm) {
|
||||||
|
case rf_udf:
|
||||||
|
case rf_stm:
|
||||||
|
return (getstm (f, len, eor, iocount));
|
||||||
|
case rf_fix:
|
||||||
|
return (getfix (f, len, eor, iocount));
|
||||||
|
case rf_var:
|
||||||
|
return (getvar (f, len, eor, iocount));
|
||||||
|
case rf_vfc:
|
||||||
|
return (getvfc (f, len, eor, iocount));
|
||||||
|
}
|
||||||
|
rabort (INTERNAL); /* should never get here */
|
||||||
|
return (NULL); /* to make the compiler happy */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Routine to do sequential I/O, either read or write according to the
|
||||||
|
* third argument passed.
|
||||||
|
*/
|
||||||
|
long seqio (firqb *f, long iolen, iohandler io, void *buffer)
|
||||||
|
{
|
||||||
|
long startlbn; /* lbn at which to start transfer */
|
||||||
|
long count; /* and byte count */
|
||||||
|
word prevdcn = 0; /* previous RE entry */
|
||||||
|
|
||||||
|
if (curvbn >= f->size) return (0); /* nothing left */
|
||||||
|
for (count = 0; ; ) {
|
||||||
|
if (cluoff == 0) {
|
||||||
|
if (curreoff == 0 && (f->stat & us_ufd) == 0) {
|
||||||
|
if (!readlk (curre)) rabort(BADRE);
|
||||||
|
lastre = curre;
|
||||||
|
}
|
||||||
|
if (count != 0) {
|
||||||
|
if (f->stat & us_ufd) {
|
||||||
|
if (clumap->uent[curreoff] - prevdcn != dcnperfcs)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (use(ufdre,k)->uent[curreoff] - prevdcn != dcnperfcs)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.debug != 0)
|
||||||
|
printf ("seqio() RE entry %o\n", use(ufdre,k)->uent[curreoff]);
|
||||||
|
}
|
||||||
|
if (count++ == 0) {
|
||||||
|
if (f->stat & us_ufd)
|
||||||
|
startlbn = dcntolbn(clumap->uent[curreoff])
|
||||||
|
+ cluoff;
|
||||||
|
else startlbn = dcntolbn(use(ufdre,k)->uent[curreoff])
|
||||||
|
+ cluoff;
|
||||||
|
if (sw.debug != NULL)
|
||||||
|
printf ("seqio() start lbn %lo\n", startlbn);
|
||||||
|
}
|
||||||
|
/* contiguous file is treated as having one giant cluster... */
|
||||||
|
if (++cluoff == f->clusiz && ((f->stat & us_nox) == 0)) {
|
||||||
|
cluoff = 0;
|
||||||
|
prevdcn = use(ufdre,k)->uent[curreoff];
|
||||||
|
curreoff++; /* on to the next RE entry */
|
||||||
|
if (curreoff == 7) { /* time to read anothe RE */
|
||||||
|
if (f->stat & us_ufd) curre = 0;
|
||||||
|
else curre = use(ufdre,k)->ulnk;
|
||||||
|
curreoff = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count == iolen / BLKSIZE || curvbn + count == f->size) break;
|
||||||
|
}
|
||||||
|
(*io) (startlbn, count * BLKSIZE, buffer);
|
||||||
|
curvbn += count; /* account for what we transferred */
|
||||||
|
return (count * BLKSIZE); /* and return the byte count */
|
||||||
|
}
|
||||||
|
|
||||||
|
void openfile (firqb *f) /* set up file I/O at VBN 0 */
|
||||||
|
{
|
||||||
|
curvbn = 0; /* currently at first block */
|
||||||
|
lastre = 0; /* working on first RE */
|
||||||
|
curre = f->rlink; /* set current RE link */
|
||||||
|
curreoff = 0; /* working on RE entry 0 */
|
||||||
|
cluoff = 0; /* and start of that cluster */
|
||||||
|
/* note: on big disks (dcs > 16) dcnperfcs will end up 0 for directories.
|
||||||
|
* that's fine; the result is that no transfer that crosses retrieval
|
||||||
|
* entries will be done in a single I/O -- exactly what we want.
|
||||||
|
*/
|
||||||
|
dcnperfcs = f->clusiz / dcs; /* how many dcn's in file cluster */
|
||||||
|
if (f->size) /* read first RE if non-null */
|
||||||
|
if ((f->stat & us_ufd) == 0 && !readlk (f->rlink))
|
||||||
|
rabort(BADRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
word *relist = NULL; /* list of pointers to RE's */
|
||||||
|
|
||||||
|
void initrandom (firqb *f)
|
||||||
|
{
|
||||||
|
long recount;
|
||||||
|
|
||||||
|
if (relist != NULL) free (relist);
|
||||||
|
if (f->stat & us_ufd) return; /* UFDs are easy */
|
||||||
|
openfile (f); /* first do common setup */
|
||||||
|
/* Note: do not use UP() here since we don't round to
|
||||||
|
* a power of 2!
|
||||||
|
*/
|
||||||
|
recount = (f->size + 7 * f->clusiz - 1) / (7 * f->clusiz);
|
||||||
|
if ((relist = (word *) malloc (recount * sizeof (word))) == NULL)
|
||||||
|
rabort(NOMEM);
|
||||||
|
memset (relist, 0, recount * sizeof (word));
|
||||||
|
relist[0] = f->rlink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fileseek (firqb *f, long vbn) /* seek to (0-based) vbn */
|
||||||
|
{
|
||||||
|
int clu, re, renum;
|
||||||
|
word prevre;
|
||||||
|
|
||||||
|
if (vbn >= f->size) rabort(INTERNAL);
|
||||||
|
clu = vbn / f->clusiz; /* get cluster number */
|
||||||
|
if ((f->stat & us_ufd) == 0) { /* more work for non-UFDs */
|
||||||
|
renum = clu / 7; /* get RE number */
|
||||||
|
if (relist[renum] == 0) { /* load RE list if we haven't been here */
|
||||||
|
for (re = 0; re <= renum; re++) {
|
||||||
|
if (relist[re]) prevre = relist[re];
|
||||||
|
else {
|
||||||
|
if (!readlk (prevre)) rabort(CORRUPT);
|
||||||
|
relist[re] = prevre = use(ufdre,k)->ulnk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readlk (curre = relist[renum]); /* read appropriate RE */
|
||||||
|
}
|
||||||
|
curreoff = clu % 7; /* set index into RE */
|
||||||
|
cluoff = vbn % f->clusiz; /* and offset into cluster */
|
||||||
|
curvbn = vbn; /* and finally, current vbn */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a RSTS file and copy it to a specified local file. Transfers in
|
||||||
|
* binary (block) mode or ascii (record) mode according to the third
|
||||||
|
* argument. The return value is the count of bytes transferred.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long getfile (FILE *to, firqb *f, int binary)
|
||||||
|
{
|
||||||
|
long reclen, iocount;
|
||||||
|
int eor;
|
||||||
|
char *recp;
|
||||||
|
|
||||||
|
if (f->size == 0) return (0); /* null file, nothing transferred */
|
||||||
|
openfile (f); /* set up file transfer */
|
||||||
|
totalbytes = 0;
|
||||||
|
if (binary) {
|
||||||
|
while ((iocount = seqio (f, iobufsize, rread, iobuf)) != 0) {
|
||||||
|
fwrite (iobuf, 1, iocount, to);
|
||||||
|
totalbytes += iocount;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iocount = seqio (f, iobufsize, rread, iobuf); /* do initial buffer fill */
|
||||||
|
f->currec = iobuf; /* init current record pointer */
|
||||||
|
f->currecsiz = 0; /* no current record size */
|
||||||
|
while (TRUE) {
|
||||||
|
recp = getrec (f, &reclen, &eor, iocount);
|
||||||
|
if (recp != NULL) {
|
||||||
|
totalbytes += reclen;
|
||||||
|
if (reclen) fwrite (recp, 1, reclen, to);
|
||||||
|
if (eor) {
|
||||||
|
fputc ('\n', to);
|
||||||
|
#if (defined(__MSDOS__) && !defined(__unix__))
|
||||||
|
totalbytes += 2;
|
||||||
|
#else
|
||||||
|
totalbytes++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (f->currec == NULL) {
|
||||||
|
if ((iocount = seqio (f, iobufsize, rread, iobuf)) == 0)
|
||||||
|
break;
|
||||||
|
else f->currec = iobuf; /* init current record pointer */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (totalbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extend the currently open file to the specified size, if not already
|
||||||
|
* that big.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long extfile (firqb *f, long blocks)
|
||||||
|
{
|
||||||
|
int clus, reoff, clunum;
|
||||||
|
word re;
|
||||||
|
|
||||||
|
if (sw.debug != NULL)
|
||||||
|
printf ("extfile(,%ld) from %ld\n", blocks, f->size);
|
||||||
|
if (f->size >= blocks) return (TRUE); /* already big enough */
|
||||||
|
if (f->stat & us_nox) return (FALSE); /* error if contiguous */
|
||||||
|
clus = (UP(blocks,f->clusiz) - UP(f->size,f->clusiz)) / f->clusiz;
|
||||||
|
if (clus == 0) { /* no new clusters needed */
|
||||||
|
f->size = blocks; /* so just do it */
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
if (cluoff == 0) reoff = curreoff;
|
||||||
|
else {
|
||||||
|
reoff = curreoff + 1;
|
||||||
|
if (reoff > 6) reoff = 0; /* overflowed current RE */
|
||||||
|
}
|
||||||
|
f->size = UP(f->size,f->clusiz); /* round up to full cluster */
|
||||||
|
while (clus > 0) { /* allocate what we need */
|
||||||
|
if (reoff == 0) { /* need to start new RE */
|
||||||
|
if ((re = getent ()) == 0) return (FALSE);
|
||||||
|
if (NULLINK(curre)) curre = re; /* this is now current */
|
||||||
|
readlk (re); /* read it */
|
||||||
|
use(ufdre,k)->ulnk = 1; /* mark it allocated */
|
||||||
|
MARKF;
|
||||||
|
if (lastre) { /* link it to earlier RE */
|
||||||
|
readlk (lastre);
|
||||||
|
use(ufdre,k)->ulnk = re;
|
||||||
|
} else { /* link first RE to NE */
|
||||||
|
readlk (f->nlink);
|
||||||
|
use(ufdne,k)->uar = re;
|
||||||
|
f->rlink = re; /* record in firqb also */
|
||||||
|
}
|
||||||
|
MARKF;
|
||||||
|
lastre = re; /* this is now the last RE */
|
||||||
|
readlk (re); /* read the new RE */
|
||||||
|
}
|
||||||
|
if ((clunum = getclu (f->clusiz, f->clusiz)) == 0) return (FALSE);
|
||||||
|
use(ufdre,k)->uent[reoff] = clunum;
|
||||||
|
MARKF;
|
||||||
|
f->size += f->clusiz; /* adjust file size */
|
||||||
|
reoff++;
|
||||||
|
if (reoff > 6) reoff = 0; /* overflowed current RE */
|
||||||
|
clus--; /* any clusters left to do? */
|
||||||
|
}
|
||||||
|
f->size = blocks; /* it worked, all done */
|
||||||
|
readlk (curre); /* make sure we have the right RE */
|
||||||
|
return (TRUE); /* return with success */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read a local file and put it to a specified RSTS file. Transfers in
|
||||||
|
* binary (block) mode or ascii (record) mode according to the third
|
||||||
|
* argument. The return value is the count of bytes transferred if the
|
||||||
|
* copy completed, or the negative of what was transferred if the transfer
|
||||||
|
* did not finish (i.e., due to no room on the disk).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* writefile is a support routine that writes some number of bytes from iobuf
|
||||||
|
* to the rsts output file. It returns FALSE if the write did not finish, e.g.,
|
||||||
|
* due to lack of disk space.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long writefile (firqb *f, long count)
|
||||||
|
{
|
||||||
|
long offset, blocks, wcount;
|
||||||
|
|
||||||
|
if (sw.debug != NULL) printf ("writefile(,%ld)\n", count);
|
||||||
|
count = UP(count,BLKSIZE);
|
||||||
|
offset = 0;
|
||||||
|
blocks = (totalbytes + count) / BLKSIZE;
|
||||||
|
extfile (f, blocks); /* extend if needed */
|
||||||
|
while (count) {
|
||||||
|
wcount = seqio (f, count, rwrite, iobuf + offset);
|
||||||
|
if (wcount == 0) {
|
||||||
|
totalbytes = -totalbytes;
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
offset += wcount;
|
||||||
|
totalbytes += wcount;
|
||||||
|
count -= wcount;
|
||||||
|
}
|
||||||
|
return (TRUE); /* write suceeded */
|
||||||
|
}
|
||||||
|
|
||||||
|
long putfile (FILE *from, firqb *f, int binary)
|
||||||
|
{
|
||||||
|
long blocks, wcount, iocount, iocount2, adjust;
|
||||||
|
long oldsize, offset;
|
||||||
|
long ilen, llen;
|
||||||
|
char *iptr, *eol;
|
||||||
|
ufdne *n;
|
||||||
|
ufdae *a;
|
||||||
|
|
||||||
|
openfile (f); /* set up file transfer */
|
||||||
|
totalbytes = 0;
|
||||||
|
if (binary) {
|
||||||
|
while ((iocount = fread (iobuf, 1, iobufsize, from)) != 0) {
|
||||||
|
iocount2 = UP(iocount, BLKSIZE);
|
||||||
|
adjust = iocount2 - iocount;
|
||||||
|
if (adjust) memset (iobuf + iocount, 0, adjust);
|
||||||
|
if (!writefile (f, iocount2)) break;
|
||||||
|
if (adjust) {
|
||||||
|
totalbytes -= adjust;
|
||||||
|
break; /* short read, done with file */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iptr = iobuf; /* start getting lines at the start */
|
||||||
|
ilen = iobufsize + 2; /* use all including 2 extra bytes */
|
||||||
|
for ( ; ; ) {
|
||||||
|
if (fgets (iptr, ilen, from) == NULL) break;
|
||||||
|
llen = strlen (iptr); /* get length of this line */
|
||||||
|
eol = iptr + llen; /* point to terminator */
|
||||||
|
if (*--eol == '\n') { /* if we got a complete line */
|
||||||
|
if (*(eol - 1) == '\r') { /* terminator = cr-lf? */
|
||||||
|
eol++; /* next line starts here */
|
||||||
|
} else { /* only \n at eol */
|
||||||
|
*eol++ = '\r'; /* put in the cr */
|
||||||
|
*eol++ = '\n'; /* and overwrite null with lf */
|
||||||
|
llen ++; /* account for cr */
|
||||||
|
}
|
||||||
|
} else eol++; /* skip to end of data */
|
||||||
|
iptr = eol; /* advance read ptr */
|
||||||
|
ilen -= llen; /* compute space left */
|
||||||
|
if (ilen <= 2) { /* full buffer */
|
||||||
|
if (!writefile (f, iobufsize)) {
|
||||||
|
ilen = 0; /* don't write more */
|
||||||
|
break; /* quit this file */
|
||||||
|
}
|
||||||
|
iptr = iobuf; /* reinit pointer */
|
||||||
|
ilen = 2 - ilen; /* # bytes to move */
|
||||||
|
eol = iobuf + iobufsize; /* move from here */
|
||||||
|
for ( ; ilen > 0; ilen--) *iptr++ = *eol++;
|
||||||
|
ilen = iobufsize + 2 - (iptr - iobuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ilen = iptr - iobuf; /* get amount buffered */
|
||||||
|
adjust = UP(ilen,BLKSIZE) - ilen; /* get amount to pad */
|
||||||
|
if (adjust) memset (iptr, 0, adjust); /* do it */
|
||||||
|
iptr += adjust; /* point past it */
|
||||||
|
if (iptr != iobuf) writefile (f, iptr - iobuf); /* write pending data */
|
||||||
|
totalbytes -= adjust; /* don't report pad */
|
||||||
|
}
|
||||||
|
readlk (f->alink); /* read file's AE */
|
||||||
|
a = use(ufdae,k);
|
||||||
|
oldsize = a->usiz; /* get old file size */
|
||||||
|
if (a->urts[0] == 0) oldsize += a->urts[1] >> 16;
|
||||||
|
if (f->size != oldsize ) { /* size changed */
|
||||||
|
if (f->size < oldsize) rabort(INTERNAL); /* can't shrink */
|
||||||
|
updqb (f, UP(f->size,f->clusiz) - UP(oldsize,f->clusiz));
|
||||||
|
a->usiz = f->size & 0xffff;
|
||||||
|
MARKF;
|
||||||
|
if (f->size >> 16) { /* large file */
|
||||||
|
a->urts[1] = f->size >> 16;
|
||||||
|
if ((oldsize >> 16) == 0) { /* it was small */
|
||||||
|
if (a->urts[0]) {
|
||||||
|
printf ("Warning - RTS name cleared for large file ");
|
||||||
|
printcurname (f);
|
||||||
|
printf ("\n");
|
||||||
|
a->urts[0] = 0;
|
||||||
|
}
|
||||||
|
readlk (f->nlink);
|
||||||
|
n = use(ufdne,k);
|
||||||
|
if (n->uprot & up_run) {
|
||||||
|
n->uprot &= ~up_run;
|
||||||
|
MARKF;
|
||||||
|
printf ("Warning - runnable protection bit cleared for large file ");
|
||||||
|
printcurname (f);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (totalbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return TRUE if the filename has an extension that suggests it's a text
|
||||||
|
* file, and FALSE otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char textlist[][4] =
|
||||||
|
{ "txt", "lst", "map", "sid", "log", "lis",
|
||||||
|
"rno", "doc", "mem", "bas", "b2s", "mac",
|
||||||
|
"for", "ftn", "fth", "cbl", "dbl", "com",
|
||||||
|
"cmd", "bat", "tec", "ctl", "odl", "ps ",
|
||||||
|
"c ", "h ", "ps", "c", "h", "src",
|
||||||
|
"alg", "" };
|
||||||
|
|
||||||
|
int textfile (char *name)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
p = strchr (name, '.');
|
||||||
|
if (p == NULL) return (FALSE); /* no extension */
|
||||||
|
p++; /* skip past the dot */
|
||||||
|
for (i = 0; textlist[i][0] != '\0'; i++)
|
||||||
|
if (strcmp (textlist[i], p) == 0) return (TRUE);
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
25
extracters/rstsflx/fileio.h
Normal file
25
extracters/rstsflx/fileio.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
extern long seqio(firqb * f , long iolen , iohandler io , void * buffer);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void openfile(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void initrandom(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void fileseek(firqb * f , long vbn);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern long getfile(FILE * to , firqb * f , int binary);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern long extfile(firqb * f , long blocks);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern long writefile(firqb * f , long count);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern long putfile(FILE * from , firqb * f , int binary);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int textfile(char * name);
|
||||||
309
extracters/rstsflx/filename.c
Normal file
309
extracters/rstsflx/filename.c
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
/* subroutines to handle rsts file name conversion and file spec parse */
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
|
||||||
|
#define isr50(c) (isalnum (c) || (c) == ' ' || (c) == '?' || (c) == '*')
|
||||||
|
|
||||||
|
const char *parsename (const char *p, firqb *out) /* parse the name part of a spec */
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < 6; n++) out->name[n] = ' ';
|
||||||
|
out->name[6] = '\0'; /* put in terminator */
|
||||||
|
if (isr50(*p)) { /* name present */
|
||||||
|
n = 0;
|
||||||
|
while (isr50(*p)) {
|
||||||
|
if (*p == ' ') { /* skip blanks */
|
||||||
|
p++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out->flags |= f_name;
|
||||||
|
if (*p == '*') {
|
||||||
|
if (n < 6) {
|
||||||
|
out->name[n++] = '?';
|
||||||
|
out->flags |= f_namw;
|
||||||
|
} else p++;
|
||||||
|
} else {
|
||||||
|
if (n < 6) out->name[n++] = tolower (*p);
|
||||||
|
if (*p++ == '?') out->flags |= f_namw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *parsenameext (const char *p, firqb *out) /* parse the name.ext part of a spec */
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 0; n < NAMELEN - 1; n++) out->name[n] = ' ';
|
||||||
|
p = parsename (p, out); /* parse the name part */
|
||||||
|
out->name[6] = '.';
|
||||||
|
out->name[NAMELEN - 1] = '\0'; /* put in terminator */
|
||||||
|
if (*p == '.') { /* extension present */
|
||||||
|
p++;
|
||||||
|
out->flags |= f_ext;
|
||||||
|
if (isr50(*p)) {
|
||||||
|
n = 0;
|
||||||
|
while (isr50(*p)) {
|
||||||
|
if (*p == ' ') { /* skip blanks */
|
||||||
|
p++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*p == '*') {
|
||||||
|
if (n < 3) {
|
||||||
|
out->name[7 + n++] = '?';
|
||||||
|
out->flags |= f_extw;
|
||||||
|
} else p++;
|
||||||
|
} else {
|
||||||
|
if (n < 3) out->name[7 + n++] = tolower (*p);
|
||||||
|
if (*p++ == '?') out->flags |= f_extw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse (const char *p, firqb *out) /* returns FALSE if error, TRUE if ok */
|
||||||
|
{
|
||||||
|
char *pp;
|
||||||
|
|
||||||
|
out->proj = 0;
|
||||||
|
out->prog = 0;
|
||||||
|
out->flags = 0;
|
||||||
|
if (*p == '[' || *p == '(' || *p == '/') { /* PPN first */
|
||||||
|
p++;
|
||||||
|
out->flags |= f_ppn; /* flag PPN present */
|
||||||
|
if (*p == '*') { /* wild proj */
|
||||||
|
p++;
|
||||||
|
out->proj = 255;
|
||||||
|
out->flags |= f_ppnw;
|
||||||
|
} else {
|
||||||
|
out->proj = strtoul (p, &pp, 10);
|
||||||
|
if (pp == p || out->proj > 254) return (FALSE);
|
||||||
|
p = pp;
|
||||||
|
}
|
||||||
|
if (*p != ',' && *p != '/') return (FALSE);
|
||||||
|
p++;
|
||||||
|
if (*p == '*') { /* wild prog */
|
||||||
|
p++;
|
||||||
|
out->prog = 255;
|
||||||
|
out->flags |= f_ppnw;
|
||||||
|
} else {
|
||||||
|
out->prog = strtoul (p, &pp, 10);
|
||||||
|
if (pp == p || out->prog > 254) return (FALSE);
|
||||||
|
p = pp;
|
||||||
|
}
|
||||||
|
if (out->proj == 0 && out->prog == 0) return (FALSE);
|
||||||
|
if (*p != ']' && *p != ')' &&
|
||||||
|
*p != '/' && *p != '\0') return (FALSE);
|
||||||
|
if (*p != '\0') p++;
|
||||||
|
} else switch (*p) { /* see if special PPN char */
|
||||||
|
case '$':
|
||||||
|
out->proj = 1; /* supply [1,2] */
|
||||||
|
out->prog = 2;
|
||||||
|
out->flags |= f_ppn; /* indicate PPN present */
|
||||||
|
p++; /* skip that char */
|
||||||
|
break;
|
||||||
|
case '!':
|
||||||
|
out->proj = 1; /* supply [1,3] */
|
||||||
|
out->prog = 3;
|
||||||
|
out->flags |= f_ppn; /* indicate PPN present */
|
||||||
|
p++; /* skip that char */
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
out->proj = 1; /* supply [1,4] */
|
||||||
|
out->prog = 4;
|
||||||
|
out->flags |= f_ppn; /* indicate PPN present */
|
||||||
|
p++; /* skip that char */
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
out->proj = 1; /* supply [1,5] */
|
||||||
|
out->prog = 5;
|
||||||
|
out->flags |= f_ppn; /* indicate PPN present */
|
||||||
|
p++; /* skip that char */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* no PPN supplied */
|
||||||
|
out->proj = 1; /* supply default of [1,2] */
|
||||||
|
out->prog = 2; /* don't set f_ppn flag */
|
||||||
|
}
|
||||||
|
p = parsenameext (p, out);
|
||||||
|
if (*p == '<') { /* protection code present */
|
||||||
|
p++;
|
||||||
|
out->flags |= f_prot;
|
||||||
|
out->newprot = strtoul (p, &pp, 10);
|
||||||
|
if (pp == p) return (FALSE);
|
||||||
|
p = pp;
|
||||||
|
if (*p++ != '>') return (FALSE);
|
||||||
|
}
|
||||||
|
return (*p == '\0'); /* success if all was parsed */
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char r50table[] = " abcdefghijklmnopqrstuvwxyz$.?0123456789:";
|
||||||
|
|
||||||
|
char *r50toascii (word16 r50, char *string, int space)
|
||||||
|
{
|
||||||
|
int t, c, pos;
|
||||||
|
|
||||||
|
pos = 03100;
|
||||||
|
for (t = 0; t<3; t++) {
|
||||||
|
c = r50 / pos;
|
||||||
|
if (c || space) *string++ = r50table[c];
|
||||||
|
r50 %= pos;
|
||||||
|
pos /= 050;
|
||||||
|
}
|
||||||
|
*string = '\0'; /* put in string terminator */
|
||||||
|
return (string);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *r50toascii2 (word16 r50[], char *string, int space)
|
||||||
|
{
|
||||||
|
string = r50toascii (r50[0], string, space);
|
||||||
|
return (r50toascii (r50[1], string, space));
|
||||||
|
}
|
||||||
|
|
||||||
|
void r50filename (word16 r50[], char *name, int space)
|
||||||
|
{
|
||||||
|
name = r50toascii2 (r50, name, space);
|
||||||
|
*name++ = '.';
|
||||||
|
name = r50toascii (r50[2], name, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printfqbppn (const firqb *f)
|
||||||
|
{
|
||||||
|
if (f->proj == 255) printf ("[*,");
|
||||||
|
else printf ("[%d,", f->proj);
|
||||||
|
if (f->prog == 255) printf ("*]");
|
||||||
|
else printf ("%d]", f->prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printfqbname (const firqb *f)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
printfqbppn (f);
|
||||||
|
for (n = 0; n < NAMELEN - 1; n++)
|
||||||
|
if (f->name[n] != ' ') putchar (f->name[n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void printcurname (const firqb *f)
|
||||||
|
{
|
||||||
|
if (f->stat & us_ufd)
|
||||||
|
{
|
||||||
|
if (f->cproj == 255)
|
||||||
|
printf ("[*,*]");
|
||||||
|
else if (f->cprog == 255)
|
||||||
|
printf ("[%d,*]", f->cproj);
|
||||||
|
else printf ("[%d,%d]", f->cproj, f->cprog);
|
||||||
|
}
|
||||||
|
else printf ("[%d,%d]%s", f->cproj, f->cprog, f->cname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* merge a native (unix or dos) input filespec or RSTS name.ext with a
|
||||||
|
* (possibly wild) rsts output file spec to produce the specific output
|
||||||
|
* filename as a 3-word rad50 value. If the third argument is TRUE, then
|
||||||
|
* the last directory element in the input filename path must be numeric,
|
||||||
|
* and is used to set the current PPN fields in the output FIRQB.
|
||||||
|
*/
|
||||||
|
void mergename (char *iname, firqb *oname, int tree)
|
||||||
|
{
|
||||||
|
int n, spflag;
|
||||||
|
firqb inf;
|
||||||
|
char c;
|
||||||
|
char *in1, *in2;
|
||||||
|
char tname[FILENAME_MAX];
|
||||||
|
int ppn;
|
||||||
|
|
||||||
|
if ((in1 = strrchr (iname, '/')) != NULL) in1++;
|
||||||
|
else in1 = iname;
|
||||||
|
if ((in2 = strrchr (in1, '\\')) != NULL) in1 = in2 + 1;
|
||||||
|
inf.flags = 0; /* clear parse flags */
|
||||||
|
if (*(parsenameext (in1, &inf)) != '\0' /* see if we can parse that */
|
||||||
|
|| (inf.flags & F_WILD)) /* it should not have * or ? */
|
||||||
|
memcpy (inf.name, "xxxxxx.xxx", NAMELEN); /* use xxx if bad name */
|
||||||
|
oname->cname[6] = '.'; /* make sure . is in */
|
||||||
|
spflag = FALSE; /* no spaces yet */
|
||||||
|
for (n = 0; n < NAMELEN - 1; n++) {
|
||||||
|
if (n == 6) {
|
||||||
|
spflag = FALSE; /* no spaces yet in ext */
|
||||||
|
continue; /* skip the '.' separator */
|
||||||
|
}
|
||||||
|
c = oname->name[n]; /* start with output spec */
|
||||||
|
if (c == '?' && !spflag)
|
||||||
|
c = inf.name[n]; /* use input if output wild */
|
||||||
|
if (c == ' ') spflag = TRUE; /* stop if we find a space */
|
||||||
|
if (spflag) c = ' '; /* force spaces after space */
|
||||||
|
oname->cname[n] = c; /* store result */
|
||||||
|
}
|
||||||
|
oname->cname[NAMELEN - 1] = '\0'; /* ensure terminator */
|
||||||
|
if (tree) {
|
||||||
|
n = in1 - iname; /* get offset to name part */
|
||||||
|
if (n) n--; /* now to the / */
|
||||||
|
else {
|
||||||
|
oname->cproj = oname->cprog = 0; /* can't set PPN from iname */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcpy (tname, iname); /* copy the name */
|
||||||
|
tname[n] = '\0'; /* chop off directory part */
|
||||||
|
if ((in1 = strrchr (tname, '/')) != NULL) in1++;
|
||||||
|
else in1 = tname;
|
||||||
|
if ((in2 = strrchr (in1, '\\')) != NULL) in1 = in2 + 1;
|
||||||
|
ppn = strtoul (in1, &in2, 10); /* convert to decimal */
|
||||||
|
if (*in2 != '\0') ppn = 0; /* check for error */
|
||||||
|
if (oname->proj == 255) {
|
||||||
|
if (strlen (in1) < 4) ppn = 0;
|
||||||
|
oname->cproj = ppn / 1000; /* proj = first digits */
|
||||||
|
} else oname->cproj = oname->proj;
|
||||||
|
if (oname->prog == 255)
|
||||||
|
oname->cprog = ppn % 1000;
|
||||||
|
else oname->cprog = oname->prog;
|
||||||
|
if (oname->cproj > 254 || oname->cprog > 254)
|
||||||
|
oname->cproj = oname->cprog = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* routines to convert ascii names to rad50. These assume that the name
|
||||||
|
* is valid rad50, i.e., letters and digits only. Special case: for the
|
||||||
|
* parsing of RTS names, '.' is also accepted as a rad50 character.
|
||||||
|
* Any non-rad50 character is treated as space, i.e., rad50 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
word cvtr50 (const char *in)
|
||||||
|
{
|
||||||
|
int mul, r50, n;
|
||||||
|
|
||||||
|
for (r50 = 0, mul = 03100, n = 0; n < 3; in++, mul /= 050, n++) {
|
||||||
|
if (isdigit (*in)) r50 += (*in - '0' + 036) * mul;
|
||||||
|
else if (isalpha (*in)) r50 += (tolower (*in) - 'a' + 001) * mul;
|
||||||
|
else if (*in == '.') r50 += 034 * mul;
|
||||||
|
}
|
||||||
|
return (r50);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert 6-character name */
|
||||||
|
|
||||||
|
void cvtnametor50 (const char *in, word16 *out)
|
||||||
|
{
|
||||||
|
out[0] = cvtr50 (in);
|
||||||
|
out[1] = cvtr50 (in + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert name.ext */
|
||||||
|
|
||||||
|
void cvtnameexttor50 (const char *in, word16 *out)
|
||||||
|
{
|
||||||
|
cvtnametor50 (in, out);
|
||||||
|
out[2] = cvtr50 (in + 7); /* skip the "." */
|
||||||
|
}
|
||||||
|
|
||||||
39
extracters/rstsflx/filename.h
Normal file
39
extracters/rstsflx/filename.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
extern const char * parsename(const char * p , firqb * out);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern const char * parsenameext(const char * p , firqb * out);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int parse(const char * p , firqb * out);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern char * r50toascii(word16 r50 , char * string , int space);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern char * r50toascii2(word16 r50[] , char * string , int space);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void r50filename(word16 r50[] , char * name , int space);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void printfqbppn(const firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void printfqbname(const firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void printcurname(const firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void mergename(char * iname , firqb * oname , int tree);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern word cvtr50(const char * in);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void cvtnametor50(const char * in , word16 * out);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void cvtnameexttor50(const char * in , word16 * out);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
1544
extracters/rstsflx/fip.c
Normal file
1544
extracters/rstsflx/fip.c
Normal file
File diff suppressed because it is too large
Load Diff
87
extracters/rstsflx/fip.h
Normal file
87
extracters/rstsflx/fip.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
extern void fbwrite(void);
|
||||||
|
extern void checkwrite(void);
|
||||||
|
extern void fbread(long block);
|
||||||
|
extern void readdcn(long dcn);
|
||||||
|
extern int ulk(word link);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void readlk2(word link);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int readlk(word link);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int readlktbl(word link);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern long scanbytes(long start , long last , int clusiz , long clucount);
|
||||||
|
extern long scanbits(long start , long last , int clusiz , long clucount);
|
||||||
|
extern long getclu(int clusiz , long size);
|
||||||
|
extern void retclu(long pos , int clusiz);
|
||||||
|
extern void readlabel(void);
|
||||||
|
extern void setppn(firqb * f , int proj , int prog , word ppnent , int which);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern word nextppn(firqb * f , int which);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern word initfilescan(firqb * f , int which);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int wmatch(const char * wn , const char * n);
|
||||||
|
extern int nextfileindir(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int nextfile(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int findfile(firqb * f , const char * name);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int findqb(const firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void updqb(const firqb * f , long delta);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void upddlw(const firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void upddla(const firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int extdir2(int newcm , int clusiz , byte flags , const ufdlabel * newl);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int extdir(void);
|
||||||
|
extern int allocufd(word dirne , firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int getent(void);
|
||||||
|
extern void retent(word link);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void retfile(word nlink);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void delfile(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int crefile(firqb * f , const word16 * rtsname,
|
||||||
|
const ufdrms1 *rms1, const ufdrms2 *rms2);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int protfile(firqb * f);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int makedir(firqb * f , int newclu);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern int remdir(firqb * f , word ne);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void findsat(void);
|
||||||
|
extern void rmount(void);
|
||||||
|
extern void rmountrw(void);
|
||||||
|
extern void rumount(void);
|
||||||
|
extern void rumountrw(void);
|
||||||
299
extracters/rstsflx/fldef.h
Normal file
299
extracters/rstsflx/fldef.h
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
/* fldef.h -- RSTS file system definitions
|
||||||
|
*
|
||||||
|
* Derived from fldef.mac, RSTS V10.1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* rad50 constants we need */
|
||||||
|
#define MFD 0051064 /* rad50 "MFD" */
|
||||||
|
#define GFD 0026264 /* rad50 "GFD" */
|
||||||
|
#define UFD 0102064 /* rad50 "UFD" */
|
||||||
|
#define TMP 0077430 /* rad50 "TMP" */
|
||||||
|
|
||||||
|
/* Disk file structure definitions
|
||||||
|
* Any definitions that apply only for certain disk structure levels
|
||||||
|
* are marked accordingly. They apply to the rev level stated and those
|
||||||
|
* after it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Note: except for the pack label, each of these struct definitions
|
||||||
|
* must define a struct of size 16 bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct { /* Pack label entry */
|
||||||
|
word16 ulnk; /* Link if RDS0.0, otherwise 1 */
|
||||||
|
int16 fill1; /* Reserved (-1) */
|
||||||
|
word16 mdcn; /* Starting DCN of MFD (RDS1.1) */
|
||||||
|
word16 plvl; /* Pack revision level */
|
||||||
|
word16 ppcs; /* Pack cluster size */
|
||||||
|
word16 pstat; /* Pack status/flags */
|
||||||
|
word16 pckid[2]; /* Pack ID */
|
||||||
|
word16 tapgvn[2]; /* TAP generation-version number (RDS1.1) */
|
||||||
|
word16 bckdat; /* Date of last TAP full backup (RDS1.1) */
|
||||||
|
word16 bcktim; /* Time of last TAP full backup (RDS1.1) */
|
||||||
|
word16 mntdat; /* Date of last mount/dismount (RDS1.2) */
|
||||||
|
word16 mnttim; /* Time of last mount/dismount (RDS1.2) */
|
||||||
|
byte fill2[BLKSIZE-(14*sizeof(word16))]; /* Reserved */
|
||||||
|
} packlabel;
|
||||||
|
|
||||||
|
/* Flag bits in pack label field */
|
||||||
|
|
||||||
|
#define uc_top 0001000 /* New files first */
|
||||||
|
#define uc_dlw 0004000 /* Maintain date of last write */
|
||||||
|
#define uc_ro 0010000 /* Read-only pack */
|
||||||
|
#define uc_new 0020000 /* "New" pack (RDS1.1) */
|
||||||
|
#define uc_pri 0040000 /* Pack is private/system */
|
||||||
|
#define uc_mnt 0100000 /* Pack is mounted (dirty) */
|
||||||
|
|
||||||
|
/* Rev levels */
|
||||||
|
#define RDS0 0 /* RDS 0 -- V7.x and before */
|
||||||
|
#define RDS11 ((1<<8)+1) /* RDS 1.1 -- V8 */
|
||||||
|
#define RDS12 ((1<<8)+2) /* RDS 1.2 -- V9.0 and beyond */
|
||||||
|
|
||||||
|
/* MFD and GFD are new as of RDS1.1 */
|
||||||
|
|
||||||
|
typedef struct { /* MFD label entry */
|
||||||
|
word16 fill1; /* Reserved (0) */
|
||||||
|
int16 fill2; /* Reserved (-1) */
|
||||||
|
word16 fill3[3]; /* Reserved (0) */
|
||||||
|
word16 malnk; /* Link to pack attributes */
|
||||||
|
byte lppn[2]; /* PPN [255,255] */
|
||||||
|
word16 lid; /* Identification (RAD50 "MFD") */
|
||||||
|
} mfdlabel;
|
||||||
|
|
||||||
|
typedef struct { /* Directory cluster map */
|
||||||
|
byte uclus; /* Directory clustersize */
|
||||||
|
byte uflag; /* RDS1 GFD/MFD flag in high bit */
|
||||||
|
word16 uent[7]; /* The dcn's of the cluster(s) */
|
||||||
|
} fdcm;
|
||||||
|
|
||||||
|
#define fd_new 0200 /* flag bit for GFD/MFD in uflag (RDS1.1) */
|
||||||
|
|
||||||
|
typedef struct { /* GFD label entry */
|
||||||
|
word16 fill1; /* Reserved (0) */
|
||||||
|
int16 fill2; /* Reserved (-1) */
|
||||||
|
word16 fill3[4]; /* Reserved (0) */
|
||||||
|
byte lppn[2]; /* PPN [x,255] */
|
||||||
|
word16 lid; /* Identification (RAD50 "GFD") */
|
||||||
|
} gfdlabel;
|
||||||
|
|
||||||
|
/* mfd/gfd offsets */
|
||||||
|
#define gfddcntbl 1 /* block with DCN pointer table */
|
||||||
|
#define gfdatrtbl 2 /* block with attribute link table */
|
||||||
|
|
||||||
|
/* For RDS0, the "GFD NE" and "GFD AE" live in the MFD ([1,1] directory)
|
||||||
|
* which starts at DCN 1. They are in a linked list, possibly mixed
|
||||||
|
* with files, in the usual UFD fashion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct { /* GFD name entry */
|
||||||
|
word16 ulnk; /* Link to attributes */
|
||||||
|
word16 unam[3]; /* PPN and password */
|
||||||
|
byte ustat; /* Status byte */
|
||||||
|
byte uprot; /* Protection code */
|
||||||
|
word16 uacnt; /* Access count */
|
||||||
|
word16 uaa; /* Link to accounting entry */
|
||||||
|
word16 uar; /* Dcn of start of UFD */
|
||||||
|
} gfdne;
|
||||||
|
|
||||||
|
typedef struct { /* GFD accounting entry */
|
||||||
|
word16 ulnk; /* Flags */
|
||||||
|
word16 mcpu; /* Accum cpu time (LSB) */
|
||||||
|
word16 mcon; /* Accum connect time */
|
||||||
|
word16 mkct; /* Accum kct's (LSB) */
|
||||||
|
word16 mdev; /* Accum device time */
|
||||||
|
word16 mmsb; /* Accum cpu time and kct's (MSB's) */
|
||||||
|
word16 mdper; /* Disk quota */
|
||||||
|
word16 uclus; /* UFD cluster size */
|
||||||
|
} gfdae;
|
||||||
|
|
||||||
|
typedef struct { /* UFD label entry */
|
||||||
|
word16 ulnk; /* Link to first name block in UFD */
|
||||||
|
int16 fill2; /* Reserved (-1) */
|
||||||
|
word16 fill3[4]; /* Reserved (0) */
|
||||||
|
byte lppn[2]; /* PPN [x,y] */
|
||||||
|
word16 lid; /* Identification (RAD50 "UFD") */
|
||||||
|
} ufdlabel;
|
||||||
|
|
||||||
|
typedef struct { /* UFD name entry */
|
||||||
|
word16 ulnk; /* Link to next name entry */
|
||||||
|
word16 unam[3]; /* File name and extension */
|
||||||
|
byte ustat; /* Status byte */
|
||||||
|
byte uprot; /* Protection code */
|
||||||
|
word16 uacnt; /* Access count */
|
||||||
|
word16 uaa; /* Link to UFD accounting entry */
|
||||||
|
word16 uar; /* Link to retrieval entries */
|
||||||
|
} ufdne;
|
||||||
|
|
||||||
|
typedef struct { /* UFD accounting entry */
|
||||||
|
word16 ulnk; /* Link to attributes and flags */
|
||||||
|
word16 udla; /* Date of last access (or write) */
|
||||||
|
word16 usiz; /* File size */
|
||||||
|
word16 udc; /* Date of creation */
|
||||||
|
word16 utc; /* Time of creation */
|
||||||
|
word16 urts[2]; /* File's run-time system name or 0/MSB size */
|
||||||
|
word16 uclus; /* File cluster size */
|
||||||
|
} ufdae;
|
||||||
|
|
||||||
|
typedef struct { /* UFD first RMS attribute blockette */
|
||||||
|
word16 ulnk; /* Link to second attributes blockette */
|
||||||
|
word16 fa_typ; /* File type (rfm, org, rat) */
|
||||||
|
word16 fa_rsz; /* Record size */
|
||||||
|
word16 fa_siz[2]; /* File size (32 bits) */
|
||||||
|
word16 fa_eof[2]; /* File EOF block number (32 bits) */
|
||||||
|
word16 fa_eofb; /* EOF byte offset */
|
||||||
|
} ufdrms1;
|
||||||
|
|
||||||
|
#define fa_rfm 0000007 /* record format field in fa_typ */
|
||||||
|
#define rf_udf 0 /* undefined organization */
|
||||||
|
#define rf_fix 1 /* fixed length records */
|
||||||
|
#define rf_var 2 /* variable length records */
|
||||||
|
#define rf_vfc 3 /* variable with fixed control header */
|
||||||
|
#define rf_stm 4 /* stream (cr/lf delimiter) */
|
||||||
|
#define fa_org 0000070 /* file organization format in fa_typ */
|
||||||
|
#define fo_seq 000 /* sequential organization */
|
||||||
|
#define fo_rel 020 /* relative organization */
|
||||||
|
#define fo_idx 040 /* indexed organization */
|
||||||
|
#define fa_rat 0007700 /* record attribute flags */
|
||||||
|
#define ra_ftn 0000400 /* fortran carriage control */
|
||||||
|
#define ra_imp 0001000 /* implied carriage control */
|
||||||
|
#define ra_spn 0004000 /* no-span records */
|
||||||
|
|
||||||
|
typedef struct { /* UFD second RMS attribute blockette */
|
||||||
|
word16 ulnk; /* Link (reserved) */
|
||||||
|
byte fa_bkt; /* Bucket size */
|
||||||
|
byte fa_hsz; /* Header size */
|
||||||
|
word16 fa_msz; /* Max record size */
|
||||||
|
word16 fa_ext; /* Default extension amount */
|
||||||
|
word16 filler[4]; /* Reserved */
|
||||||
|
} ufdrms2;
|
||||||
|
|
||||||
|
/* All directory attributes are new as of RDS1.1 or later */
|
||||||
|
|
||||||
|
typedef struct { /* MFD/GFD attribute entry */
|
||||||
|
word16 ulnk; /* Link to next, flags */
|
||||||
|
byte uatyp; /* Type */
|
||||||
|
byte uadat[16-3]; /* Data */
|
||||||
|
} uattr;
|
||||||
|
|
||||||
|
/* Time of creation flag bit definitions */
|
||||||
|
|
||||||
|
#define utc_tm 0003777 /* Bits needed for the time field */
|
||||||
|
#define utc_ig 0004000 /* IGNORE flag (RDS1.2) */
|
||||||
|
#define utc_bk 0010000 /* NOBACKUP flag (RDS1.2) */
|
||||||
|
/* Other bits reserved */
|
||||||
|
|
||||||
|
typedef struct { /* UFD retrieval entry */
|
||||||
|
word16 ulnk; /* Link to next retrieval entry */
|
||||||
|
word16 uent[7]; /* The dcn's of the cluster(s) */
|
||||||
|
} ufdre;
|
||||||
|
|
||||||
|
/* Bit assignments in ustat and f$stat */
|
||||||
|
|
||||||
|
#define us_out 0001 /* File is 'out of sat' (historical) */
|
||||||
|
#define us_plc 0002 /* File is "placed" */
|
||||||
|
#define us_wrt 0004 /* Write access given out (not on disk if large files) */
|
||||||
|
#define us_upd 0010 /* File open in update mode (not on disk if large files) */
|
||||||
|
#define us_nox 0020 /* No file extending allowed (contiguous) */
|
||||||
|
#define us_nok 0040 /* No delete and/or rename allowed */
|
||||||
|
#define us_ufd 0100 /* Entry is MFD type entry */
|
||||||
|
#define us_del 0200 /* File marked for deletion */
|
||||||
|
|
||||||
|
/* Bit assignments in uprot and f$prot */
|
||||||
|
|
||||||
|
#define up_rpo 0001 /* Read protect against owner */
|
||||||
|
#define up_wpo 0002 /* Write " " " */
|
||||||
|
#define up_rpg 0004 /* Read " " group */
|
||||||
|
#define up_wpg 0010 /* Write " " " */
|
||||||
|
#define up_rpw 0020 /* Read " " world */
|
||||||
|
#define up_wpw 0040 /* Write " " " */
|
||||||
|
#define up_run 0100 /* Executable file */
|
||||||
|
#define up_prv 0200 /* Clear on delete, privileged if executable file */
|
||||||
|
|
||||||
|
/* Link and flag word fields */
|
||||||
|
|
||||||
|
#define ul_use 0000001 /* On to ensure entry is "in use" */
|
||||||
|
#define ul_bad 0000002 /* Some bad block exists in file */
|
||||||
|
#define ul_che 0000004 /* Cache (name entry) or sequential (accting entry) */
|
||||||
|
#define ul_cln 0000010 /* Reserved for 'clean' */
|
||||||
|
#define ul_eno 0000760 /* Entry offset within block (5 bits) */
|
||||||
|
#define ul_clo 0007000 /* Cluster offset within UFD (3 bits) */
|
||||||
|
#define ul_blo 0170000 /* Block offset within cluster (4 bits) */
|
||||||
|
#define sl_clo 9 /* Shift count for ul_clo field */
|
||||||
|
#define sl_blo 12 /* shift count for ul_blo field */
|
||||||
|
|
||||||
|
#define LINKBITS (ul_eno | ul_clo | ul_blo) /* bits to test for null */
|
||||||
|
#define NULLINK(l) (((l) & LINKBITS) == 0)
|
||||||
|
|
||||||
|
/* Account attribute codes */
|
||||||
|
|
||||||
|
#define aa_quo 1 /* Quotas */
|
||||||
|
#define aa_prv 2 /* Privilege masks */
|
||||||
|
#define aa_pas 3 /* Password */
|
||||||
|
#define aa_dat 4 /* Date/time recording (creation, change, login) */
|
||||||
|
#define aa_nam 5 /* User name (RDS1.2) */
|
||||||
|
#define aa_qt2 6 /* Quotas part 2 (RDS1.2) */
|
||||||
|
|
||||||
|
/* Attribute blockette layouts */
|
||||||
|
|
||||||
|
typedef struct { /* Disk Quota Attribute Blockette */
|
||||||
|
word16 ulnk; /* Link to next, flags */
|
||||||
|
byte uatyp; /* Type */
|
||||||
|
byte aq_djb; /* Detached job quota */
|
||||||
|
word16 aq_lol; /* Logged out quota (LSB) */
|
||||||
|
word16 aq_lil; /* Logged in quota (LSB) */
|
||||||
|
byte aq_lim; /* Logged in quota (MSB) */
|
||||||
|
byte aq_lom; /* Logged out quota (MSB) */
|
||||||
|
byte aq_rsm; /* Reserved */
|
||||||
|
byte aq_crm; /* Current usage (MSB) */
|
||||||
|
word16 aq_rsl; /* Reserved */
|
||||||
|
word16 aq_crl; /* Current usage (LSB) */
|
||||||
|
} ua_quo;
|
||||||
|
|
||||||
|
#define privsz 6 /* number of privilege bytes */
|
||||||
|
|
||||||
|
typedef struct { /* Privilege mask data */
|
||||||
|
word16 ulnk; /* Link to next, flags */
|
||||||
|
byte uatyp; /* Type */
|
||||||
|
byte fill1; /* Filler */
|
||||||
|
byte ap_prv[privsz]; /* Authorized privileges */
|
||||||
|
byte fill2[020-privsz-1-3]; /* Filler */
|
||||||
|
} ua_prv;
|
||||||
|
|
||||||
|
typedef struct { /* Date/time data */
|
||||||
|
word16 ulnk; /* Link to next, flags */
|
||||||
|
byte uatyp; /* Type */
|
||||||
|
byte at_kb; /* Keyboard of last login */
|
||||||
|
word16 at_lda; /* Date of last login */
|
||||||
|
word16 at_lti; /* Time of last login */
|
||||||
|
word16 at_pda; /* Date of last password16 change */
|
||||||
|
word16 at_pti; /* Time of last password change */
|
||||||
|
word16 at_cda; /* Date of creation */
|
||||||
|
word16 at_exp; /* Expiration date (RDS1.2) */
|
||||||
|
/* Account creation time (RDS1.1 only) */
|
||||||
|
} ua_dat;
|
||||||
|
|
||||||
|
/* Fields within at_lti */
|
||||||
|
#define at_msk 0003777 /* Bits needed for the time field */
|
||||||
|
#define at_npw 0004000 /* No password required */
|
||||||
|
/* Other bits reserved */
|
||||||
|
|
||||||
|
/* Fields within at_pti */
|
||||||
|
/* at_msk 0003777 * Bits needed for the time field */
|
||||||
|
#define at_nlk 0004000 /* Not readable password if set */
|
||||||
|
#define at_ndl 0010000 /* No-dialups flag */
|
||||||
|
#define at_nnt 0020000 /* No-network flag */
|
||||||
|
#define at_nlg 0040000 /* No-login account */
|
||||||
|
#define at_cap 0100000 /* Captive account */
|
||||||
|
|
||||||
|
typedef struct { /* Second quota and date/time block */
|
||||||
|
word16 ulnk; /* Link to next, flags */
|
||||||
|
byte uatyp; /* Type */
|
||||||
|
byte a2_job; /* Total job quota */
|
||||||
|
word16 a2_rib; /* RIB quota */
|
||||||
|
word16 a2_msg; /* Message limit quota */
|
||||||
|
word16 fill1; /* Reserved */
|
||||||
|
byte fill2; /* Reserved */
|
||||||
|
byte a2_pwf; /* Password failed count */
|
||||||
|
word16 a2_ndt; /* Date of Last non-interactive login */
|
||||||
|
word16 a2_nti; /* Time of Last non-interactive login */
|
||||||
|
} ua_qt2;
|
||||||
45
extracters/rstsflx/flx.dep
Normal file
45
extracters/rstsflx/flx.dep
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
rstsflx.o: rstsflx.c version.h flx.h rstsflx.h platform.h fldef.h \
|
||||||
|
scancmd.h diskio.h
|
||||||
|
fip.o: fip.c flx.h rstsflx.h platform.h fldef.h fip.h diskio.h rtime.h \
|
||||||
|
filename.h
|
||||||
|
rtime.o: rtime.c flx.h rstsflx.h platform.h rtime.h fldef.h
|
||||||
|
filename.o: filename.c flx.h rstsflx.h platform.h filename.h fldef.h
|
||||||
|
doget.o: doget.c flx.h rstsflx.h platform.h fldef.h doget.h fip.h \
|
||||||
|
filename.h fileio.h scancmd.h
|
||||||
|
dolist.o: dolist.c flx.h rstsflx.h platform.h fldef.h dolist.h fip.h \
|
||||||
|
rtime.h filename.h scancmd.h
|
||||||
|
doalloc.o: doalloc.c flx.h rstsflx.h platform.h fldef.h doalloc.h fip.h
|
||||||
|
docomp.o: docomp.c flx.h rstsflx.h platform.h fldef.h docomp.h diskio.h \
|
||||||
|
fip.h
|
||||||
|
dotype.o: dotype.c flx.h rstsflx.h platform.h fldef.h dotype.h fip.h \
|
||||||
|
filename.h fileio.h scancmd.h
|
||||||
|
doput.o: doput.c flx.h rstsflx.h platform.h fldef.h doput.h fip.h \
|
||||||
|
filename.h fileio.h scancmd.h
|
||||||
|
dodump.o: dodump.c flx.h rstsflx.h platform.h fldef.h dodump.h fip.h \
|
||||||
|
filename.h diskio.h fileio.h scancmd.h
|
||||||
|
dodelete.o: dodelete.c flx.h rstsflx.h platform.h fldef.h dodelete.h \
|
||||||
|
fip.h filename.h fileio.h scancmd.h
|
||||||
|
dorename.o: dorename.c flx.h rstsflx.h platform.h fldef.h dorename.h \
|
||||||
|
fip.h filename.h fileio.h scancmd.h
|
||||||
|
dorts.o: dorts.c flx.h rstsflx.h platform.h fldef.h dorts.h fip.h \
|
||||||
|
filename.h fileio.h scancmd.h
|
||||||
|
doprot.o: doprot.c flx.h rstsflx.h platform.h fldef.h doprot.h fip.h \
|
||||||
|
filename.h fileio.h scancmd.h
|
||||||
|
dodir.o: dodir.c flx.h rstsflx.h platform.h fldef.h dodir.h fip.h \
|
||||||
|
filename.h
|
||||||
|
doident.o: doident.c flx.h rstsflx.h platform.h fldef.h doident.h fip.h \
|
||||||
|
rtime.h
|
||||||
|
doinit.o: doinit.c flx.h rstsflx.h platform.h fldef.h doinit.h fip.h \
|
||||||
|
diskio.h filename.h
|
||||||
|
dohook.o: dohook.c flx.h rstsflx.h platform.h fldef.h silfmt.h dohook.h \
|
||||||
|
fip.h filename.h fileio.h diskio.h
|
||||||
|
scancmd.o: scancmd.c flx.h rstsflx.h platform.h fldef.h silfmt.h \
|
||||||
|
scancmd.h fip.h diskio.h filename.h doalloc.h doget.h doident.h \
|
||||||
|
dolist.h dotype.h dodump.h doput.h dodelete.h dorename.h dorts.h \
|
||||||
|
dodir.h doprot.h doinit.h dohook.h docomp.h doclean.h
|
||||||
|
doclean.o: doclean.c flx.h rstsflx.h platform.h fldef.h diskio.h \
|
||||||
|
filename.h doclean.h fip.h rtime.h
|
||||||
|
fileio.o: fileio.c flx.h rstsflx.h platform.h fldef.h fileio.h filename.h \
|
||||||
|
diskio.h fip.h
|
||||||
|
diskio.o: diskio.c flx.h rstsflx.h platform.h diskio.h absio.h
|
||||||
|
unxabsio.o: unxabsio.c flx.h rstsflx.h platform.h absio.h
|
||||||
BIN
extracters/rstsflx/flx.doc
Normal file
BIN
extracters/rstsflx/flx.doc
Normal file
Binary file not shown.
227
extracters/rstsflx/flx.h
Normal file
227
extracters/rstsflx/flx.h
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
/* rstsflx common definitions */
|
||||||
|
|
||||||
|
/* define BROKEN_ANSI when compiling on systems that have a defective
|
||||||
|
* set of include files, like SunOS 4.1
|
||||||
|
*/
|
||||||
|
#ifdef BROKEN_ANSI
|
||||||
|
#define EXIT_SUCCESS 0
|
||||||
|
#define EXIT_FAILURE 1
|
||||||
|
#define strtoul strtol
|
||||||
|
#define SEEK_SET 0
|
||||||
|
#define FILENAME_MAX 160
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Apple doesn't define __unix__ */
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#define __unix__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "rstsflx.h" /* include mainline's prototypes */
|
||||||
|
|
||||||
|
/* macro to map a struct onto a given offset of fibuf */
|
||||||
|
|
||||||
|
#define use(str,off) ((str *)(&fibuf[(off)]))
|
||||||
|
#define clumap (use(fdcm,BLKSIZE-sizeof(fdcm)))
|
||||||
|
#define fibufw ((word16 *)(&fibuf[0]))
|
||||||
|
|
||||||
|
/* block numbering conversions */
|
||||||
|
|
||||||
|
#define dcntolbn(dcn) ((dcn)*dcs) /* convert DCN to LBN */
|
||||||
|
#define pcntolbn(pcn) ((pcn)*pcs+dcs) /* convert PCN to LBN */
|
||||||
|
#define lbntodcn(lbn) ((lbn)/dcs) /* convert LBN to DCN */
|
||||||
|
#define lbntopcn(lbn) (((lbn)-dcs)/pcs) /* convert LBN to PCN */
|
||||||
|
#define dcntopcn(dcn) (((dcn)-1)*dcs/pcs) /* convert DCN to PCN */
|
||||||
|
#define pcntodcn(pcn) ((pcn)*pcs/dcs+1) /* convert PCN to DCN */
|
||||||
|
|
||||||
|
/* other handy macros */
|
||||||
|
|
||||||
|
#define UP(x,y) (((x)+(y)-1)&(-(y))) /* round x up to mult of y */
|
||||||
|
#define DOWN(x,y) ((x)&(-(y))) /* round x down to mult of y */
|
||||||
|
|
||||||
|
/* buffer marking */
|
||||||
|
|
||||||
|
#define MARKS (womsat = TRUE) /* mark SATT dirty */
|
||||||
|
#define MARKF (fiblkw = TRUE) /* mark FIBUF dirty */
|
||||||
|
|
||||||
|
/* common constants */
|
||||||
|
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
/* Useful general data types
|
||||||
|
*
|
||||||
|
* Note: "int" is being used here whenever 16 bits suffice;
|
||||||
|
* "long int" where 32 bits are needed. In some platforms,
|
||||||
|
* we'll end up with more bits than that, which is not a problem.
|
||||||
|
* Whenever data types of a specific size (rather than just a
|
||||||
|
* minimum size) are needed, the types defined in platform.h are used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned int word;
|
||||||
|
typedef unsigned long int lword;
|
||||||
|
|
||||||
|
/* bring in platform specific type definitions */
|
||||||
|
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
/* lengths of various strings, including null terminator */
|
||||||
|
|
||||||
|
#define NAMELEN 11 /* file name.ext */
|
||||||
|
#define DATELEN 12 /* Y2k style date (4 digit year) */
|
||||||
|
#define RTIMELEN 9 /* RSTS style time */
|
||||||
|
#define RTSLEN 7 /* Runtime system name */
|
||||||
|
|
||||||
|
/* buffer sizes */
|
||||||
|
|
||||||
|
#define BLKSIZE 512 /* one disk block */
|
||||||
|
#define LSIZE 512 /* length of line buffer */
|
||||||
|
|
||||||
|
/* error codes; sometimes return codes, sometimes fatal error codes */
|
||||||
|
|
||||||
|
#define BADRE 0
|
||||||
|
#define BADLINK 1
|
||||||
|
#define BADBLK 3
|
||||||
|
#define BADDCS 4
|
||||||
|
#define CORRUPT 5
|
||||||
|
#define NOMEM 6
|
||||||
|
#define INTERNAL 7
|
||||||
|
#define DIRTY 8
|
||||||
|
#define ROPACK 9
|
||||||
|
#define DISKIO 10
|
||||||
|
#define NOMSG 11 /* used when caller generates the message */
|
||||||
|
#define BADPAK 12 /* pack cannot be rebuilt */
|
||||||
|
|
||||||
|
#define rabort(code) doabort (code, __FILE__, __LINE__)
|
||||||
|
|
||||||
|
/* file scan codes for "dofiles" */
|
||||||
|
|
||||||
|
#define NOTNULL 0
|
||||||
|
#define NULLISNULL 1
|
||||||
|
#define NULLISWILD 2
|
||||||
|
|
||||||
|
/* open modes */
|
||||||
|
|
||||||
|
#define DREADMODE "rb" /* read only disk access */
|
||||||
|
#define DWRITEMODE "r+b" /* read/write disk access */
|
||||||
|
#define DCREATEMODE "w+b" /* creating new container file */
|
||||||
|
|
||||||
|
/* data types */
|
||||||
|
|
||||||
|
typedef struct { /* switch flag table layout */
|
||||||
|
char *ascii;
|
||||||
|
char *bswitch; /* binary or brief (in list) */
|
||||||
|
char *clusiz;
|
||||||
|
char *contig;
|
||||||
|
char *create;
|
||||||
|
char *rstsdevice;
|
||||||
|
char *debug;
|
||||||
|
char *end;
|
||||||
|
char *full;
|
||||||
|
char *merge;
|
||||||
|
char *oattr;
|
||||||
|
char *odt;
|
||||||
|
char *offset;
|
||||||
|
char *prot;
|
||||||
|
char *query;
|
||||||
|
char *replace;
|
||||||
|
char *rmsvar;
|
||||||
|
char *rmsfix;
|
||||||
|
char *rmsstm;
|
||||||
|
char *size;
|
||||||
|
char *disksize;
|
||||||
|
char *start;
|
||||||
|
char *summary;
|
||||||
|
char *tree;
|
||||||
|
char *unprot;
|
||||||
|
char *verbose;
|
||||||
|
char *wide;
|
||||||
|
char *overwrite;
|
||||||
|
char *narrow;
|
||||||
|
char *user;
|
||||||
|
char *hex;
|
||||||
|
} swtab;
|
||||||
|
|
||||||
|
#define f_name 1 /* name present */
|
||||||
|
#define f_namw 2 /* name wild */
|
||||||
|
#define f_ext 4 /* extension present */
|
||||||
|
#define f_extw 8 /* extension wild */
|
||||||
|
#define f_ppn 16 /* PPN present */
|
||||||
|
#define f_ppnw 32 /* PPN wild */
|
||||||
|
#define f_prot 64 /* protection code present */
|
||||||
|
|
||||||
|
#define F_WILD (f_namw | f_extw | f_ppnw) /* something wild if set */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long size; /* filesize */
|
||||||
|
int clusiz; /* cluster size */
|
||||||
|
int flags; /* parse flags */
|
||||||
|
word nlink; /* link to NE */
|
||||||
|
word alink; /* link to AE */
|
||||||
|
word rlink; /* link to first RE */
|
||||||
|
word rmslink; /* link to attributes */
|
||||||
|
word recfmt; /* record format and flags for fileio */
|
||||||
|
word recsiz; /* record size (if fixed records) */
|
||||||
|
word rechdrsiz; /* header size if vfc */
|
||||||
|
long eofblk; /* EOF block number from RMS */
|
||||||
|
int eofbyte; /* EOF byte from RMS */
|
||||||
|
word currecsiz; /* size of current (split across buffers) rec */
|
||||||
|
word recskip; /* amount to skip for vfc */
|
||||||
|
char *currec; /* current record pointer */
|
||||||
|
byte stat; /* saved file status */
|
||||||
|
byte prot; /* saved file protection */
|
||||||
|
byte proj; /* supplied PPN as two bytes */
|
||||||
|
byte prog;
|
||||||
|
char name[NAMELEN]; /* supplied file name.ext */
|
||||||
|
byte newprot; /* protection code from filespec */
|
||||||
|
byte cproj; /* current PPN as two bytes */
|
||||||
|
byte cprog;
|
||||||
|
char cname[NAMELEN]; /* current name.ext */
|
||||||
|
} firqb; /* well, sort of... :-) holds parsed filename */
|
||||||
|
|
||||||
|
/* typedefs for procedure datatypes, used to work around cc -protoi bug */
|
||||||
|
|
||||||
|
typedef void (*commandaction)(firqb *);
|
||||||
|
typedef void (*commandhandler)(int, char **);
|
||||||
|
typedef void (*iohandler)(long, long, void *);
|
||||||
|
|
||||||
|
/* external references: */
|
||||||
|
|
||||||
|
extern swtab sw; /* switch and argument pointers */
|
||||||
|
extern char *progname; /* name of this program */
|
||||||
|
extern byte fibuf[BLKSIZE]; /* buffer for directories */
|
||||||
|
extern byte *sattbufp; /* pointer to SATT buffer */
|
||||||
|
extern int sattsize; /* size of SATT in bytes */
|
||||||
|
extern long sattlbn; /* start LBN of SATT */
|
||||||
|
extern long satptr; /* current allocation pointer (PCN) */
|
||||||
|
extern int womsat; /* TRUE if SATT needs to be written */
|
||||||
|
extern long fiblk; /* current block in FIBUF */
|
||||||
|
extern int fiblkw; /* TRUE if FIBUF needs to be written */
|
||||||
|
extern long i,k; /* current directory entry pointers */
|
||||||
|
extern int pcs; /* pack clustersize */
|
||||||
|
extern long pcns; /* number of pack clusters on this disk */
|
||||||
|
extern int pflags; /* pack flags */
|
||||||
|
extern int plevel; /* pack structure rev level */
|
||||||
|
extern long mfddcn; /* DCN of start of MFD */
|
||||||
|
extern long mfdlbn; /* LBN of start of MFD */
|
||||||
|
extern char pname[7]; /* pack ID in ascii */
|
||||||
|
extern int dcs; /* device clustersize */
|
||||||
|
extern long diskblocks; /* device block count */
|
||||||
|
extern const char *rname; /* file name of disk/container */
|
||||||
|
extern const char *rssize; /* and size, as a string */
|
||||||
|
extern long rsize; /* size of RSTS disk or container file */
|
||||||
|
extern int absflag; /* flag for absolute I/O */
|
||||||
|
extern FILE *rstsfile; /* file for the rsts disk/container */
|
||||||
|
extern char **fargv; /* array of pointers to arguments */
|
||||||
|
extern int fargc; /* and count of how many we found */
|
||||||
|
extern char *iobuf; /* general file I/O buffer */
|
||||||
|
extern long iobufsize; /* size of the buffer */
|
||||||
|
extern int entptr; /* current directory entry allocation pointer */
|
||||||
|
extern word nextlink; /* link to next file (ulnk of current) */
|
||||||
|
extern word prevlink; /* link to predecessor file */
|
||||||
|
extern word nextppnlink; /* link to next PPN for RDS 0 */
|
||||||
|
extern word prevppnlink; /* link to prececessor of PPN for RDS 0 */
|
||||||
|
extern long curgfd; /* LBN of start of current GFD */
|
||||||
|
extern char *defdevice; /* default RSTS device name */
|
||||||
|
extern char *defsize; /* and size */
|
||||||
|
extern long newhistitems; /* new history items this session */
|
||||||
BIN
extracters/rstsflx/flx.pdf
Normal file
BIN
extracters/rstsflx/flx.pdf
Normal file
Binary file not shown.
233
extracters/rstsflx/linuxabsio.c
Normal file
233
extracters/rstsflx/linuxabsio.c
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
/* absolute I/O support for Linux
|
||||||
|
*
|
||||||
|
* Paul Koning 95.01.05 created
|
||||||
|
* 99.12.31 updated for Linux (from generic unxabsio.c)
|
||||||
|
* 00.01.03 added size determination and geometry test
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <asm/ioctl.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/hdreg.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "absio.h"
|
||||||
|
|
||||||
|
/* this routine is called to scan a supplied container file/device
|
||||||
|
* name. If the name refers to a real disk, then absflag is set
|
||||||
|
* and rsize is set to the device size. Otherwise, no action is taken.
|
||||||
|
*
|
||||||
|
* More precisely, there are three things this routine may want to do,
|
||||||
|
* depending on the OS and the name supplied.
|
||||||
|
*
|
||||||
|
* If, for the specified name, the absolute I/O routines in this module
|
||||||
|
* need to be called, then absflag should be set to TRUE, and rsize must
|
||||||
|
* be set to the size of the device. Otherwise, absflag should be left
|
||||||
|
* alone (which leaves it FALSE); that way the other absolute I/O routines
|
||||||
|
* in this module will not be called and standard C I/O is used instead.
|
||||||
|
*
|
||||||
|
* If, for the specified name, "fstat" will not return a size (i.e., returns
|
||||||
|
* zero) then rsize must specify the correct size. This can be set in this
|
||||||
|
* module, based on OS specific operations, or it can simply be left
|
||||||
|
* unchanged, in which case it has to be supplied by the user.
|
||||||
|
*
|
||||||
|
* For example, in Unix the fstat function doesn't return a size for raw
|
||||||
|
* devices (it returns zero) but the stdio routines are otherwise perfectly
|
||||||
|
* suitable. So this routine does NOT set absflag since no special abs I/O
|
||||||
|
* routines are needed. It does check the return from stat(); if this
|
||||||
|
* indicates a raw device, it checks that rsize has been supplied and
|
||||||
|
* complains if not. Note that the code below does not attempt to obtain
|
||||||
|
* the device size, since there is no portable Unix way of doing this that
|
||||||
|
* I know of.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static dev_t rdev;
|
||||||
|
static int floppy;
|
||||||
|
static byte trackbuf[BLKSIZE * 10];
|
||||||
|
static int curtrack = -1;
|
||||||
|
static int writecurrent;
|
||||||
|
|
||||||
|
static void makechs_rx50 (int block, int *trk, int *sec)
|
||||||
|
{
|
||||||
|
int t, s;
|
||||||
|
|
||||||
|
t = block / 10;
|
||||||
|
s = block % 10 + 1;
|
||||||
|
if (s < 6) s = (s - 1) * 2 + 1;
|
||||||
|
else s = (s - 5) * 2;
|
||||||
|
s += t * 2;
|
||||||
|
while (s > 10) s -= 10;
|
||||||
|
t++;
|
||||||
|
if (t == 80) t = 0; /* wrap around last 10 blocks */
|
||||||
|
*trk = t;
|
||||||
|
*sec = s - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flushtrack (void)
|
||||||
|
{
|
||||||
|
if (writecurrent)
|
||||||
|
{
|
||||||
|
lseek (floppy, curtrack * sizeof (trackbuf), SEEK_SET);
|
||||||
|
if (write (floppy, trackbuf, sizeof (trackbuf)) !=
|
||||||
|
sizeof (trackbuf))
|
||||||
|
doabort (DISKIO, __FILE__, __LINE__);
|
||||||
|
writecurrent = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gettrack (int track)
|
||||||
|
{
|
||||||
|
if (track != curtrack)
|
||||||
|
{
|
||||||
|
flushtrack ();
|
||||||
|
lseek (floppy, track * sizeof (trackbuf), SEEK_SET);
|
||||||
|
if (read (floppy, trackbuf, sizeof (trackbuf)) !=
|
||||||
|
sizeof (trackbuf))
|
||||||
|
doabort (DISKIO, __FILE__, __LINE__);
|
||||||
|
curtrack = track;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void absname (const char *rname)
|
||||||
|
{
|
||||||
|
struct stat sbuf;
|
||||||
|
int fd, i = -1;
|
||||||
|
long size;
|
||||||
|
struct hd_geometry loc;
|
||||||
|
|
||||||
|
if (stat (rname, &sbuf)) return; /* try to get info about device */
|
||||||
|
diskblocks = UP(sbuf.st_size,BLKSIZE) / BLKSIZE;
|
||||||
|
if (diskblocks == 0)
|
||||||
|
{
|
||||||
|
if (S_ISBLK(sbuf.st_mode))
|
||||||
|
{
|
||||||
|
fd = open (rname, O_RDONLY);
|
||||||
|
if (fd >= 0)
|
||||||
|
{
|
||||||
|
i = ioctl (fd, BLKGETSIZE, &size);
|
||||||
|
if (i >= 0)
|
||||||
|
diskblocks = size;
|
||||||
|
i = ioctl (fd, HDIO_GETGEO, &loc);
|
||||||
|
close (fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
diskblocks = rsize;
|
||||||
|
/* user can always override autoconfigured size */
|
||||||
|
if (rsize != 0)
|
||||||
|
diskblocks = rsize;
|
||||||
|
if (diskblocks == 0)
|
||||||
|
{
|
||||||
|
printf ("Size not specified for RSTS disk %s\n", rname);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (diskblocks == 800 &&
|
||||||
|
(i < 0 ||
|
||||||
|
(loc.cylinders == 80 &&
|
||||||
|
loc.heads == 1)))
|
||||||
|
{
|
||||||
|
/* Looks like an RX50 floppy, turn on
|
||||||
|
* special handling
|
||||||
|
*/
|
||||||
|
if (sw.debug != NULL)
|
||||||
|
printf ("rx50 handling enabled\n");
|
||||||
|
absflag = TRUE;
|
||||||
|
}
|
||||||
|
/* if size wasn't overridden in command line,
|
||||||
|
* use the size we found
|
||||||
|
*/
|
||||||
|
if (rsize == 0)
|
||||||
|
rsize = diskblocks;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("RSTS disk container is null or not a block device\n");
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do any device open actions that may be needed.
|
||||||
|
* The "mode" argument is a standard C open mode. The return value is zero
|
||||||
|
* for success, non-zero for error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int absopen (const char *rname, const char *mode)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
if (strcmp (mode, DREADMODE) == 0)
|
||||||
|
flags = O_RDONLY;
|
||||||
|
else
|
||||||
|
flags = O_RDWR;
|
||||||
|
floppy = open (rname, flags);
|
||||||
|
return (floppy < 0);
|
||||||
|
curtrack = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do a seek on a device. You can do it here
|
||||||
|
* or as part of the read/write, whichever is easier. This routine is
|
||||||
|
* called only if the I/O operations are changing between read and write,
|
||||||
|
* or are not sequential. So you would want to do the work here if your
|
||||||
|
* OS does implicit sequential I/O, and make this a NOP if the read and
|
||||||
|
* write primitives take an explicit block number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void absseek (long block)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do any needed "close" actions for absolute I/O */
|
||||||
|
|
||||||
|
void absclose ()
|
||||||
|
{
|
||||||
|
flushtrack ();
|
||||||
|
close (floppy);
|
||||||
|
floppy = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do an absolute device read. The block number
|
||||||
|
* is supplied, even though it could have been derived from a preceding
|
||||||
|
* absseek call. This is because absseek is not called when sequential
|
||||||
|
* reads are done.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long absread (long sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
int track, tsec;
|
||||||
|
byte *b = (byte *) buffer;
|
||||||
|
|
||||||
|
while (count)
|
||||||
|
{
|
||||||
|
makechs_rx50 (sec, &track, &tsec);
|
||||||
|
gettrack (track);
|
||||||
|
memcpy (b, trackbuf + (BLKSIZE * tsec), BLKSIZE);
|
||||||
|
b += BLKSIZE;
|
||||||
|
count -= BLKSIZE;
|
||||||
|
sec++;
|
||||||
|
}
|
||||||
|
return 0; /* success */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do an absolute device write. */
|
||||||
|
|
||||||
|
long abswrite (long sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
int track, tsec;
|
||||||
|
byte *b = (byte *) buffer;
|
||||||
|
|
||||||
|
while (count)
|
||||||
|
{
|
||||||
|
makechs_rx50 (sec, &track, &tsec);
|
||||||
|
gettrack (track);
|
||||||
|
memcpy (trackbuf + (BLKSIZE * tsec), b, BLKSIZE);
|
||||||
|
writecurrent = TRUE;
|
||||||
|
b += BLKSIZE;
|
||||||
|
count -= BLKSIZE;
|
||||||
|
sec++;
|
||||||
|
}
|
||||||
|
return 0; /* success */
|
||||||
|
}
|
||||||
65
extracters/rstsflx/platform.h
Normal file
65
extracters/rstsflx/platform.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/* Platform specific typedefs
|
||||||
|
*
|
||||||
|
* This file defines data types used for accessing external data,
|
||||||
|
* i.e., stuff that is a specific size. You may need to edit this
|
||||||
|
* to make the field sizes work right for a particular platform.
|
||||||
|
* (Likely cases are noted below.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We'll try to figure out the sizes automatically. If this doesn't
|
||||||
|
* work right, define SHORTSIZE, LONGSIZE, and INTSIZE to equal the
|
||||||
|
* size (in bytes) of "short int", "long int" and "int" respectively.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifndef SHORTSIZE
|
||||||
|
#if (SHRT_MAX == 0x7fff)
|
||||||
|
#define SHORTSIZE 2
|
||||||
|
#else
|
||||||
|
#error "Please define SHORTSIZE"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef INTSIZE
|
||||||
|
#if (INT_MAX == 0x7fff)
|
||||||
|
#define INTSIZE 2
|
||||||
|
#else
|
||||||
|
#if (INT_MAX == 0x7fffffff)
|
||||||
|
#define INTSIZE 4
|
||||||
|
#else
|
||||||
|
#error "Please define INTSIZE"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LONGSIZE
|
||||||
|
#if (LONG_MAX == 0x7fffffff)
|
||||||
|
#define LONGSIZE 4
|
||||||
|
#else
|
||||||
|
#if (LONG_MAX == 0x7fffffffffffffff)
|
||||||
|
#define LONGSIZE 8
|
||||||
|
#else
|
||||||
|
#error "Please define LONGSIZE"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (SHORTSIZE == 2)
|
||||||
|
typedef unsigned short int word16;
|
||||||
|
typedef short int int16;
|
||||||
|
#else
|
||||||
|
#error "can't typedef 16-bit integers..."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (LONGSIZE == 4)
|
||||||
|
typedef unsigned long int lword32;
|
||||||
|
typedef long int long32;
|
||||||
|
#else
|
||||||
|
#if (INTSIZE == 4)
|
||||||
|
typedef unsigned int lword32;
|
||||||
|
typedef int long32;
|
||||||
|
#else
|
||||||
|
#error "can't typedef 32-bit integers..."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
166
extracters/rstsflx/rstsflx.c
Normal file
166
extracters/rstsflx/rstsflx.c
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/* Program to manipulate RSTS disks and disk container files */
|
||||||
|
|
||||||
|
#include "version.h" /* set version number */
|
||||||
|
|
||||||
|
/* system includes */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
#include <readline/readline.h>
|
||||||
|
#include <readline/history.h>
|
||||||
|
|
||||||
|
/* application specific includes */
|
||||||
|
|
||||||
|
#include "flx.h" /* common definitions */
|
||||||
|
#include "rstsflx.h"
|
||||||
|
#include "fldef.h" /* RSTS file system definitions */
|
||||||
|
#include "scancmd.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
|
||||||
|
#define IOBLOCKS 64
|
||||||
|
|
||||||
|
#define IOSIZE IOBLOCKS*BLKSIZE /* size of general I/O buffer */
|
||||||
|
#define IOEXTRA 10 /* number of extra bytes to allocate */
|
||||||
|
|
||||||
|
char *iobuf; /* pointer to buffer */
|
||||||
|
long iobufsize; /* and size we allocated */
|
||||||
|
char *cmdbuf; /* command line from readline */
|
||||||
|
|
||||||
|
static jmp_buf mainbuf;
|
||||||
|
|
||||||
|
void doabort(int status, const char *srcfile, int srcline)
|
||||||
|
{
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case BADRE:
|
||||||
|
printf ("Invalid retrieval entries for file\n");
|
||||||
|
break;
|
||||||
|
case BADBLK:
|
||||||
|
printf ("Block number out of range\n");
|
||||||
|
break;
|
||||||
|
case BADDCS:
|
||||||
|
printf ("Invalid DCS (device too big)\n");
|
||||||
|
break;
|
||||||
|
case CORRUPT:
|
||||||
|
printf ("Corrupt disk structure\n");
|
||||||
|
break;
|
||||||
|
case NOMEM:
|
||||||
|
printf ("malloc failure\n");
|
||||||
|
break;
|
||||||
|
case DIRTY:
|
||||||
|
printf ("Disk was not properly dismounted\n");
|
||||||
|
break;
|
||||||
|
case ROPACK:
|
||||||
|
printf ("Disk is read-only and -Write was not specified\n");
|
||||||
|
break;
|
||||||
|
case DISKIO:
|
||||||
|
printf ("I/O error on RSTS disk\n");
|
||||||
|
perror (progname); /* print details */
|
||||||
|
break;
|
||||||
|
case NOMSG:
|
||||||
|
/* no message, caller did that */
|
||||||
|
break;
|
||||||
|
case BADPAK:
|
||||||
|
printf ("Disk cannot be rebuilt\n");
|
||||||
|
break;
|
||||||
|
case INTERNAL:
|
||||||
|
default:
|
||||||
|
printf ("Internal error in program...\n");
|
||||||
|
}
|
||||||
|
/* if it looks like our problem, report where it happened */
|
||||||
|
if (status != DIRTY &&
|
||||||
|
status != ROPACK &&
|
||||||
|
status != NOMSG &&
|
||||||
|
status != BADPAK)
|
||||||
|
{
|
||||||
|
printf (" in module %s, line %d\n", srcfile, srcline);
|
||||||
|
}
|
||||||
|
longjmp (mainbuf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int cmdlen;
|
||||||
|
char **cmdargv = NULL; /* for scanning command line */
|
||||||
|
int cmdargc;
|
||||||
|
char *word;
|
||||||
|
void (*command)(int, char **);
|
||||||
|
int endian;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
/* set initial abort handler */
|
||||||
|
if (setjmp (mainbuf))
|
||||||
|
{
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
endian = 0;
|
||||||
|
*((char *)&endian) = 'A';
|
||||||
|
#if (INTSIZE == 2)
|
||||||
|
if (endian == 0x4100)
|
||||||
|
#else
|
||||||
|
if (endian == 0x41000000)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
printf ("FLX is not supported on big endian systems\n");
|
||||||
|
exit (EXIT_FAILURE); /* quit right now */
|
||||||
|
}
|
||||||
|
else if (endian != 0x41)
|
||||||
|
{
|
||||||
|
printf ("Error in endian test: %08x\n", endian);
|
||||||
|
exit (EXIT_FAILURE); /* quit right now */
|
||||||
|
}
|
||||||
|
progname = argv[0]; /* remember our name */
|
||||||
|
if ((iobuf = (char *) malloc (IOSIZE + IOEXTRA)) == NULL)
|
||||||
|
rabort (NOMEM);
|
||||||
|
iobufsize = IOSIZE;
|
||||||
|
initialize_readline (); /* Bind our completer. */
|
||||||
|
if (argc > 1) /* arguments on command line */
|
||||||
|
{
|
||||||
|
if ((command = scanargs (argc, argv)) == NULL)
|
||||||
|
exit (EXIT_FAILURE); /* scan arguments */
|
||||||
|
(*command) (fargc, fargv); /* go execute the command */
|
||||||
|
if (command != dodisk) return 0; /* done, exit */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setrname ();
|
||||||
|
printf ("FLX %s\nDefault RSTS disk is %s\n\n", IDENT, rname);
|
||||||
|
}
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* in the case of abort, we come back here */
|
||||||
|
setjmp (mainbuf);
|
||||||
|
cmdbuf = readline ("flx> ");
|
||||||
|
if (cmdbuf == NULL) break; /* control-d to quit */
|
||||||
|
s = stripwhite (cmdbuf);
|
||||||
|
if (*s)
|
||||||
|
{
|
||||||
|
add_history (s);
|
||||||
|
newhistitems++;
|
||||||
|
if (cmdargv != NULL) free (cmdargv);
|
||||||
|
if ((cmdargv = (char **) malloc (sizeof (char *))) == NULL)
|
||||||
|
rabort (NOMEM);
|
||||||
|
cmdargv[0] = progname; /* match conventions */
|
||||||
|
cmdargc = 1;
|
||||||
|
word = strtok (s, " ");
|
||||||
|
while (word != NULL)
|
||||||
|
{
|
||||||
|
cmdargv = (char **) realloc (cmdargv,
|
||||||
|
++cmdargc * sizeof (char *));
|
||||||
|
if (cmdargv == NULL) rabort (NOMEM);
|
||||||
|
cmdargv[cmdargc - 1] = word;
|
||||||
|
word = strtok (NULL, " ");
|
||||||
|
}
|
||||||
|
if (cmdargc == 1) continue; /* ignore null command */
|
||||||
|
/* go execute the command */
|
||||||
|
if ((command = scanargs (cmdargc, cmdargv)) != NULL)
|
||||||
|
(*command)(fargc, fargv);
|
||||||
|
}
|
||||||
|
free (cmdbuf);
|
||||||
|
}
|
||||||
|
doexit (0, NULL);
|
||||||
|
}
|
||||||
3
extracters/rstsflx/rstsflx.h
Normal file
3
extracters/rstsflx/rstsflx.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
extern void doabort(int status , const char * srcfile , int srcline)
|
||||||
|
__attribute__ ((noreturn));
|
||||||
|
extern int main(int argc , char **argv);
|
||||||
76
extracters/rstsflx/rtime.c
Normal file
76
extracters/rstsflx/rtime.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/* subroutines to handle RSTS date/time */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "rtime.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
|
||||||
|
static const char months[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||||
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||||
|
static int days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
|
||||||
|
char *cvtdate (word date, char *buf)
|
||||||
|
{
|
||||||
|
long day, yr;
|
||||||
|
int mon;
|
||||||
|
|
||||||
|
if (date == 0) { /* no date present */
|
||||||
|
memcpy (buf, " none ", DATELEN);
|
||||||
|
return (buf + DATELEN - 1); /* point to terminator */
|
||||||
|
}
|
||||||
|
yr = (long)date / 1000 + 1970;
|
||||||
|
day = date % 1000;
|
||||||
|
if (yr & 3) days[1] = 28;
|
||||||
|
else days[1] = 29; /* check for leap year */
|
||||||
|
for (mon = 0; mon < 12; mon++) {
|
||||||
|
if (day <= days[mon]) break;
|
||||||
|
day -= days[mon];
|
||||||
|
}
|
||||||
|
sprintf (buf, "%2ld-%3s-%04ld", day, months[mon], yr);
|
||||||
|
return (buf + DATELEN - 1); /* point to terminator */
|
||||||
|
}
|
||||||
|
|
||||||
|
char *cvttime (word time, char *buf)
|
||||||
|
{
|
||||||
|
int hour, min;
|
||||||
|
char m;
|
||||||
|
|
||||||
|
time &= at_msk; /* mask out any flags */
|
||||||
|
if (time == 0) { /* no time present */
|
||||||
|
memcpy (buf, " none ", RTIMELEN);
|
||||||
|
return (buf + RTIMELEN - 1); /* point to terminator */
|
||||||
|
}
|
||||||
|
time = 1440 - time; /* now time since midnight */
|
||||||
|
hour = time / 60;
|
||||||
|
min = time % 60;
|
||||||
|
if (hour >= 12) {
|
||||||
|
hour -= 12;
|
||||||
|
m = 'p';
|
||||||
|
} else m = 'a';
|
||||||
|
if (hour == 0) hour = 12;
|
||||||
|
sprintf (buf, "%2d:%02d %1cm", hour, min, m);
|
||||||
|
return (buf + RTIMELEN - 1); /* point to terminator */
|
||||||
|
}
|
||||||
|
|
||||||
|
word curdate () /* current date in rsts form */
|
||||||
|
{
|
||||||
|
struct tm *tmb;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
time (&now);
|
||||||
|
tmb = localtime (&now);
|
||||||
|
return ((tmb->tm_year - 70) * 1000 + tmb->tm_yday + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
word curtime () /* current time in rsts form */
|
||||||
|
{
|
||||||
|
struct tm *tmb;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
time (&now);
|
||||||
|
tmb = localtime (&now);
|
||||||
|
return (1440 - (tmb->tm_hour * 60 + tmb->tm_min));
|
||||||
|
}
|
||||||
12
extracters/rstsflx/rtime.h
Normal file
12
extracters/rstsflx/rtime.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
extern char * cvtdate(word date , char * buf);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern char * cvttime(word time , char * buf);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern word curdate(void);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern word curtime(void);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
577
extracters/rstsflx/scancmd.c
Normal file
577
extracters/rstsflx/scancmd.c
Normal file
@@ -0,0 +1,577 @@
|
|||||||
|
/* command line handling for rstsflx */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <readline/readline.h>
|
||||||
|
#include <readline/history.h>
|
||||||
|
|
||||||
|
/* Some unixes define this, some do not. */
|
||||||
|
#ifndef whitespace
|
||||||
|
#define whitespace(c) ((c) == ' ' || (c) == '\t')
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "fldef.h"
|
||||||
|
#include "silfmt.h"
|
||||||
|
#include "scancmd.h"
|
||||||
|
#include "fip.h"
|
||||||
|
#include "diskio.h"
|
||||||
|
#include "filename.h"
|
||||||
|
#include "doalloc.h"
|
||||||
|
#include "doget.h"
|
||||||
|
#include "doident.h"
|
||||||
|
#include "dolist.h"
|
||||||
|
#include "dotype.h"
|
||||||
|
#include "dodump.h"
|
||||||
|
#include "doput.h"
|
||||||
|
#include "dodelete.h"
|
||||||
|
#include "dorename.h"
|
||||||
|
#include "dorts.h"
|
||||||
|
#include "dodir.h"
|
||||||
|
#include "doprot.h"
|
||||||
|
#include "doinit.h"
|
||||||
|
#include "dohook.h"
|
||||||
|
#include "docomp.h"
|
||||||
|
#include "doclean.h"
|
||||||
|
|
||||||
|
swtab sw; /* switch flag table */
|
||||||
|
|
||||||
|
char *progname; /* name of program (argv[0]) */
|
||||||
|
char *cmdname; /* command name (argv[1]) */
|
||||||
|
char **fargv = NULL; /* array of pointers to arguments */
|
||||||
|
int fargc; /* and count of how many we found */
|
||||||
|
char *defdevice = NULL; /* default device name */
|
||||||
|
char *defsize = NULL; /* and size, as a string */
|
||||||
|
char *histfile; /* name of history file */
|
||||||
|
int hfilesize; /* size limit for history file */
|
||||||
|
long newhistitems; /* number of history items added */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *kw;
|
||||||
|
void (*hand)(int, char *[]);
|
||||||
|
} cmdent;
|
||||||
|
|
||||||
|
/* This routine is used to ask (if -query was specified) whether a file
|
||||||
|
* should be processed or not. It returns the answer, which is a character
|
||||||
|
* "y", "n" or "q". Note that the answer "a" is returned as "y" and
|
||||||
|
* further prompting is turned off.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char doquery (void (*printfile)(void *), void *name)
|
||||||
|
{
|
||||||
|
char answer[200];
|
||||||
|
char first;
|
||||||
|
|
||||||
|
if (sw.query == NULL) return ('y');
|
||||||
|
else {
|
||||||
|
for (;;) {
|
||||||
|
printf (" %s ", cmdname);
|
||||||
|
(*printfile) (name);
|
||||||
|
printf (" (y,n,a,q)? ");
|
||||||
|
fflush (stdout);
|
||||||
|
fgets (answer, sizeof (answer), stdin);
|
||||||
|
first = tolower (answer[0]);
|
||||||
|
if (first == 'q' || first == 'n' || first == 'y')
|
||||||
|
return (first);
|
||||||
|
if (first == 'a')
|
||||||
|
{
|
||||||
|
sw.query = NULL;
|
||||||
|
return ('y');
|
||||||
|
}
|
||||||
|
printf ("Invalid answer\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is used as the generic main loop for many command
|
||||||
|
* processing routines. The first two arguments define the list of
|
||||||
|
* command (file) arguments. The third argument controls what to do
|
||||||
|
* if the name part of the filespec is null:
|
||||||
|
* NOTNULL error -- "missing filename"
|
||||||
|
* NULLISWILD ok, substitute wildcard ("?") for the missing name
|
||||||
|
* NULLISNULL ok, leave the name part null, so it's a directory
|
||||||
|
* reference -- and if it's [*,*] or [n,*], treat
|
||||||
|
* that as access to MFD and GFD respectively (rather
|
||||||
|
* than wild directories).
|
||||||
|
*
|
||||||
|
* -query switch processing is provided in this routine. If a command
|
||||||
|
* does not want -query to have effect, it should override the switch to
|
||||||
|
* be absent (sw.query = NULL).
|
||||||
|
*/
|
||||||
|
|
||||||
|
void dofiles (int argc, char **argv, commandaction action, int nullflag)
|
||||||
|
{
|
||||||
|
int fnum, j;
|
||||||
|
firqb f;
|
||||||
|
int matches;
|
||||||
|
char answer;
|
||||||
|
|
||||||
|
if (argc == 0) printf ("Usage: %s %s files...\n", progname, cmdname);
|
||||||
|
for (fnum = 0; fnum < argc; fnum++)
|
||||||
|
{
|
||||||
|
if (!parse (argv[fnum], &f))
|
||||||
|
{
|
||||||
|
printf ("Invalid filespec %s\n", argv[fnum]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nullflag == NOTNULL && (f.flags & f_name) == 0)
|
||||||
|
{
|
||||||
|
printf ("Missing filename %s\n", argv[fnum]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (nullflag == NULLISWILD)
|
||||||
|
{
|
||||||
|
if ((f.flags & f_name) == 0)
|
||||||
|
for (j = 0; j < 6; j++) f.name[j] = '?';
|
||||||
|
f.flags |= f_name | f_namw;
|
||||||
|
if ((f.flags & f_ext) == 0)
|
||||||
|
{
|
||||||
|
f.name[7] = '?';
|
||||||
|
f.name[8] = '?';
|
||||||
|
f.name[9] = '?';
|
||||||
|
f.flags |= f_ext | f_extw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (nullflag == NULLISNULL && (f.flags & f_name) == 0)
|
||||||
|
{
|
||||||
|
if (f.prog == 255)
|
||||||
|
{
|
||||||
|
if (plevel == RDS0)
|
||||||
|
{
|
||||||
|
printf ("GFD or MFD not legal for RDS.0 pack\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (f.proj == 255)
|
||||||
|
{
|
||||||
|
printf ("Invalid directory spec\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matches = 0;
|
||||||
|
if (initfilescan (&f, gfddcntbl)) /* setup file scan */
|
||||||
|
{
|
||||||
|
answer = 'y'; /* dummy */
|
||||||
|
while (nextfile (&f))
|
||||||
|
{
|
||||||
|
matches++; /* found another */
|
||||||
|
answer = doquery ((void (*)(void *))printcurname, &f);
|
||||||
|
if (answer == 'q') break;
|
||||||
|
if (answer == 'n') continue;
|
||||||
|
(*action) (&f); /* do whatever */
|
||||||
|
}
|
||||||
|
if (answer == 'q') break; /* out two levels... */
|
||||||
|
}
|
||||||
|
if (matches == 0)
|
||||||
|
{
|
||||||
|
printf ("No files matching ");
|
||||||
|
printfqbname (&f);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dodisk (int argc, char **argv)
|
||||||
|
{
|
||||||
|
long rsize, tsize;
|
||||||
|
int flag;
|
||||||
|
|
||||||
|
if (defdevice != NULL) free (defdevice);
|
||||||
|
if (defsize != NULL) free (defsize);
|
||||||
|
defdevice = NULL;
|
||||||
|
defsize = NULL;
|
||||||
|
if (argc > 0)
|
||||||
|
{
|
||||||
|
if (argc > 1) /* size also supplied */
|
||||||
|
{
|
||||||
|
getsize (argv[1], &rsize, &tsize, &flag);
|
||||||
|
if (rsize == 0)
|
||||||
|
{
|
||||||
|
printf ("Invalid size %s\n", argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
defdevice = (char *) malloc (strlen (argv[0]) + 1);
|
||||||
|
defsize = (char *) malloc (strlen (argv[1]) + 1);
|
||||||
|
if (defdevice == NULL || defsize == NULL)
|
||||||
|
rabort(NOMEM);
|
||||||
|
strcpy (defdevice, argv[0]);
|
||||||
|
strcpy (defsize, argv[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
defdevice = (char *) malloc (strlen (argv[0]) + 1);
|
||||||
|
if (defdevice == NULL) rabort(NOMEM);
|
||||||
|
strcpy (defdevice, argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sw.verbose != NULL)
|
||||||
|
{
|
||||||
|
setrname ();
|
||||||
|
if (defsize != NULL)
|
||||||
|
printf ("Default RSTS disk name is %s, size %ld\n",
|
||||||
|
rname, rsize);
|
||||||
|
else printf ("Default RSTS disk name is %s\n", rname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doexit (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
i = append_history (newhistitems, histfile);
|
||||||
|
if (i) write_history (histfile);
|
||||||
|
else history_truncate_file (histfile, hfilesize);
|
||||||
|
free (histfile);
|
||||||
|
#endif
|
||||||
|
exit (EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cmdent commands[] =
|
||||||
|
{
|
||||||
|
{ "list", dolist },
|
||||||
|
{ "directory", dolist },
|
||||||
|
{ "ls", dolist },
|
||||||
|
{ "type", dotype },
|
||||||
|
{ "cat", dotype },
|
||||||
|
{ "dump", dodump },
|
||||||
|
{ "exit", doexit },
|
||||||
|
{ "quit", doexit },
|
||||||
|
{ "bye", doexit },
|
||||||
|
{ "get", doget },
|
||||||
|
{ "put", doput },
|
||||||
|
{ "delete", dodelete },
|
||||||
|
{ "rm", dodelete },
|
||||||
|
{ "protect", doprot },
|
||||||
|
{ "rts", dorts },
|
||||||
|
{ "runtime", dorts },
|
||||||
|
{ "rename", dorename },
|
||||||
|
{ "mv", dorename },
|
||||||
|
{ "move", dorename },
|
||||||
|
{ "hook", dohook },
|
||||||
|
{ "mkdir", domkdir },
|
||||||
|
{ "rmdir", dormdir },
|
||||||
|
{ "identify", doident },
|
||||||
|
{ "allocation", doalloc },
|
||||||
|
{ "initialize", doinit },
|
||||||
|
{ "dskint", doinit },
|
||||||
|
{ "disk", dodisk },
|
||||||
|
{ "compress", docomp },
|
||||||
|
{ "clean", doclean },
|
||||||
|
{ "rebuild", doclean },
|
||||||
|
{ NULL, NULL } };
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *kw;
|
||||||
|
char **flag;
|
||||||
|
int arg; /* TRUE if switch takes an argument */
|
||||||
|
} swname;
|
||||||
|
|
||||||
|
#define sd(x,y) { #x, &sw.y, FALSE } /* switch w/o arg */
|
||||||
|
#define sda(x,y) { #x, &sw.y, TRUE } /* switch with arg */
|
||||||
|
|
||||||
|
const swname switches[] =
|
||||||
|
{
|
||||||
|
sd(ascii,ascii),
|
||||||
|
sd(binary,bswitch),
|
||||||
|
sd(brief,bswitch),
|
||||||
|
sda(clustersize,clusiz),
|
||||||
|
sd(confirm,query),
|
||||||
|
sd(contiguous,contig),
|
||||||
|
sda(create,create),
|
||||||
|
sda(disk,rstsdevice),
|
||||||
|
sd(Debug,debug),
|
||||||
|
sda(end,end),
|
||||||
|
sda(filesize,size),
|
||||||
|
sd(full,full),
|
||||||
|
sd(image,bswitch),
|
||||||
|
sd(long,full),
|
||||||
|
sda(merge,merge),
|
||||||
|
sd(noprotect,unprot),
|
||||||
|
sd(oattributes,oattr),
|
||||||
|
sd(odt,odt),
|
||||||
|
sda(offset,offset),
|
||||||
|
sd(protect,prot),
|
||||||
|
sd(query,query),
|
||||||
|
sd(replace,replace),
|
||||||
|
sd(r,rmsvar),
|
||||||
|
sda(rf,rmsfix),
|
||||||
|
sd(rv,rmsvar),
|
||||||
|
sd(rs,rmsstm),
|
||||||
|
sda(size,size),
|
||||||
|
sda(Size,disksize),
|
||||||
|
sda(start,start),
|
||||||
|
sd(summary,summary),
|
||||||
|
sd(tree,tree),
|
||||||
|
sd(unprotect,unprot),
|
||||||
|
sd(verbose,verbose),
|
||||||
|
sd(wide, wide),
|
||||||
|
sd(Write,overwrite),
|
||||||
|
sd(1column,narrow),
|
||||||
|
sd(user,user),
|
||||||
|
sd(hex,hex),
|
||||||
|
{ "", NULL, FALSE } };
|
||||||
|
|
||||||
|
commandhandler scanargs(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int n, l;
|
||||||
|
const cmdent *c;
|
||||||
|
const swname *s, *swn;
|
||||||
|
commandhandler command;
|
||||||
|
|
||||||
|
memset (&sw, 0, sizeof (swtab)); /* Indicate no switches yet */
|
||||||
|
if (fargv != NULL) free (fargv);
|
||||||
|
if ((fargv = (char **) malloc (argc * sizeof(char *))) == NULL) rabort (NOMEM);
|
||||||
|
fargc = 0; /* No arguments yet */
|
||||||
|
cmdname = NULL; /* and no command name yet */
|
||||||
|
for (n = 1; n < argc; n++) /* scan the program arguments */
|
||||||
|
{
|
||||||
|
if (argv[n][0] == '-') /* it's a switch */
|
||||||
|
{
|
||||||
|
s = switches; /* point to switch names */
|
||||||
|
l = strlen (argv[n]) - 1;
|
||||||
|
swn = NULL; /* no match yet */
|
||||||
|
while (s->flag != NULL)
|
||||||
|
{
|
||||||
|
if (strncmp (&argv[n][1], s->kw, l) == 0) {
|
||||||
|
if (strlen (s->kw) == l)
|
||||||
|
{
|
||||||
|
swn = s;
|
||||||
|
break; /* exact match */
|
||||||
|
}
|
||||||
|
if (swn == NULL) swn = s;
|
||||||
|
else if (s->flag != swn->flag)
|
||||||
|
{
|
||||||
|
printf ("Ambiguous switch %s\n",
|
||||||
|
argv[n]);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
if (swn == NULL)
|
||||||
|
{
|
||||||
|
printf ("Unrecognized switch %s\n", argv[n]);
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
*(swn->flag) = argv[n];
|
||||||
|
if (swn->arg) /* switch takes an argument */
|
||||||
|
{
|
||||||
|
if (++n == argc) /* skip it */
|
||||||
|
{
|
||||||
|
printf ("Missing argument for switch %s\n", argv[n - 1]);
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
*(swn->flag) = argv[n]; /* point to that */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cmdname == NULL) cmdname = argv[n];
|
||||||
|
else fargv[fargc++] = argv[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
c = commands;
|
||||||
|
command = NULL; /* Nothing found yet */
|
||||||
|
if (cmdname == NULL)
|
||||||
|
{
|
||||||
|
printf ("Missing command keyword\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
l = strlen (cmdname); /* get length of command */
|
||||||
|
while (c->kw != NULL) /* look for matching command */
|
||||||
|
{
|
||||||
|
if (strncmp (cmdname, c->kw, l) == 0)
|
||||||
|
{
|
||||||
|
if (strlen (c->kw) == l)
|
||||||
|
{
|
||||||
|
command = c->hand;
|
||||||
|
break; /* stop now on exact match */
|
||||||
|
}
|
||||||
|
if (command == NULL) command = c->hand;
|
||||||
|
else if (command != c->hand)
|
||||||
|
{
|
||||||
|
printf ("Ambiguous command %s\n", cmdname);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
if (command == NULL)
|
||||||
|
{
|
||||||
|
printf ("Unrecognized command %s\n", cmdname);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip whitespace from the start and end of STRING. Return a pointer
|
||||||
|
* into STRING.
|
||||||
|
*/
|
||||||
|
char *stripwhite (char *string)
|
||||||
|
{
|
||||||
|
register char *s, *t;
|
||||||
|
|
||||||
|
for (s = string; whitespace (*s); s++) ;
|
||||||
|
|
||||||
|
if (*s == 0) return (s);
|
||||||
|
|
||||||
|
t = s + strlen (s) - 1;
|
||||||
|
while (t > s && whitespace (*t)) t--;
|
||||||
|
*++t = '\0';
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* **************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* Interface to Readline Completion */
|
||||||
|
/* */
|
||||||
|
/* **************************************************************** */
|
||||||
|
|
||||||
|
/* some forward declarations */
|
||||||
|
char * command_generator (const char *text, int state);
|
||||||
|
char * switch_generator (const char *text, int state);
|
||||||
|
char ** flx_completion (char *text, int start, int end);
|
||||||
|
|
||||||
|
/* Tell the GNU Readline library how to complete. We want to try to complete
|
||||||
|
* on command names if this is the first word in the line, or on filenames
|
||||||
|
* if not.
|
||||||
|
*/
|
||||||
|
void initialize_readline (void)
|
||||||
|
{
|
||||||
|
char *histfilesize;
|
||||||
|
char *histsize;
|
||||||
|
int hsize = 0;
|
||||||
|
char *home;
|
||||||
|
char *hf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* get history parameters */
|
||||||
|
hf = getenv ("FLXHISTFILE");
|
||||||
|
histfilesize = getenv ("FLXHISTFILESIZE");
|
||||||
|
histsize = getenv ("FLXHISTSIZE");
|
||||||
|
hfilesize = 0;
|
||||||
|
newhistitems = 0;
|
||||||
|
if (hf == NULL)
|
||||||
|
{
|
||||||
|
home = getenv ("HOME");
|
||||||
|
i = strlen (home);
|
||||||
|
histfile = malloc (i + strlen ("/.flx_history") + 1);
|
||||||
|
strcpy (histfile, home);
|
||||||
|
strcat (histfile, "/.flx_history");
|
||||||
|
}
|
||||||
|
else histfile = strdup (hf);
|
||||||
|
if (histfilesize != NULL) hfilesize = atoi (histfilesize);
|
||||||
|
if (histsize != NULL) hsize = atoi (histsize);
|
||||||
|
if (hsize == 0) hsize = 100;
|
||||||
|
if (hfilesize == 0) hfilesize = hsize;
|
||||||
|
|
||||||
|
/* set up history stuff */
|
||||||
|
using_history ();
|
||||||
|
stifle_history (hsize);
|
||||||
|
read_history (histfile);
|
||||||
|
|
||||||
|
/* Allow conditional parsing of the ~/.inputrc file. */
|
||||||
|
rl_readline_name = "Flx";
|
||||||
|
|
||||||
|
/* Tell the completer that we want a crack first. */
|
||||||
|
rl_attempted_completion_function = (CPPFunction *)flx_completion;
|
||||||
|
|
||||||
|
/* supply some things that don't seem to be there in DOS... */
|
||||||
|
rl_basic_word_break_characters = "n\"\\'`@$>";
|
||||||
|
rl_completer_word_break_characters =
|
||||||
|
(char *) rl_basic_word_break_characters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to complete on the contents of TEXT. START and END show the
|
||||||
|
* region of TEXT that contains the word to complete. We can use the
|
||||||
|
* entire line in case we want to do some simple parsing. Return the
|
||||||
|
* array of matches, or NULL if there aren't any.
|
||||||
|
*/
|
||||||
|
char ** flx_completion (char *text, int start, int end)
|
||||||
|
{
|
||||||
|
char **matches;
|
||||||
|
|
||||||
|
matches = NULL;
|
||||||
|
|
||||||
|
/* If this word is at the start of the line, then it is a command
|
||||||
|
* to complete. Otherwise it is the name of a file in the current
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
|
if (start == 0)
|
||||||
|
matches = rl_completion_matches (text, command_generator);
|
||||||
|
else if (*text == '-')
|
||||||
|
matches = rl_completion_matches (text, switch_generator);
|
||||||
|
|
||||||
|
return (matches);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generator function for command completion. STATE lets us know whether
|
||||||
|
* to start from scratch; without any state (i.e. STATE == 0), then we
|
||||||
|
* start at the top of the list.
|
||||||
|
*/
|
||||||
|
char * command_generator (const char *text, int state)
|
||||||
|
{
|
||||||
|
static int list_index, len;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
/* If this is a new word to complete, initialize now. This includes
|
||||||
|
* saving the length of TEXT for efficiency, and initializing the index
|
||||||
|
* variable to 0.
|
||||||
|
*/
|
||||||
|
if (!state)
|
||||||
|
{
|
||||||
|
list_index = 0;
|
||||||
|
len = strlen (text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the next name which partially matches from the command list. */
|
||||||
|
while ((name = (char *) commands[list_index].kw))
|
||||||
|
{
|
||||||
|
list_index++;
|
||||||
|
if (strncmp (name, text, len) == 0)
|
||||||
|
return strdup (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no names matched, then return NULL. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ditto but for switches */
|
||||||
|
char * switch_generator (const char *text, int state)
|
||||||
|
{
|
||||||
|
static int list_index, len;
|
||||||
|
char *name;
|
||||||
|
char sw[20];
|
||||||
|
|
||||||
|
/* If this is a new word to complete, initialize now. This includes
|
||||||
|
* saving the length of TEXT for efficiency, and initializing the index
|
||||||
|
* variable to 0.
|
||||||
|
*/
|
||||||
|
if (!state)
|
||||||
|
{
|
||||||
|
list_index = 0;
|
||||||
|
len = strlen (text) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the next name which partially matches from the switch list. */
|
||||||
|
while (*(name = switches[list_index].kw))
|
||||||
|
{
|
||||||
|
list_index++;
|
||||||
|
if (strncmp (name, text + 1, len) == 0)
|
||||||
|
{
|
||||||
|
sw[0] = '-';
|
||||||
|
strcpy (sw + 1, name);
|
||||||
|
return strdup (sw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no names matched, then return NULL. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
11
extracters/rstsflx/scancmd.h
Normal file
11
extracters/rstsflx/scancmd.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
extern char doquery (void (*printfile)(void *), void *name);
|
||||||
|
extern void dodisk (int argc, char **argv);
|
||||||
|
extern void dofiles(int argc , char **argv , commandaction action , int nullflag);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void doexit(int argc , char **argv);
|
||||||
|
extern commandhandler scanargs(int argc , char **argv);
|
||||||
|
/* Prototype include a typedef name.
|
||||||
|
It should be moved after the typedef declaration */
|
||||||
|
extern void initialize_readline (void);
|
||||||
|
extern char *stripwhite (char *string);
|
||||||
87
extracters/rstsflx/silfmt.h
Normal file
87
extracters/rstsflx/silfmt.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Edit history for SILFMT
|
||||||
|
*
|
||||||
|
* [RSTS V9_0]
|
||||||
|
* 000 WJS 22-Sep-83 Creation
|
||||||
|
*
|
||||||
|
* [RSTS V9_6]
|
||||||
|
* 001 KPH 13-Nov-87 Increase number of phases to 47
|
||||||
|
*
|
||||||
|
* 002 GPK 23-Aug-94 Convert from .mac to .h
|
||||||
|
* 003 GPK 29-Aug-94 Add definition for SAV format SIL index, add
|
||||||
|
* STB and overlay descriptor format.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Set the number of SIL index blocks allowed for this release */
|
||||||
|
|
||||||
|
#define si_nbl 3 /* Maximum number of SIL index blocks */
|
||||||
|
|
||||||
|
/* Definitions of SIL Index entry */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
word16 se_nam[2]; /* Name of module */
|
||||||
|
word16 se_idn[2]; /* Ident of module */
|
||||||
|
word16 se_blk; /* Starting block of module */
|
||||||
|
word16 se_stb; /* Starting block of STB */
|
||||||
|
word16 se_stn; /* Number of entries in STB */
|
||||||
|
word16 se_lod; /* Load address of this module */
|
||||||
|
word16 se_siz; /* Size of module (in bytes) */
|
||||||
|
word16 se_xfr; /* Transfer address */
|
||||||
|
word16 se_szd; /* Size of module image of disk in blocks */
|
||||||
|
word16 se_ovb; /* Block offset to module's overlay descriptors */
|
||||||
|
word16 se_ovn; /* Number of overlay descriptors for module */
|
||||||
|
word16 se_off; /* Starting offset on disk for this module */
|
||||||
|
word16 filler; /* (reserved) */
|
||||||
|
word16 se_xxx; /* Reserved for SAV format SILs */
|
||||||
|
} silent;
|
||||||
|
|
||||||
|
#define se_len (sizeof (silent)) /* Size of SIL Index entry */
|
||||||
|
|
||||||
|
/* Derive the number of modules si_nbl SIL index blocks can contain */
|
||||||
|
|
||||||
|
#define si_oth (1000/se_len) /* Number of entries in a non-first block */
|
||||||
|
#define si_1st (si_oth-1) /* Number of entries in first block */
|
||||||
|
#define si_nmd ((si_nbl-1)*si_oth+si_1st) /* Maximum total no of index entries */
|
||||||
|
|
||||||
|
/* Layout for SIL index as it would be directly read from disk */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
word16 si_num; /* Number of modules in SIL */
|
||||||
|
silent si_ent[si_1st]; /* Space for first block's SIL Index entries */
|
||||||
|
word16 si_rsv[12]; /* Reserved */
|
||||||
|
word16 si_bls; /* Size of this SIL in blocks */
|
||||||
|
word16 si_chk; /* Checksum of SIL Index */
|
||||||
|
word16 si_sil; /* RAD50 "SIL" for identification */
|
||||||
|
silent si_mor[si_nmd - si_1st]; /* Space for non-first blocks' entries */
|
||||||
|
} silindex;
|
||||||
|
|
||||||
|
/* Layout for SIL index in the case of a .SAV file SIL */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
word16 si_num; /* Number of modules (must be 1) */
|
||||||
|
silent si_ent; /* One SIL index entry */
|
||||||
|
#define initpc si_ent.se_xxx /* Initial PC value lives here */
|
||||||
|
word16 initsp; /* Initial SP */
|
||||||
|
word16 rtjsw; /* Reserved for JSW in RT11 */
|
||||||
|
word16 rtusr; /* Reserved for USR ptr in RT11 */
|
||||||
|
word16 usertop; /* High address of program */
|
||||||
|
word16 si_rsv[(0774-052)/2]; /* Fill to end of block */
|
||||||
|
word16 si_chk; /* Checksum of SIL Index */
|
||||||
|
word16 si_sil; /* RAD50 "SIL" for identification */
|
||||||
|
} savsilindex;
|
||||||
|
|
||||||
|
/* Layout of SIL symbol table entry */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
word16 name[2]; /* Symbol name in RAD50 */
|
||||||
|
word16 ovnum; /* Overlay number */
|
||||||
|
word16 value; /* Symbol value */
|
||||||
|
} stbent;
|
||||||
|
|
||||||
|
/* Layout of overlay descriptor entry */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
word16 base; /* Base virtual address of overlay */
|
||||||
|
word16 size; /* Size in bytes of overlay */
|
||||||
|
word16 offset[2]; /* Offset (MSW, LSW) to overlay */
|
||||||
|
} ovrent;
|
||||||
110
extracters/rstsflx/unxabsio.c
Normal file
110
extracters/rstsflx/unxabsio.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/* absolute I/O support for Unix
|
||||||
|
*
|
||||||
|
* Paul Koning 95.01.05 created
|
||||||
|
*
|
||||||
|
* Note that this particular version of absio is mostly a dummy, since
|
||||||
|
* there is very little special that has to be done on Unix for absolute
|
||||||
|
* I/O. Among other things, this file should serve as a template for
|
||||||
|
* those who want to create the equivalent for another operating system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "flx.h"
|
||||||
|
#include "absio.h"
|
||||||
|
|
||||||
|
/* this routine is called to scan a supplied container file/device
|
||||||
|
* name. If the name refers to a real disk, then absflag is set
|
||||||
|
* and rsize is set to the device size. Otherwise, no action is taken.
|
||||||
|
*
|
||||||
|
* More precisely, there are three things this routine may want to do,
|
||||||
|
* depending on the OS and the name supplied.
|
||||||
|
*
|
||||||
|
* If, for the specified name, the absolute I/O routines in this module
|
||||||
|
* need to be called, then absflag should be set to TRUE, and rsize must
|
||||||
|
* be set to the size of the device. Otherwise, absflag should be left
|
||||||
|
* alone (which leaves it FALSE); that way the other absolute I/O routines
|
||||||
|
* in this module will not be called and standard C I/O is used instead.
|
||||||
|
*
|
||||||
|
* If, for the specified name, "fstat" will not return a size (i.e., returns
|
||||||
|
* zero) then rsize must specify the correct size. This can be set in this
|
||||||
|
* module, based on OS specific operations, or it can simply be left
|
||||||
|
* unchanged, in which case it has to be supplied by the user.
|
||||||
|
*
|
||||||
|
* For example, in Unix the fstat function doesn't return a size for raw
|
||||||
|
* devices (it returns zero) but the stdio routines are otherwise perfectly
|
||||||
|
* suitable. So this routine does NOT set absflag since no special abs I/O
|
||||||
|
* routines are needed. It does check the return from stat(); if this
|
||||||
|
* indicates a raw device, it checks that rsize has been supplied and
|
||||||
|
* complains if not. Note that the code below does not attempt to obtain
|
||||||
|
* the device size, since there is no portable Unix way of doing this that
|
||||||
|
* I know of.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void absname (const char *rname)
|
||||||
|
{
|
||||||
|
struct stat sbuf;
|
||||||
|
|
||||||
|
if (stat (rname, &sbuf)) return; /* try to get info about device */
|
||||||
|
diskblocks = UP(sbuf.st_size,BLKSIZE) / BLKSIZE;
|
||||||
|
if (diskblocks == 0) {
|
||||||
|
if (S_ISCHR(sbuf.st_mode)) {
|
||||||
|
diskblocks = rsize;
|
||||||
|
if (rsize == 0) {
|
||||||
|
printf ("Size not specified for RSTS disk %s\n", rname);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do any device open actions that may be needed.
|
||||||
|
* The "mode" argument is a standard C open mode. The return value is zero
|
||||||
|
* for success, non-zero for error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int absopen (const char *rname, const char *mode)
|
||||||
|
{
|
||||||
|
rabort(INTERNAL); /* should never get here */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do a seek on a device. You can do it here
|
||||||
|
* or as part of the read/write, whichever is easier. This routine is
|
||||||
|
* called only if the I/O operations are changing between read and write,
|
||||||
|
* or are not sequential. So you would want to do the work here if your
|
||||||
|
* OS does implicit sequential I/O, and make this a NOP if the read and
|
||||||
|
* write primitives take an explicit block number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void absseek (long block)
|
||||||
|
{
|
||||||
|
rabort(INTERNAL); /* should never get here */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do any needed "close" actions for absolute I/O */
|
||||||
|
|
||||||
|
void absclose ()
|
||||||
|
{
|
||||||
|
rabort(INTERNAL); /* should never get here */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do an absolute device read. The block number
|
||||||
|
* is supplied, even though it could have been derived from a preceding
|
||||||
|
* absseek call. This is because absseek is not called when sequential
|
||||||
|
* reads are done.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long absread (long sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
return (0); /* should never get here */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This routine is called to do an absolute device write. */
|
||||||
|
|
||||||
|
long abswrite (long sec, long count, void *buffer)
|
||||||
|
{
|
||||||
|
return (0); /* should never get here */
|
||||||
|
}
|
||||||
1
extracters/rstsflx/version.h
Normal file
1
extracters/rstsflx/version.h
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#define IDENT "v2.6" /* program version number */
|
||||||
Reference in New Issue
Block a user