FSIO: bug fixes and the addition of OS/8 support

This commit is contained in:
John Forecast 2020-01-11 09:21:05 -08:00 committed by Mark Pizzolato
parent f40e814fcb
commit beabfab2e8
17 changed files with 3786 additions and 78 deletions

35
converters/fsio/Changes Normal file
View File

@ -0,0 +1,35 @@
Changes Since Alpha Release:
1. mount: Fix memory leak when file system verification fails
2. dos11: Fix hang when parsing wildcard programmer number
3. Migrate to using GNU readline library for command line editing etc
4. local: Fix buffering so that local "type" command works
5. Add DOS-11 magtape support using file system type "dosmt"
6. newfs: Remove -a switch. Replace with "-t type" switch to allow more
flexibility. The equivalent of "-a" is now "-t rl02".
12-Jun-19
- Added support for sector interleave on RX01/RX02 drives
- Now supports creating RX01-sized container files
- Now works with RTFLX on TOPS-10 with RX02-sized container files
(documentation updated)
25-Jun-19
- Added support for OS/8 file systems on RX01, RX02 and RK05 drives using
file system type "os8"
- Added support for creating RT-11 file systems with additional space
allocated to each directory entry
9-Jan-20
- Merged change from tvrusso to fix compilation on FreeBSD

View File

@ -7,13 +7,14 @@ INSTALL=install
CC=gcc
EXECUTABLE=fsio
SOURCES=fsio.c declib.c tape.c dos11.c rt11.c dosmt.c local.c
INCLUDES=fsio.h declib.h tape.h dos11.h rt11.h dosmt.h
SOURCES=fsio.c declib.c tape.c dos11.c rt11.c dosmt.c local.c os8.c
INCLUDES=fsio.h declib.h tape.h dos11.h rt11.h dosmt.h os8.h
LIBS=-lreadline
MANPAGE=fsio.1
MANPAGE_DOS=fsio-dos11.1
MANPAGE_RT=fsio-rt11.1
MANPAGE_DOSMT=fsio-dosmt.1
MANPAGE_OS8=fsio-os8.1
ARCHIVE=fsio.tgz
RELEASEFILES=$(BIN)/$(EXECUTABLE)
@ -21,6 +22,7 @@ RELEASEFILES+=$(MAN)/$(MANPAGE)
RELEASEFILES+=$(MAN)/$(MANPAGE_DOS)
RELEASEFILES+=$(MAN)/$(MANPAGE_RT)
RELEASEFILES+=$(MAN)/$(MANPAGE_DOSMT)
RELEASEFILES+=$(MAN)/$(MANPAGE_OS8)
RELEASEFILES+=./fsio.txt ./fsioSimh.txt
$(EXECUTABLE): $(SOURCES) $(INCLUDES) Makefile
@ -38,6 +40,7 @@ install: $(EXECUTABLE) $(MANPAGE) $(MANPAGE_DOS) $(MANPAGE_RT)
$(INSTALL) -p -m u=r,g=r,o=r $(MANPAGE_DOS) $(MAN)
$(INSTALL) -p -m u=r,g=r,o=r $(MANPAGE_RT) $(MAN)
$(INSTALL) -p -m u=r,g=r,o=r $(MANPAGE_DOSMT) $(MAN)
$(INSTALL) -p -m u=r,g=r,o=r $(MANPAGE_OS8) $(MAN)
uninstall:
rm -f $(BIN)/$(EXECUTABLE)
@ -45,6 +48,7 @@ uninstall:
rm -f $(MAN)/$(MANPAGE_DOS)
rm -f $(MAN)/$(MANPAGE_RT)
rm -f $(MAN)/$(MANPAGE_DOSMT)
rm -f $(MAN)/$(MANPAGE_OS8)
# This assumes that fsio has been "installed" on the current system
archive: $(RELEASEFILES)

View File

