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:
Paul Koning
2016-04-27 15:00:42 -04:00
parent 0cb8000e5f
commit bf7c17ab4a
71 changed files with 10068 additions and 0 deletions

31
.gitignore vendored
View File

@@ -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

View File

@@ -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
View 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

View 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.

View 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.

View 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

View 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
View 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

View 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);

View 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
View 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);
}

View 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);

View 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(&param_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(&param_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));
}

View 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 */
}

View File

@@ -0,0 +1 @@
extern void doalloc(int argc , char ** argv);

1794
extracters/rstsflx/doclean.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
extern void doclean (int argc , char ** argv);

View 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 */
}

View File

@@ -0,0 +1 @@
extern void docomp(int argc , char ** argv);

View 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 */
}

View 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
View 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 ();
}

View 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
View 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 */
}
}

View File

@@ -0,0 +1 @@
extern void dodump(int argc , char ** argv);

193
extracters/rstsflx/doget.c Normal file
View 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 */
}

View File

@@ -0,0 +1 @@
extern void doget(int argc , char ** argv);

350
extracters/rstsflx/dohook.c Normal file
View 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 */
}

View 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);

View 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 */
}

View File

@@ -0,0 +1 @@
extern void doident(int argc , char ** argv);

387
extracters/rstsflx/doinit.c Normal file
View 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! */
}

View File

@@ -0,0 +1,2 @@
extern int getclusize(void);
extern void doinit(int argc , char * argv[]);

218
extracters/rstsflx/dolist.c Normal file
View 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 */
}

View File

@@ -0,0 +1 @@
extern void dolist(int argc , char ** argv);

View 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 */
}

View 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
View 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 */
}

View File

@@ -0,0 +1 @@
extern void doput(int argc , char ** argv);

View 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 */
}

View 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);

View 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 */
}

View 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);

View 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(&param_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(&param_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
}

View 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);

View 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));
}

View 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 */
}

View 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
View 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
View 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);
}

View 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);

View 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 "." */
}

View 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

File diff suppressed because it is too large Load Diff

87
extracters/rstsflx/fip.h Normal file
View 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
View 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;

View 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

Binary file not shown.

227
extracters/rstsflx/flx.h Normal file
View 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

Binary file not shown.

View 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 */
}

View 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

View 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);
}

View File

@@ -0,0 +1,3 @@
extern void doabort(int status , const char * srcfile , int srcline)
__attribute__ ((noreturn));
extern int main(int argc , char **argv);

View 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));
}

View 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 */

View 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;
}

View 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);

View 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;

View 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 */
}

View File

@@ -0,0 +1 @@
#define IDENT "v2.6" /* program version number */