@ -1666,12 +1666,12 @@ static void dos11Umount(
*
* Returns:
*
* Size of the container file in blocks of default file system size
* Default size of the container file in bytes (RK05).
*
--*/
static size_t dos11Size(void)
{
return DISKSIZE_RK05;
return DISKSIZE_RK05 * BLOCKSIZE_RK11;
}
/*++
@ -1707,7 +1707,7 @@ static int dos11Newfs(
memset(data, 0, sizeof(*data));
data->blocks = size;
data->blocks = size / BLOCKSIZE_RK11;
data->bitmaps = 5;
data->bmblk[0] = MAP_BLOCK;
data->bmblk[1] = MAP_BLOCK + 1;

View File

@ -1,4 +1,4 @@
.TH FSIO-DOS11 1 "December 28,2018" "FFS I/O - DOS-11"
.TH FSIO-DOS11 1 "Jun 21,2019" "FFS I/O - DOS-11"
.SH NAME
fsio-dos11 \- Foreign File System I/O - DOS-11
.br
@ -45,6 +45,7 @@ Creates an empty UFD and sets default UIC for file access.
.BR fsio (1),
.BR fsio-rt11 (1)
.BR fsio-dosmt (1)
.BR fsio-os8 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@ -1,4 +1,4 @@
.TH FSIO-DOSMT 1 "January 28,2019" "FFS I/O - DOS-11 magtape"
.TH FSIO-DOSMT 1 "Jun 25,2019" "FFS I/O - DOS-11 magtape"
.SH NAME
fsio-dosmt \- Foreign File System I/O - DOS-11 magtape
.br
@ -102,9 +102,10 @@ the end of any specific file (see info command for more details on how to
determine the current tape position).
.br
.SH SEE ALSO
.BR fsio (1),
.BR fsio (1)
.BR fsio-dos11 (1)
.BR fsio-rt11 (1)
.BR fsio-os8 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@ -0,0 +1,80 @@
.TH FSIO-OS8 1 "Sep 218,2019" "FFS I/O - OS/8"
.SH NAME
fsio-os8 \- Foreign File System I/O - OS/8
.br
.SH DESCRIPTION
\fBfsio\fP allows access to OS/8 file systems using the file system type
"\fIos8\fP"
.br
.SH OS/8 PHYSICAL DISKS
OS/8 uses a file system block size of 256 words and OS/8 devices are limited
to 4095 blocks. Blocks 0 through 6 are reserved so the largest possible file
is 4088 blocks long (1046528 words). Larger devices, for example the RK05,
place multiple file systems on each physical device.
.br
OS/8 does not write any type of signature on the device and each device type
has it's own partitioning scheme so the \fImount\fP command must use the
"\fI-f type\fP switch so that \fBfsio\fP can determine the file system
layout. \fBfsio\fP uses a set of heuristics to verify the integrity of
the OS/8 file system(s) but it is quite possible for a random disk to pass
these tests and later crash \fBfsio\fP.
.SH MOUNT OPERATION
\fImount\fP requires the "\fI-f type\fP" switch so that it can determine the
type of the underlying disk (See NEWFS OPERATION below for details).
.SH NEWFS OPERATION
\fInewfs\fP creates an RK05 disk image with 2 file systems. If the
"\fI-f type\fP" switch is present a different container file will be created
depending on the type of the device specified:
.br
.RS
.TP
\fIrk05\fP \- RK05 image (2 file systems, 3248 blocks each)
.br
.TP
\fIrx01\fP \- RX01 image (single file system, 494 blocks)
.br
.TP
\fIrx02\fP \- RX02 image (single file system, 988 blocks)
.br
.RE
Note that in order to use RX02 media the OS/8 system must have the device
extensions kit installed.
.br
The "\fI-e extra\fP" switch, where "extra" is a number in the range 0 - 63,
may be used to create file systems with "extra" additional information words
available to each directory entry. By default, \fInewfs\fP will create file
systems with 1 additional information word which will be used to hold the
file creation date. If you do not want any additional information words
use "\fI-e 0\fP".
.br
.SH SET OPERATION
The following \fIset\fP commands are supported:
.br
.TP
.B "\fIyear\fP n"
.br
All subsequent OS/8 file creations will include a creation date (if the file
system was created with at least 1 additional information word). The date used
will be the month and day of the month for today with the year "n" (where "n"
is in the range 0 - 7).
.br
.TP
.B "\fIyear\fP none"
.br
All subsequent OS/8 file creations will include a zero creation date (if the
file system was created with at least 1 additional information word). This is
the default state after mount.
.br
.SH SEE ALSO
.BR fsio (1)
.BR fsio-dos11 (1)
.BR fsio-dosmt (1)
.BR fsio-rt11 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@ -1,4 +1,4 @@
.TH FSIO-RT11 1 "May 15,2019" "FFS I/O - RT-11"
.TH FSIO-RT11 1 "Jun 25,2019" "FFS I/O - RT-11"
.SH NAME
fsio-rt11 \- Foreign File System I/O - RT-11
.br
@ -23,6 +23,15 @@ version 2 file systems.
The VMS exchange utility may be used to initialize an RT-11 volume but writes
it's own unique signature in the home block. \fBfsio\fP is able to correctly
handle this signature.
.br
.SH RT-11 PHYSICAL DISKS
RT-11 uses a file system block size of 512 bytes and most disk type either
have a block size of 512 bytes or use 2 contiguous blocks or 256 bytes each.
Floppy diskettes, RX01 and RX02 drives, use small sectors size and for
performance reason, adjacent logical sectors are interleaved within the same
track. When mounting a floppy diskette, the \fI"-f type"\fP must be used so
that \fIfsio\fP can determine the interleaving used. In this case "type"
should be either "rx01" or "rx02".
.SH LOGICAL DISKS
\fBfsio\fP can be used to access an RT-11 logical disk if the file has been
copied to the host file system.
@ -43,9 +52,18 @@ depending on the type of device specified:
\fIrl02\fP \- RL02 image (10MB, 20480 blocks)
.br
.TP
\fIrx20\fP \- RX20 image (512KB, 1024 blocks)
\fIrx01\fP \- RX01 floopy image (256KB, 2002 sectors of 128 bytes)
.br
.TP
\fIrx02\fP \- RX02 floopy image (512KB, 2002 sectors of 256 bytes)
.br
.RE
The "\fI-e extra\fP" switch, where "extra" is a number in the range 0 - 63,
may be used to create file systems with "extra" additional bytes available to
each directory entry. \fIfsio\fP will silently round up the value to make it
an even number required by RT-11. By default, \fInewfs\fP will create file
systems with no additional bytes for each directory entry.
.SH COPY OPERATION
When copying in ASCII mode, \fBfsio\fP will normally write ^Z (octal 032) to
indicate the end-of-file. Some utilities, such as FLX on RSX-11, cannot
@ -56,9 +74,10 @@ NULLs up to the next block boundary if this occurs.
.SH SET OPERATION
No \fIset\fP commands are currently supported.
.SH SEE ALSO
.BR fsio (1),
.BR fsio (1)
.BR fsio-dos11 (1)
.BR fsio-dosmt (1)
.BR fsio-os8 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@ -1,4 +1,4 @@
.TH FSIO 1 "May 15,2019" "Foreign File System I/O"
.TH FSIO 1 "Sep 17,2019" "Foreign File System I/O"
.SH NAME
fsio \- Foreign File System I/O
.SH SYNOPSIS
@ -76,7 +76,7 @@ The following commands are only accepted by file systems which are on magtape de
.br
.SH COMMANDS
.TP
.B "\fImount\fP [-dfrx] dev[:] file type"
.B "\fImount\fP [-dfrx] [-t type] dev[:] file type"
Make the container file available to fsio.
.br
.RS
@ -93,6 +93,8 @@ Make the container file available to fsio.
.br
.B "\fI\-r\fP \- mount file system read-only"
.br
.B "\fI\-t type\fP \- specify optional disk type"
.br
.B "\fI\-x\fP \- dosmt will use extended filenames when writing"
.br
.B "\fIdev[:]\fP \- user supplied name for the mount"
@ -113,13 +115,15 @@ Remove knowledge of the container file from fsio.
.RE
.RE
.TP
.B "\fInewfs\fP [-t type] file type"
.B "\fInewfs\fP [-t type] [-e count] file type"
Create an new container with an empty file system.
.br
.RS
.RS
.B "\fI\-t type\fP \- use alternate, file-system dependent size"
.br
.B "\fI\-e n\fP \- Specify extra space for directory entries (RT11, OS/8)"
.br
.B "\fIfile\fP \- name of the container file"
.br
.B "\fItype\fP \- type of container file system"
@ -327,10 +331,13 @@ This function depends on the value of blks:
.br
.B "\fIdosmt\fP \- container file in DOS-11 magtape format"
.br
.B "\fIos8\fP \- OS/8 on RX01, RX01 or RK05"
.br
.SH SEE ALSO
.BR fsio-dos11 (1),
.BR fsio-rt11 (1)
.BR fsio-dosmt (1)
.BR fsio-os8 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@ -32,7 +32,7 @@
*/
/*
* Foreign file system interface (12/26/2018)
* Foreign file system interface (9/18/2019)
*
* Each foreign file system is described by a struct FSdef which is linked
* into a master list of supported file systems in FSioInit(). Each entry
@ -84,7 +84,9 @@
* This routine is called when processing a "mount" command. The container
* file is open, and this routine should verify that it contains a valid
* file system. This routine may print out information about the file
* system. Return 1 if the file system is valid, 0 otherwise.
* system. Return 1 if the file system is valid, 0 if the file system is
* invalid and -1 if the file system is invalid and an erroir message
* has already been printed.
*
* void (*umount)(struct mountedFS *mount);
*
@ -95,9 +97,8 @@
*
* size_t (*size)(void)
*
* Return the number of "blocksz" size blocks used for the container file.
* The command line switch (-t type) may be used to determine the
* required size.
* Return the number of byte used for the container file. The command
* line switch (-t type) may be used to override the default size.
*
* int (*newfs)(struct mountedFS *mount, size_t size);
*
@ -151,9 +152,9 @@
*
* off_t (*fileSize)(void *filep);
*
* Returns the size of a file currently open for reading. If it is
* not possible to determine the actual file size, return 0. In all
* other cases, the returned value may over-estimate, but not
* Returns the size, in bytes, of a file currently open for reading.
* If it is not possible to determine the actual file size, return 0.
* In all other cases, the returned value may over-estimate, but not
* under-estimate the size of the file. For example, linked files
* on DOS-11 will overestimate the size by 2 bytes/block.
*
@ -310,12 +311,12 @@ struct command {
cmd_t func; /* Command execution function */
} cmdTable[] = {
#ifdef DEBUG
{ "mount", OPTIONS("dfrx"), 3, 3, 0, doMount },
{ "mount", OPTIONS("dfrt:x"), 3, 3, 0, doMount },
#else
{ "mount", OPTIONS("frx"), 3, 3, 0, doMount },
{ "mount", OPTIONS("frt:x"), 3, 3, 0, doMount },
#endif
{ "umount", NULL, 1, 1, 0, doUmount },
{ "newfs", OPTIONS("t:"), 2, 2, 0, doNewfs },
{ "newfs", OPTIONS("e:t:"), 2, 2, 0, doNewfs },
{ "set", NULL, 2, MAX_CMDLEN, 0, doSet },
{ "info", NULL, 1, 1, 0, doInfo },
{ "dir", OPTIONS("fn"), 1, 1, 0, doDir },
@ -364,6 +365,7 @@ extern struct FSdef localFS;
extern struct FSdef dos11FS;
extern struct FSdef rt11FS;
extern struct FSdef dosmtFS;
extern struct FSdef os8FS;
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
@ -418,6 +420,9 @@ static void FSioInit(void)
dosmtFS.next = fileSystems;
fileSystems = &dosmtFS;
os8FS.next = fileSystems;
fileSystems = &os8FS;
}
/*++
@ -746,6 +751,7 @@ static void doMount(void)
{
struct FSdef *filesys;
FILE *container;
int status;
char *mode = SWISSET('r') ? "r" : "r+";
if (checkDev(words[0]) != 0) {
@ -761,6 +767,8 @@ static void doMount(void)
struct mountedFS *mount;
if ((mount = malloc(sizeof(struct mountedFS))) != NULL) {
memset(mount, 0, sizeof(struct mountedFS));
strcpy(mount->name, words[0]);
mount->filesys = filesys;
mount->blocksz = filesys->blocksz;
@ -781,19 +789,21 @@ static void doMount(void)
}
#endif
mount->container = container;
mount->skip = 0;
/*
* Verify that the container holds a valid file system
*/
if ((*filesys->mount)(mount) != 0) {
if ((status = (*filesys->mount)(mount)) > 0) {
mount->next = mounts;
mounts = mount;
return;
}
free(mount);
fprintf(stderr,
"mount: \"%s\" does not contain a valid file system\n",
words[1]);
if (status == 0)
fprintf(stderr,
"mount: \"%s\" does not contain a valid file system\n",
words[1]);
} else fprintf(stderr, "mount: out of memory\n");
fclose(container);
} else fprintf(stderr, "mount: failed to open \"%s\"\n", words[1]);
@ -892,7 +902,9 @@ static void doNewfs(void)
size = (*filesys->size)();
if ((mount.container = fopen(words[0], "w+")) != NULL) {
off_t offset = filesys->blocksz * (size - 1);
off_t offset = size - 1;
mount.skip = 0;
/*
* If an empty file is valid, we are all done
@ -900,8 +912,8 @@ static void doNewfs(void)
if ((filesys->flags & FS_EMPTYFILE) != 0)
return;
if ((fseeko(mount.container, offset, SEEK_SET) == 0) &&
(fwrite(&ch, 1, filesys->blocksz, mount.container) == filesys->blocksz)) {
if ((fseeko(mount.container, offset + mount.skip, SEEK_SET) == 0) &&
(fwrite(&ch, 1, 1, mount.container) == 1)) {
mount.filesys = filesys;
mount.blocksz = filesys->blocksz;
@ -1263,8 +1275,8 @@ static void doType(void)
* Close the file
*/
(*mount->filesys->closeFile)(file);
}
} else fprintf(stderr, "dump: \"%s\" no such file\n", fname);
} else fprintf(stderr, "type: \"%s\" no such file\n", fname);
}
}
/*++
@ -1415,10 +1427,12 @@ static void doHelp(void)
"A common command format is used:\n\n"
" verb [switches] arg1 arg2 ...\n\n"
"The following commands are supported:\n\n"
" mount [-r] dev[:] container fstype\n\n"
" mount [-r] [-t type] dev[:] container fstype\n\n"
"The file system container file is made available to fsio (via the dev\n"
"specifier). fstype specifies the type of the container file system.\n"
"If -r is specified, the file system will be read-only.\n\n"
"If -r is specified, the file system will be read-only.\n"
"In some cases (e.g. OS/8) fsio is unable to determine the type of the\n"
"underlying disk so it must be specified using \"-t type\"\n\n"
" umount dev[:]\n\n"
"Remove all knowledge of the container file from fsio.\n\n"
" newfs [-t type] container fstype\n\n"
@ -1942,7 +1956,7 @@ int FSioReadBlock(
{
off_t offset = block * mount->blocksz;
if (fseeko(mount->container, offset, SEEK_SET) == 0)
if (fseeko(mount->container, offset + mount->skip, SEEK_SET) == 0)
return fread(buf, mount->blocksz, 1, mount->container);
return 0;
@ -1976,8 +1990,87 @@ int FSioWriteBlock(
{
off_t offset = block * mount->blocksz;
if (fseeko(mount->container, offset, SEEK_SET) == 0)
if (fseeko(mount->container, offset + mount->skip, SEEK_SET) == 0)
return fwrite(buf, mount->blocksz, 1, mount->container);
return 0;
}
/*++
* F S i o R e a d S e c t o r
*
* Read a sector of a specified size from the container. The caller is
* responsible for making sure that the buffer has sufficient space for
* the sector. This routine is used when file system blocks are constructed
* from a number of sectors which are interleaved on the physical disk (e.g.
* RX02 floppies).
*
* Inputs:
*
* mount - pointer to a mounted file system descriptor
* sector - logical sector # in the range 0 - N
* size - size of each sector (in bytes)
* buf - pointer to the buffer to receive the data
*
* Outputs:
*
* The buffer will be overwritten by the contents of the sector from
* the container file system
*
* Returns:
*
* 1 if read was successful, 0 otherwise
*
--*/
int FSioReadSector(
struct mountedFS *mount,
unsigned int sector,
unsigned int size,
void *buf
)
{
off_t offset = sector * size;
if (fseeko(mount->container, offset + mount->skip, SEEK_SET) == 0)
return fread(buf, size, 1, mount->container);
return 0;
}
/*++
* F S i o W r i t e S e c t o r
*
* Write a sector of a specified size to the container. This routine is used
* when file system blocks are constructed from a number of sectors which are
* interleaved on the physical disk (e.g. RX02 floppies).
*
* Inputs:
*
* mount - pointer to a mounted file system descriptor
* sector - logical sector # in the range 0 - N
* size - size of each sector (in bytes)
* buf - pointer to the buffer to receive the data
*
* Outputs:
*
* None
*
* Returns:
*
* 1 if read was successful, 0 otherwise
*
--*/
int FSioWriteSector(
struct mountedFS *mount,
unsigned int sector,
unsigned int size,
void *buf
)
{
off_t offset = sector * size;
if (fseeko(mount->container, offset + mount->skip, SEEK_SET) == 0)
return fwrite(buf, size, 1, mount->container);
return 0;
}

View File

@ -40,6 +40,7 @@ enum openMode { M_RD, M_WR };
#include "dos11.h"
#include "rt11.h"
#include "dosmt.h"
#include "os8.h"
/*
* All of the supported file systems are natively little endian so we only
@ -150,17 +151,22 @@ struct mountedFS {
/* Bits after 0x0080 reserved for */
/* file system use */
FILE *container; /* Container file access */
off_t skip; /* Data to skip in container file */
union {
struct DOS11data _dos11;
struct RT11data _rt11;
struct DOSMTdata _dosmt;
struct OS8data _os8;
} FSdata;
#define dos11data FSdata._dos11
#define rt11data FSdata._rt11
#define dosmtdata FSdata._dosmt
#define os8data FSdata._os8
};
extern int FSioReadBlock(struct mountedFS *, unsigned int, void *);
extern int FSioWriteBlock(struct mountedFS *, unsigned int, void *);
extern int FSioReadSector(struct mountedFS *, unsigned int, unsigned int, void *);
extern int FSioWriteSector(struct mountedFS *, unsigned int, unsigned int, void *);
#endif

View File

@ -87,7 +87,7 @@ Full command syntax:
1. mount
mount [-dfr] dev[:] container type
mount [-dfr] [-t type] dev[:] container type
Make the specified container file available to fsio for I/O.
@ -97,6 +97,10 @@ Full command syntax:
validate the container file format
-r If present, the file system is only available for read access
-t type Specify the type of the container file. This is only required
for OS/8 file systems where type should be one of "rx01",
"rx02" or "rk05".
dev[:] User supplied name to be used for accessing files within the
container file. Files within the container are named by using
the syntax dev:filespec where filespec uses the native syntax
@ -133,6 +137,7 @@ Full command syntax:
dos11 RK05 image (2.5MB, 4800 blocks)
rt11 MSCP image (32MB, 65535 blocks)
dosmt An empty file suitable for use with any magtape controller
os8 An OS/8 file system
-t type Use a different size for the container file. The size used
will be file system dependent.
@ -142,6 +147,12 @@ Full command syntax:
rl02 RL02 image (10MB, 20480 blocks)
rx20 RX20 image (512KB, 1024 blocks)
For os8, the following disk types are valid:
rk05 RK05 image (3248 blocks)
rx01 RX01 image (2002 sectors of 128 bytes each)
rx02 RX02 imgae (2002 sectors of 256 bytes each)
container The name of the file to create
type The type of the file system to create in the container

View File

@ -274,14 +274,44 @@ before you have any network running.
TOPS-10
-------
The RTFLX utility is available on TOPS-10 reading/writing files on an RX20
drive (combination of RX02 drive and controller) attached to a DECsystem-2020
(KS10). In order to access the RX20, a new system generation must be
performed. There is a help file on Tops-10 for RTFLX but no other
documentation.
Use the RTFLX utility to copy the file over to the TOPS-10 file system. When
creating the SIMH file using the "newfs" command use the "-t rx20" switch to
create a floppy image. The RX20 is a double density floppy and is only
available on KS10 systems.
.
Simulation stopped, PC: 000001 (SOJG 6,1)
sim> att ry0 xfer.dsk
RY: buffering file in memory
sim> c
There is a help file on Tops-10 for RTFLX but no other documentation. The
default TOPS-10 monitor does not include support for the RX20 so a new
system generation will be required.
.assign rxa0: rt:
RXA000 assigned
.r rtflx
RTFLX>dir
FILE TXT 1 11-Jun-87
Total of 1 block in 1 file
973 blocks free on RT:
RTFLX>copy rt:file.txt
FILE.TXT=RT:FILE.TXT
RTFLX>exit
.dir *.txt
FILE TXT 1 <057> 11-Jun-87 DSKB: [1,2]
.deassign rxa0:
.
If you use the RTFLX "ZERO" command to initialize an RT-11 file system it
will create an RT-11 V2 format file system and you will need to use the "-f"
switch to force fsio to see the file system.
I do not currently have a functioning TOPS-10 system to test this on.

3015
converters/fsio/os8.c Normal file

File diff suppressed because it is too large Load Diff

248
converters/fsio/os8.h Normal file
View File

@ -0,0 +1,248 @@
/*
* Copyright (C) 2019 John Forecast. 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JOHN FORECAST "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 AUTHOR 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.
*/
#ifndef __OS8_H__
#define __OS8_H__
/*
* General disk layout (each block is 256 12-bit words).
*
* Block
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 0 | Reserved |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 1-6 | Directory segments |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 7-12 | Keyboard Monitor | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 13-15 | User Service Routine | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 16-25 | Device Handlers | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 26 | Enter Processor For USR | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 27-50 | System Scratch Blocks | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 51-53 | Command Decoder | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 54-55 | SAVE And DATE Overlays | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 56 | Monitor Error Routine | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 57 | CHAIN Processor For USR | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 60-63 | System ODT | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 64 | Reserved For System Expansion | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 65 | CCL Reminiscences | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 66 | 12K TD8E Resident Code | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 67 | CCL Overlay | **
* +---+---+---+---+---+---+---+---+---+---+---+---+
* Files | ... |
* | ... |
* | ... |
* | ... |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* End Of Volume
*
* Blocks marked "**" are only reserved on System Devices, on non-System
* Devices, file storage starts at block 7.
*
* Directory Segment Header:
*
* Word
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 0 | Minus # of entries in this segment |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 1 | Starting block # of first file in this segment|
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 2 | Link to next directory segment |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 3 | Flag Word |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 4 | Minus # of additional information words |
* +---+---+---+---+---+---+---+---+---+---+---+---+
*
* Directory Entry:
*
* Word
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 0 | Sixbit ASCII File Name (chars 1 - 2) |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 1 | Sixbit ASCII File Name (chars 3 - 4) |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 2 | Sixbit ASCII File Name (chars 5 - 6) |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* 3 | Sixbit ASCII File Extension (chars 1 - 2) |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* | N additional information words |
* | ... |
* | ... |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* N + 4 | Minus file length in blocks |
* +---+---+---+---+---+---+---+---+---+---+---+---+
*
* If there are additional informations words in the directory, the file
* creation time is stored in word 4 (zero means not available):
*
* +---+---+---+---+---+---+---+---+---+---+---+---+
* | | | |
* +---+---+---+---+---+---+---+---+---+---+---+---+
* | | | | | |
* | | | | +-------+
* | | +---------------+ |
* +-----------+ | Year - 1970
* | Day of Month (1 - 31)
* Month (1 - 12)
*/
#define OS8_BLOCKSIZE 256 /* Size of a block on disk (words) */
#define OS8_DSSTART 1 /* Start of directory segments */
#define OS8_DSLAST 6 /* Last directory segment */
#define OS8_DATA 7 /* Start of data (non-system device) */
#define OS8_DH_ENTRIES 0 /* -(# of entries in segment) */
#define OS8_DH_START 1 /* Block # for segment start */
#define OS8_DH_NEXT 2 /* Next directory segment */
#define OS8_DH_FLAGWD 3 /* Flag word */
#define OS8_DH_EXTRA 4 /* -(# of additional info. words) */
#define OS8_DH_SIZE 5 /* Size of directory header */
#define OS8_DI_FNAME1 0 /* File name (chars 1 - 2) */
#define OS8_DI_FNAME2 1 /* File name (chars 3 - 4) */
#define OS8_DI_FNAME3 2 /* File name (chars 5 - 6) */
#define OS8_DI_EXT 3 /* File extension (1 - 2 chars) */
/* Additional words go here */
#define OS8_DI_DATE 4 /* Optional creation date */
#define OS8_DI_LENGTH 4 /* -(File length in blocks) */
#define OS8_DI_SIZE 5 /* Default entry size */
#define OS8_ED_IND 0 /* Empty directory entry */
#define OS8_ED_LENGTH 1 /* -(Empty file length in blocks) */
#define OS8_ED_SIZE 2 /* Entry size */
/*
* Device specific definitions
*/
#define OS8_RK05FS_BLKS 3248 /* Blocks in an RK05 file system */
#define OS8_RX01SS 128 /* Byte sector size of RX01 floppy */
#define OS8_RX02SS 256 /* Byte sector size of RX02 floppy */
#define OS8_RX01SS_W 64 /* Word sector size of RX01 floppy */
#define OS8_RX02SS_W 128 /* Word sector size of RX02 floppy */
#define OS8_RX0xNSECT 26 /* Sectors/track on RX01/RX02 */
#define OS8_RX0xSZ 2002 /* Sectors on an RX01/RX02 */
/*
* Structure to describe a filename. Asterisks may be used as wild card
* characters for the 2 components of a filename; namd and extension
*/
struct os8FileSpec {
uint8_t flags; /* Wild card indicators */
uint16_t name[3]; /* File name (sixbit) */
uint16_t ext; /* File extension (sixbit) */
char fname[6]; /* File name (ASCII) */
char fext[2]; /* File extension (ASCII) */
};
#define OS8_WC_NAME 001 /* Wild card in name */
#define OS8_WC_EXT 002 /* Wild card in extension */
#define OS8_M_NONE 0000 /* Wild cards not allowed */
#define OS8_M_ALLOW 0001 /* Wild cards allowed */
#define OS8_M_NONAME 0002 /* Wild cards allowed */
/* If no filename + extension */
/* present, default to *.* */
/*
* OS/8 files pack 3 bytes into a pair of 12-bit words. The following states
* are used to pack/unpack bytes.
*/
#define OS8_BYTE0 0 /* Pack/unpack byte 0 */
#define OS8_BYTE1 1 /* Pack/unpack byte 1 */
#define OS8_BYTE2 2 /* Pack/unpack byte 2 */
#define OS8_CHECK 3 /* Check for end of block/EOF */
/*
* Structure to define an open file. This is an OS/8 directory entry along
* with sufficient information to be able to write the directory entry back
* to disk.
*/
struct os8OpenFile {
uint16_t name[3]; /* File name */
uint16_t ext; /* File extension */
uint16_t creation; /* Creation date */
uint16_t length; /* File length (blocks) */
/* End of directory entry */
uint8_t segment; /* Directory segment */
uint16_t offset; /* Directory offset */
uint16_t entrysz; /* Size of directory entries */
uint16_t extra; /* Extra words in directory entries */
uint16_t remain; /* Remaining directory entries */
/* Start of read/write info */
enum openMode mode; /* Open mode (read/write) */
struct mountedFS *mount; /* Mounted file system descriptor */
uint8_t unit; /* File system # */
uint16_t *buffer; /* Private buffer for file I/O */
uint16_t start; /* Starting block # */
uint16_t current; /* Current block # */
uint16_t last; /* Last block # */
uint16_t wordpos; /* Current word offset */
uint8_t bytepos; /* Current byte position */
off_t written; /* # of bytes written to the file */
};
/*
* Device descriptor
*/
struct OS8device {
char *name; /* Device name */
uint8_t filesys; /* # of file systems on device */
size_t diskSize; /* # of blocks on device */
off_t skip; /* Reserved space at start of disk */
uint16_t blocks[8]; /* File system sizes */
int (*blockPresent)(struct mountedFS *, uint8_t, unsigned int);
int (*readBlock)(struct mountedFS *, uint8_t, unsigned int, void *);
int (*writeBlock)(struct mountedFS *, uint8_t, unsigned int, void *);
};
/*
* OS/8 specific data area
*/
struct OS8data {
unsigned int blocks; /* Size of container */
struct OS8device *device; /* Device type */
uint8_t devices; /* # of "devices" present */
uint8_t valid; /* Bitmap of valid devices */
uint16_t date; /* Date for creating files */
uint16_t buf[OS8_BLOCKSIZE]; /* Disk buffer */
};
#endif

View File

@ -45,8 +45,9 @@ static struct DiskSize {
char *name; /* Disk name */
size_t size; /* Disk size */
} rt11DiskSize[] = {
{ "rl02", RT11_RL02SZ },
{ "rx20", RT11_RX20SZ },
{ "rl02", RT11_RL02SZ * RT11_BLOCKSIZE },
{ "rx01", RT11_RX0xSZ * RT11_RX01SS },
{ "rx02", RT11_RX0xSZ * RT11_RX02SS },
{ NULL, 0 }
};
@ -337,6 +338,39 @@ int rt11MatchRegex(
return 0;
}
/*++
* M a p L o g T o P h y s
*
* Map a logical sector address to a physical sector address for an RX01/RX02
* drive.
*
* Inputs:
*
* sectno - logical sector number
*
* Outputs:
*
* None
*
* Returns:
*
* Physical sector number
*
--*/
unsigned int MapLogToPhys(
unsigned int sectno
)
{
unsigned int i, track, sector;
track = sectno / RT11_RX0xNSECT;
i = (sectno % RT11_RX0xNSECT) << 1;
if (i >= RT11_RX0xNSECT)
i++;
sector = (i + (6 * track)) % RT11_RX0xNSECT;
return sector + (track * RT11_RX0xNSECT);
}
/*++
* r t 1 1 R e a d B l o c k
*
@ -367,10 +401,10 @@ int rt11ReadBlock(
)
{
struct RT11data *data = &mount->rt11data;
void *buffer = buf == NULL ? data->buf : buf;
char *buffer = buf == NULL ? data->buf : buf;
int status = 0;
if (PARTITIONVALID(data, unit)) {
if (RT11_PARTITIONVALID(data, unit)) {
if (block > data->maxblk[unit]) {
ERROR("Attempt to read block (%u) outside file system \"%s%o:\"\n",
block, mount->name, unit);
@ -383,7 +417,25 @@ int rt11ReadBlock(
mount->name, unit, block);
#endif
status = FSioReadBlock(mount, (unit << 16) | block, buffer);
if (data->sectorsz != 0) {
/*
* The sectors making up the disk are sector-interleaved. The algorithm
* below is for RX01/RX02 interleave. Note that all such devices are
* small enough that there can only be a single file system present.
*/
unsigned int count = RT11_BLOCKSIZE / data->sectorsz;
unsigned int sectno = block * count;
do {
unsigned int sector = MapLogToPhys(sectno);
status = FSioReadSector(mount, sector, data->sectorsz, buffer);
count--;
buffer += data->sectorsz;
sectno++;
} while ((count != 0) && (status != 0));
} else status = FSioReadBlock(mount, (unit << 16) | block, buffer);
if (status == 0)
ERROR("I/O error on \"%s%o:\"\n", mount->name, unit);
@ -422,10 +474,10 @@ int rt11WriteBlock(
)
{
struct RT11data *data = &mount->rt11data;
void *buffer = buf == NULL ? data->buf : buf;
char *buffer = buf == NULL ? data->buf : buf;
int status = 0;
if (PARTITIONVALID(data, unit)) {
if (RT11_PARTITIONVALID(data, unit)) {
if (block > data->maxblk[unit]) {
ERROR("Attempt to write block (%u) outside file system \"%s%o:\"\n",
block, mount->name, unit);
@ -438,7 +490,25 @@ int rt11WriteBlock(
mount->name, unit, block);
#endif
status = FSioWriteBlock(mount, (unit << 16) | block, buffer);
if (data->sectorsz != 0) {
/*
* The sectors making up the disk are sector-interleaved. The algorithm
* below is for RX01/RX02 interleave. Note that all such devices are
* small enough that there can only be a single file system present.
*/
unsigned int count = RT11_BLOCKSIZE / data->sectorsz;
unsigned int sectno = block * count;
do {
unsigned int sector = MapLogToPhys(sectno);
status = FSioWriteSector(mount, sector, data->sectorsz, buffer);
count--;
buffer += data->sectorsz;
sectno++;
} while ((count != 0) && (status != 0));
} else status = FSioWriteBlock(mount, (unit << 16) | block, buffer);
if (status == 0)
ERROR("I/O error on \"%s%o:\"\n", mount->name, unit);
@ -450,7 +520,8 @@ int rt11WriteBlock(
/*++
* r t 1 1 R e a d D i r S e g m e n t
*
* Read a directory segment (2 disk blocks) into the mount specific buffer.
* Read a directory segment (2 file system blocks) into the mount specific
* buffer.
*
* Inputs:
*
@ -460,7 +531,7 @@ int rt11WriteBlock(
*
* Outputs:
*
* The directory segment will be read into the mount specific buffer.
* The directory segment will be read into the mount specific buffer.
*
* Returns:
*
@ -680,7 +751,7 @@ static int rt11BestFit(
* r t 1 1 M e r g e E m p t y R e g i o n s
*
* Following a delete operation, check if we can merge empty regions
* together anc compact the directory segment. In the worst case there
* together and compact the directory segment. In the worst case there
* can be 3 directory entries involved; <UNUSED>, <File>, <UNUSED>. If
* <File> is deleted we need to collapse all three <UNUSED> entries to one.
* The directory segment is currently in the mount point specific buffer.
@ -1131,7 +1202,7 @@ int rt11LookupFile(
{
struct RT11data *data = &mount->rt11data;
if (PARTITIONVALID(data, unit)) {
if (RT11_PARTITIONVALID(data, unit)) {
uint16_t entrysz, position, dsseg = 1;
do {
@ -1684,6 +1755,26 @@ static int rt11Mount(
struct RT11data *data = &mount->rt11data;
struct stat stat;
data->sectorsz = 0;
/*
* Check for device type override.
*/
if (SWISSET('t')) {
if (strcmp("rx01", SWGETVAL('t')) == 0) {
mount->skip = RT11_RX0xNSECT * RT11_RX01SS;
data->sectorsz = RT11_RX01SS;
}
if (strcmp("rx02", SWGETVAL('t')) == 0) {
mount->skip = RT11_RX0xNSECT * RT11_RX02SS;
data->sectorsz = RT11_RX02SS;
}
if (data->sectorsz == 0)
fprintf(stderr,
"mount: Ignoring unknown disk type \"%s\"\n", SWGETVAL('t'));
}
memset(&data->valid, 0, sizeof(data->valid));
if (fstat(fileno(mount->container), &stat) == 0) {
@ -1727,7 +1818,7 @@ static int rt11Mount(
mount->name, validcount, validcount == 1 ? "" : "s");
for (i = 0; (i < 256) && (validcount != 0); i++)
if (PARTITIONVALID(data, i)) {
if (RT11_PARTITIONVALID(data, i)) {
uint16_t entrysz, freeblks = 0, dsseg = 1;
uint16_t highest = 0;
@ -1756,6 +1847,10 @@ static int rt11Mount(
if (!quiet) {
char vers[4], *version = NULL;
uint16_t cnt, extra;
cnt = le16toh(data->buf[RT11_DH_COUNT]);
extra = le16toh(data->buf[RT11_DH_EXTRA]);
if (rt11ReadBlock(mount, i, RT11_HOME, NULL) == 0)
return 0;
@ -1788,11 +1883,11 @@ static int rt11Mount(
printf(" Version: %s, System ID: %12s\n",
version, (char *)&data->buf[RT11_HB_SYSID]);
printf(" Total blocks: %5d, Free blocks: %5d\n"
" Directory segments: %2d (Highest %d)\n"
" Directory segments: %2d (Highest in use: %d)\n"
" Extra bytes/directory entry: %d\n",
data->maxblk[i] + 1, freeblks,
le16toh(data->buf[RT11_DH_COUNT]), highest,
le16toh(data->buf[RT11_DH_EXTRA]));
data->maxblk[i] + 1, freeblks, cnt, highest, extra);
if (data->sectorsz != 0)
printf(" Sector size: %d\n", data->sectorsz);
}
validcount--;
}
@ -1829,7 +1924,7 @@ static void rt11Umount(
/*++
* r t 1 1 S i z e
*
* Return the size of and RT-11 container file.
* Return the size of an RT-11 container file.
*
* Inputs:
*
@ -1846,7 +1941,7 @@ static void rt11Umount(
--*/
static size_t rt11Size(void)
{
size_t size = RT11_MAXPARTSZ - 1;
size_t size = (RT11_MAXPARTSZ - 1) * RT11_BLOCKSIZE;
if (SWISSET('t')) {
int i = 0;
@ -1859,7 +1954,7 @@ static size_t rt11Size(void)
}
i++;
}
if (size == (RT11_MAXPARTSZ - 1))
if (size == ((RT11_MAXPARTSZ - 1) * RT11_BLOCKSIZE))
fprintf(stderr,
"newfs: Invalid device type \"%s\", using default\n", type);
}
@ -1893,7 +1988,43 @@ static int rt11Newfs(
{
struct RT11data *data = &mount->rt11data;
int i;
uint16_t checksum = 0;
uint16_t checksum = 0, extra = 0;;
/*
* Check for device type override.
*/
if (SWISSET('t')) {
if (strcmp("rx01", SWGETVAL('t')) == 0) {
mount->skip = RT11_RX0xNSECT * RT11_RX01SS;
data->sectorsz = RT11_RX01SS;
}
if (strcmp("rx02", SWGETVAL('t')) == 0) {
mount->skip = RT11_RX0xNSECT * RT11_RX02SS;
data->sectorsz = RT11_RX02SS;
}
}
/*
* Check for extra bytes on each directory entry, rounded up to nearest
* even value.
*/
if (SWISSET('e')) {
char *endptr;
extra = strtoul(SWGETVAL('e'), &endptr, 10);
extra = (extra + 1) & ~1;
if ((extra > 63) || (*endptr != '\0')) {
fprintf(stderr, "newfs: bad -e switch value \"%s\" - ignored\n",
SWGETVAL('e'));
extra = 0;
}
}
/*
* Remove possible first track
*/
size = ((size * RT11_BLOCKSIZE) - mount->skip) / RT11_BLOCKSIZE;
/*
* Mark partition 0 as valid
@ -1901,6 +2032,7 @@ static int rt11Newfs(
memset(data->valid, 0, sizeof(data->valid));
data->valid[0] = 1;
data->maxblk[0] = size;
data->first[0] = RT11_DSSTART;
data->filesystems = 1;
/*
@ -1931,6 +2063,7 @@ static int rt11Newfs(
data->buf[RT11_DH_COUNT] = htole16(RT11_DS_MAX);
data->buf[RT11_DH_HIGHEST] = htole16(1);
data->buf[RT11_DH_EXTRA] = htole16(extra);
data->buf[RT11_DH_START] = htole16(RT11_DSSTART + (2 * RT11_DS_MAX));
if (i == 1) {
@ -1977,7 +2110,7 @@ static void rt11Info(
struct RT11data *data = &mount->rt11data;
if (present) {
if (PARTITIONVALID(data, unit))
if (RT11_PARTITIONVALID(data, unit))
info(mount, unit);
} else {
uint16_t i, count = data->filesystems;
@ -1986,7 +2119,7 @@ static void rt11Info(
* Display information about all valid partitions
*/
for (i = 0; (i < 256) && (count != 0); i++)
if (PARTITIONVALID(data, i)) {
if (RT11_PARTITIONVALID(data, i)) {
info(mount, i);
count--;
}
@ -2027,7 +2160,7 @@ static void rt11Dir(
return;
}
if (PARTITIONVALID(data, unit)) {
if (RT11_PARTITIONVALID(data, unit)) {
uint16_t entrysz, dsseg = 1;
regex_t reg;
@ -2404,7 +2537,7 @@ static size_t rt11ReadFile(
* # of bytes of data written, 0 means EOF or error
*
--*/
size_t rt11WriteFile(
static size_t rt11WriteFile(
void *filep,
void *buf,
size_t buflen

View File

@ -166,6 +166,9 @@
#define RT11_HOME 1 /* Home block is always 1 */
#define RT11_DSSTART 6 /* Start of directory segs */
#define RT11_BLOCKSIZE 512 /* Size of a data block on disk */
#define RT11_RX01SS 128 /* Sector size of RX01 floppy */
#define RT11_RX02SS 256 /* Sector size of RX02 floppy */
#define RT11_RX0xNSECT 26 /* Sectors/track on RX01/RX02 */
#define RT11_SYSVER_V3A 36521
#define RT11_SYSVER_V04 36434
@ -181,15 +184,15 @@
#define RT11_VMSSYSID "DECVMSEXCHNG" /* VMS exchange created volume */
/*
* Partition sizes. The last block os a maximum sized partition is unused.
* The minimum size is based on a file system having 1 directory segment and
* 1 data block! Is this reasonable?
* Partition sizes. The last block of a maximum sized partition (32MB) is
* unused. The minimum size is based on a file system having 1 directory
* segment and 1 data block! Is this reasonable?
*/
#define RT11_MAXPARTSZ 0200000 /* Max partition size */
#define RT11_MINPARTSZ 0000010 /* Min partition size */
#define RT11_RL02SZ 20480 /* Size of an RL02 drive */
#define RT11_RX20SZ 1024 /* Size of an RX20 floppy drive */
#define RT11_RL02SZ 20480 /* Blocks on an RL02 drive */
#define RT11_RX0xSZ 2002 /* Sectors on an RX01/RX02 */
#define RT11_HB_BBLOCK 0000 /* Bad block replacement tbl */
#define RT11_HB_RESTORE 0102 /* INIT/RESTORE data area */
@ -287,6 +290,8 @@ struct rt11OpenFile {
*/
struct RT11data {
unsigned int blocks; /* Size of container */
unsigned int sectorsz; /* Interleave sector size */
/* 0 if no interleave */
uint16_t filesystems; /* Max # of filesystems */
uint16_t valid[16]; /* Valid partitions */
uint16_t maxblk[256]; /* Max block address */
@ -294,6 +299,6 @@ struct RT11data {
uint16_t buf[512]; /* Disk buffer - enough for a */
/* directory segment */
};
#define PARTITIONVALID(d, u) ((d->valid[u / 16] & (1 << (u % 16))) != 0)
#define RT11_PARTITIONVALID(d, u) ((d->valid[u / 16] & (1 << (u % 16))) != 0)
#endif

20
extracters/ods2/Makefile Normal file
View File

@ -0,0 +1,20 @@
# all of these can be over-ridden on the "make" command line if they don't suit your environment.
TOOL=ods2
CFLAGS=-O2 -Wall -Wshadow -Wextra -pedantic -Woverflow -Wstrict-overflow
BIN=/usr/local/bin
INSTALL=install
CC=gcc
$(TOOL): $(TOOL).c access.c cache.c device.c direct.c phynt.c rms.c vmstime.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $(TOOL) $(TOOL).c access.c cache.c device.c direct.c phynt.c rms.c vmstime.c $(LDLIBS)
.PHONY: clean install uninstall
clean:
rm -f $(TOOL)
install: $(TOOL)
$(INSTALL) -p -m u=rx,g=rx,o=rx $(TOOL) $(BIN)
uninstall:
rm -f $(BIN)/$(TOOL)