Various os/8 and rt11 fixes. Add support for Unix V7.

This commit is contained in:
John Forecast
2025-01-14 19:14:37 -05:00
committed by Timothe Litt
parent a6fb802807
commit 405010f948
21 changed files with 3847 additions and 160 deletions

View File

@@ -33,3 +33,36 @@ Changes Since Alpha Release:
- Merged change from tvrusso to fix compilation on FreeBSD
20-Aug-20
- Fixed bug in OS/8 file deletion which incorrectly reduced the directory
file count by 1
- Fix ASCII mode read in OS/8 where it would read an entire block into
memory rather than a single line. When copying to local:, this would
result in the destination file having unexpected <CR> characters.
15-Feb-21
- Added support Research Unix V7 file systems of RK05, RL01 and RL02 drives
using file system type "unixv7"
3-Mar-23
- Added support for RK06 and RK07 Unix V7 drives
- Added support for creating arbitrary sized Unix V7 file systems
26-Sep-24
- Fixed display of System ID during RT-11 mount if there is non-zero data
following the System ID on the disk
13-Nov-24
- Fixed OS/8 ASCII file read/write to to handle ^Z marking the end of file
28-Nov-24
- Fixed RT11 scan to find the size of the partition. The old code would
incorrectly terminate on an EMPTY marker rather than END-OF-SEGMENT.

View File

@@ -7,14 +7,15 @@ INSTALL=install
CC=gcc
EXECUTABLE=fsio
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
SOURCES=fsio.c declib.c tape.c dos11.c rt11.c dosmt.c local.c os8.c unixv7.c
INCLUDES=fsio.h declib.h tape.h dos11.h rt11.h dosmt.h os8.h unixv7.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
MANPAGE_UNIXV7=fsio-unixv7.1
ARCHIVE=fsio.tgz
RELEASEFILES=$(BIN)/$(EXECUTABLE)
@@ -23,8 +24,16 @@ RELEASEFILES+=$(MAN)/$(MANPAGE_DOS)
RELEASEFILES+=$(MAN)/$(MANPAGE_RT)
RELEASEFILES+=$(MAN)/$(MANPAGE_DOSMT)
RELEASEFILES+=$(MAN)/$(MANPAGE_OS8)
RELEASEFILES+=$(MAN)/$(MANPAGE_UNIXV7)
RELEASEFILES+=./fsio.txt ./fsioSimh.txt
MANPAGES=$(MANPAGE)
MANPAGES+=$(MANPAGE_DOS)
MANPAGES+=$(MANPAGE_RT)
MANPAGES+=$(MANPAGE_DOSMT)
MANPAGES+=$(MANPAGE_OS8)
MANPAGES+=$(MANPAGE_UNIXV7)
$(EXECUTABLE): $(SOURCES) $(INCLUDES) Makefile
$(CC) $(CFLAGS) $(DEFINES) -o $(EXECUTABLE) $(SOURCES) $(LIBS)
@@ -33,7 +42,7 @@ $(EXECUTABLE): $(SOURCES) $(INCLUDES) Makefile
clean:
rm -f $(EXECUTABLE)
install: $(EXECUTABLE) $(MANPAGE) $(MANPAGE_DOS) $(MANPAGE_RT)
install: $(EXECUTABLE) $(MANPAGES)
$(INSTALL) -p -m u=rx,g=rx,o=rx $(EXECUTABLE) $(BIN)
mkdir -p $(MAN)
$(INSTALL) -p -m u=r,g=r,o=r $(MANPAGE) $(MAN)
@@ -41,6 +50,7 @@ install: $(EXECUTABLE) $(MANPAGE) $(MANPAGE_DOS) $(MANPAGE_RT)
$(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)
$(INSTALL) -p -m u=r,g=r,o=r $(MANPAGE_UNIXV7) $(MAN)
uninstall:
rm -f $(BIN)/$(EXECUTABLE)
@@ -49,6 +59,7 @@ uninstall:
rm -f $(MAN)/$(MANPAGE_RT)
rm -f $(MAN)/$(MANPAGE_DOSMT)
rm -f $(MAN)/$(MANPAGE_OS8)
rm -f $(MAN)/$(MANPAGE_UNIXV7)
# This assumes that fsio has been "installed" on the current system
archive: $(RELEASEFILES)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 John Forecast. All Rights Reserved.
* Copyright (C) 2018 - 2025 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:
@@ -2473,6 +2473,7 @@ struct FSdef dos11FS = {
dos11Umount,
dos11Size,
dos11Newfs,
NULL,
dos11Set,
dos11Info,
dos11Dir,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 John Forecast. All Rights Reserved.
* Copyright (C) 2018 - 2025 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:
@@ -385,9 +385,21 @@ static int dosmtReadBytes(
break;
}
}
*buf++ = file->buf[file->nextb++];
len--;
count++;
if (SWISSET('a')) {
char ch = file->buf[file->nextb++] & 0177;
if ((ch != 0) && (ch != 0177)) {
*buf++ = ch;
count++;
}
len--;
if (ch == '\n')
break;
} else {
*buf++ = file->buf[file->nextb++];
len--;
count++;
}
}
return count;
}
@@ -982,6 +994,7 @@ static void *dosmtOpenFileW(
file->nextb = 0;
file->tm = 0;
file->error = 0;
memset(file->buf, 0, DOSMTRCLNT);
}
return file;
}
@@ -1015,8 +1028,8 @@ static off_t dosmtFileSize(
uint32_t length;
/*
* Compute the length of this file. The estimate may larger than the
* actual size of the file size don't know the actual EOF position
* Compute the length of this file. The estimate may be larger than the
* actual size of the file since we don't know the actual EOF position
* within the last block of the file.
*/
do {
@@ -1097,13 +1110,21 @@ static void dosmtCloseFile(
data->eot = tapeGetPosition(mount->container);
if (tapeWriteEOM(mount->container, 1) == 0)
/*
* Write 2 tape marks indicating the end of tape (DOS/BATCH requires
* 3 TM in a row, 1 for the EOF and the last 2 to indicate EOT) and then
* backup over the last 2 TMs.
*/
if ((tapeWriteTM(mount->container) == 0) ||
(tapeWriteTM(mount->container) == 0))
file->error = 1;
if (file->error != 0) {
ERROR("Panic: Error writing on \"%s\"\n", mount->name);
exit(3);
}
tapeSetPosition(mount->container, data->eot);
}
free(file);
@@ -1304,6 +1325,7 @@ struct FSdef dosmtFS = {
dosmtUmount,
NULL,
NULL,
NULL,
dosmtSet,
dosmtInfo,
dosmtDir,

View File

@@ -1,4 +1,4 @@
.TH FSIO-DOS11 1 "Jun 21,2019" "FFS I/O - DOS-11"
.TH FSIO-DOS11 1 "Feb 14,2021" "FFS I/O - DOS-11"
.SH NAME
fsio-dos11 \- Foreign File System I/O - DOS-11
.br
@@ -14,6 +14,9 @@ group number and user number. Wildcard characters are only valid with the
.SH NEWFS OPERATION
\fInewfs\fP creates a blank RK05 image (2.5MB, 4800 blocks) with no UFD
entries.
.SH COPY OPERATION
In ASCII mode ('-a'), characters will be converted to 7-bits and NULL and
delete characters will not be copied.
.SH SET OPERATION
The following \fIset\fP commands are supported:
.br
@@ -46,6 +49,7 @@ Creates an empty UFD and sets default UIC for file access.
.BR fsio-rt11 (1)
.BR fsio-dosmt (1)
.BR fsio-os8 (1)
.BR fsio-unixv7 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@@ -1,4 +1,4 @@
.TH FSIO-DOSMT 1 "Jun 25,2019" "FFS I/O - DOS-11 magtape"
.TH FSIO-DOSMT 1 "Feb 14,2021" "FFS I/O - DOS-11 magtape"
.SH NAME
fsio-dosmt \- Foreign File System I/O - DOS-11 magtape
.br
@@ -31,6 +31,9 @@ command, fsio will make use of the extra 3 characters on file lookup,
directory listing and file creation.
.SH NEWFS OPERATION
\fInewfs\fP creates an empty (zero length) file.
.SH COPY OPERATION
In ASCII mode ('-a'), characters will be converted to 7-bits and NULL and
delete characters will not be copied.
.SH SET OPERATION
The following \fIset\fP commands are supported:
.br
@@ -106,6 +109,7 @@ determine the current tape position).
.BR fsio-dos11 (1)
.BR fsio-rt11 (1)
.BR fsio-os8 (1)
.BR fsio-unixv7 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@@ -1,4 +1,4 @@
.TH FSIO-OS8 1 "Sep 218,2019" "FFS I/O - OS/8"
.TH FSIO-OS8 1 "Feb 14,2021" "FFS I/O - OS/8"
.SH NAME
fsio-os8 \- Foreign File System I/O - OS/8
.br
@@ -15,16 +15,16 @@ 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
"\fI-t 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
\fImount\fP requires the "\fI-t 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
"\fI-t type\fP" switch is present a different container file will be created
depending on the type of the device specified:
.br
.RS
@@ -75,6 +75,7 @@ the default state after mount.
.BR fsio-dos11 (1)
.BR fsio-dosmt (1)
.BR fsio-rt11 (1)
.BR fsio-unixv7 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@@ -1,4 +1,4 @@
.TH FSIO-RT11 1 "Jun 25,2019" "FFS I/O - RT-11"
.TH FSIO-RT11 1 "Feb 14,2021" "FFS I/O - RT-11"
.SH NAME
fsio-rt11 \- Foreign File System I/O - RT-11
.br
@@ -84,6 +84,7 @@ No \fIset\fP commands are currently supported.
.BR fsio-dos11 (1)
.BR fsio-dosmt (1)
.BR fsio-os8 (1)
.BR fsio-unixv7 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@@ -0,0 +1,74 @@
.TH FSIO-UNIXV7 1 "Mar 2,2023" "FFS I/O - UNIX V7"
.SH NAME
fsio-unixv7 \- Foreign File System I/O - Unix V7
.br
.SH DESCRIPTION
\fBfsio\fP allows access to Unix V7 file systems using the file system type
"\fIunixv7\fP". Note that you must use "\fI/etc/rawfs\fP" on Ultrix-11 3.0/3.1
to access files on disks created by \fBfsio\fP.
.br
.SH UNIX V7 PHYSICAL DISKS
UNIX V7 uses a logical block size of 512 bytes. \fBfsio\fP supports access to
disks which have their super block stored at block 2. Unix V7 does not write
any type of signature on the device so the \fImount\fP command uses a set of
heuristics to determine if the file system is valid.
.SH MOUNT OPERATION
\fImount\fP accepts the optional "\fI-t type\fP" switch to provide an additonal
check on the integrity of the file system (e.g. check for blocks addresses
larger than the specified disk) (See NEWFS OPERATION below for details).
.br
\fImount\fP also accepts the optional "\fI-o nnn\fP" switch where nnn is the
block offset of the start of the partition to be mounted. Since most, if not
all, UNIX V7 implementations hard code the partition layout for a specific
disk within the device driver, you will have to examine the device driver
code to calculate this offset.
.SH NEWFS OPERATION
\fInewfs\fP requires either the "\fI-b blocks\fP" or the "\fI-t type\fP" switch
to determine the size of the container file to be created:
.br
.RS
.TP
\fIrk05\fP \- RK05 image (2436 blocks, 776 inodes)
.br
.TP
\fIrl01\fP \- RL01 image (10240 blocks, 3272 inodes)
.br
.TP
\fIrl02\fP \- RL02 image (20480 blocks, 6552 inodes)
.br
.TP
\fIrk06\fP \- RK06 image (27126 blocks, 8680 inodes)
.br
.TP
\fIrk07\fP \- RK07 image (53790 blocks, 17208 inodes)
.br
.RE
.br
If neither switch is present, an RK05-sized disk will be created.
.br
By default, inodes occupy 4% of the disk space. This can be overridden by
using the "\fI-i num\fP" switch, where \fInum\fP can be in the range 8 - 65500
and the resulting inode space cannot occupy more than 50% of the disk space
(8 inodes consume 1 disk block).
.br
.SH SET OPERATION
The following \fIset\fP commands are supported:
.br
.TP
.B "\fIuid\fP n"
Sets the default UID for created files and directories (was 0 after mount).
.TP
.B "\fIgid\fP n"
Sets the default GID for created files and directories (was 0 after mount).
.SH SEE ALSO
.BR fsio (1)
.BR fsio-dos11 (1)
.BR fsio-dosmt (1)
.BR fsio-os8 (1)
.BR fsio-rt11 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@@ -1,4 +1,4 @@
.TH FSIO 1 "Sep 17,2019" "Foreign File System I/O"
.TH FSIO 1 "Mar 2,2023" "Foreign File System I/O"
.SH NAME
fsio \- Foreign File System I/O
.SH SYNOPSIS
@@ -34,54 +34,56 @@ verb [switches] args ...
The following verbs are supported:
.br
.B "\fImount\fP \- make a container file available to fsio"
.B "\fImount\fP \- Make a container file available to fsio"
.br
.B "\fIumount\fP \- remove knowledge of a container file from fsio"
.B "\fIumount\fP \- Remove knowledge of a container file from fsio"
.br
.B "\fInewfs\fP \- create and new container and empty file system"
.B "\fInewfs\fP \- Create a new container and empty file system"
.br
.B "\fIset\fP \- set parameters on a mounted file system"
.B "\fImkdir\fP \- Create a new empty directory on a mounted file system"
.br
.B "\fIinfo\fP \- display information about the container file system"
.B "\fIset\fP \- Set parameters on a mounted file system"
.br
.B "\fIdir\fP \- list a directory"
.B "\fIinfo\fP \- Display information about the container file system"
.br
.B "\fIdump\fP \- dump a file in hex or octal"
.B "\fIdir\fP \- List a directory"
.br
.B "\fIcopy\fP \- copy a single file"
.B "\fIdump\fP \- Dump a file in hex or octal"
.br
.B "\fItype\fP \- type a file on the terminal"
.B "\fIcopy\fP \- Copy a single file"
.br
.B "\fIdelete\fP \- delete a file"
.B "\fItype\fP \- Type a file on the terminal"
.br
.B "\fIstatus\fP \- display currently mounted file systems"
.B "\fIdelete\fP \- Delete a file"
.br
.B "\fIdo\fP \- echo and execute commands from a file"
.B "\fIstatus\fP \- Display currently mounted file systems"
.br
.B "\fIhelp\fP \- display help on using fsio"
.B "\fIdo\fP \- Echo and execute commands from a file"
.br
.B "\fIexit\fP \- terminate fsio (quit is an alias for exit)"
.B "\fIhelp\fP \- Display help on using fsio"
.br
.B "\fIexit\fP \- Terminate fsio (quit is an alias for exit)"
.br
.TP
The following commands are only accepted by file systems which are on magtape devices:
.br
.B "\fIrewind\fP \- position the tape to the start of the data stream"
.B "\fIrewind\fP \- Position the tape to the start of the data stream"
.br
.B "\fIeom\fP \- position the tape to the end of the data stream"
.B "\fIeom\fP \- Position the tape to the end of the data stream"
.br
.B "\fIskipf\fP \- position the tape by skipping forward over files"
.B "\fIskipf\fP \- Position the tape by skipping forward over files"
.br
.B "\fIskipr\fP \- position the tape by skipping backward over files"
.B "\fIskipr\fP \- Position the tape by skipping backward over files"
.br
.SH COMMANDS
.TP
.B "\fImount\fP [-dfrx] [-t type] dev[:] file type"
Make the container file available to fsio.
.B "\fImount\fP [-dfrx] [-t type] [-o nnn] dev[:] file type"
Make the container file available to \fBfsio\fP.
.br
.RS
.RS
.B "\fI\-d\fP \- generate debug output on stdout"
.B "\fI\-d\fP \- Generate debug output on stdout"
.br
.B " Use environment variable \fIFSioDebugLog\fP to"
.br
@@ -89,44 +91,62 @@ Make the container file available to fsio.
.br
.B " Only available if built with DEBUG enabled"
.br
.B "\fI\-f\fP \- bypass home block validation (RT-11 only)"
.B "\fI\-f\fP \- Bypass home block validation (RT-11 only)"
.br
.B "\fI\-r\fP \- mount file system read-only"
.B "\fI\-o nnn\fP \- Specify partition block offset (unixv7 only)"
.br
.B "\fI\-t type\fP \- specify optional disk type"
.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"
.B "\fIdev[:]\fP \- User supplied name for the mount"
.br
.B "\fIfile\fP \- name of the container file"
.B "\fIfile\fP \- Name of the container file"
.br
.B "\fItype\fP \- type of container file system"
.B "\fItype\fP \- Type of container file system"
.br
.RE
.RE
.TP
.B "\fIumount\fP dev[:]"
Remove knowledge of the container file from fsio.
Remove knowledge of the container file from \fBfsio\fP.
.br
.RS
.RS
.B "\fIdev[:]\fP \- name supplied on a previous mount"
.B "\fIdev[:]\fP \- Name supplied on a previous mount"
.RE
.RE
.TP
.B "\fInewfs\fP [-t type] [-e count] file type"
.B "\fInewfs\fP [-b blks] [-t type] [-e n] [-i n] 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"
.B "\fI\-b blks\fP \- Specify file system size (unixv7)"
.br
.B "\fI\-e n\fP \- Specify extra space for directory entries (RT11, OS/8)"
.B "\fI\-t type\fP \- Use alternate, device-dependent size"
.br
.B "\fIfile\fP \- name of the container file"
.B "\fI\-e n\fP \- Specify extra space for directory entries"
.br
.B "\fItype\fP \- type of container file system"
.B " (RT11, OS/8)"
.br
.B "\fI\-i n\fP \- Specify inode count (8 to 65500) (UnixV7)"
.br
.B "\fIfile\fP \- Name of the container file"
.br
.B "\fItype\fP \- Type of container file system"
.br
.RE
.RE
.TP
.B "\fImkdir\fP [-p] dev:dirspec"
Create a new empty directory on a mounted file system.
.br
.RS
.RS
.B "\fI\-p\fP \- Create any missing intermediate directories"
.br
.RE
.RE
@@ -136,9 +156,9 @@ Set parameters on a mounted file system.
.br
.RS
.RS
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.B "\fIargs ...\fP\- arguments are passed on to the file system"
.B "\fIargs ...\fP\- Arguments are passed on to the file system"
.br
.RE
.RE
@@ -148,7 +168,7 @@ Display information about the file system(s) within the container file.
.br
.RS
.RS
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.RE
.RE
.TP
@@ -157,13 +177,13 @@ List the contents of a specific directory.
.br
.RS
.RS
.B "\fI\-f\fP \- display a full (vs. brief) directory"
.B "\fI\-f\fP \- Display a full (vs. brief) directory"
.br
.B "\fI\-n\fP \- don't rewind tape before listing directory"
.B "\fI\-n\fP \- Don't rewind tape before listing directory"
.br
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.B "\fIdirspec\fP \- filespec to display, may include wildcards"
.B "\fIdirspec\fP \- Filespec to display, may include wildcards"
.br
.RE
.RE
@@ -173,45 +193,45 @@ Dump the contents of the file in octal, hex or characters.
.br
.RS
.RS
.B "\fI\-b\fP \- dump byte (8-bits) at a time"
.B "\fI\-b\fP \- Dump byte (8-bits) at a time"
.br
.B "\fI\-c\fP \- dump in character format"
.B "\fI\-c\fP \- Dump in character format"
.br
.B "\fI\-d\fP \- dump double-word (32-bits) at a time"
.B "\fI\-d\fP \- Dump double-word (32-bits) at a time"
.br
.B "\fI\-w\fP \- dump word (16-bits) at a time"
.B "\fI\-w\fP \- Dump word (16-bits) at a time"
.br
.B "\fI\-x\fP \- dump in hex format (default is octal)"
.B "\fI\-x\fP \- Dump in hex format (default is octal)"
.br
.B "\fI\-n\fP \- don't rewind magtape before looking for file"
.B "\fI\-n\fP \- Don't rewind magtape before looking for file"
.br
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.B "\fIdirspec\fP \- filespec to dump"
.B "\fIdirspec\fP \- Filespec to dump"
.br
.RE
.RE
.TP
.B "\fIcopy\fP [-anpc blks] dev1:srcfile dev2:dstfile"
.B "\fIcopy\fP [-anp] [-c blks] dev1:srcfile dev2:dstfile"
Copy a file.
.br
.RS
.RS
.B "\fI\-a\fP \- copy in ASCII mode (translates line endings)"
.B "\fI\-a\fP \- Copy in ASCII mode (translates line endings)"
.br
.B "\fI\-p\fP \- pad the file with NULLs"
.B "\fI\-p\fP \- Pad the file with NULLs"
.br
.B "\fI\-n\fP \- don't rewind magtape before looking for input file"
.B "\fI\-n\fP \- Don't rewind magtape before looking for input file"
.br
.B "\fI\-c blks\fP \- make contiguous file of specified size"
.B "\fI\-c blks\fP \- Make contiguous file of specified size"
.br
.B "\fIdev1:\fP \- name supplied on a previous mount"
.B "\fIdev1:\fP \- Name supplied on a previous mount"
.br
.B "\fIsrcfile\fP \- source file to copy"
.B "\fIsrcfile\fP \- Source file to copy"
.br
.B "\fIdev2:\fP \- name supplied on a previous mount"
.B "\fIdev2:\fP \- Name supplied on a previous mount"
.br
.B "\fIdstfile\fP \- destination file to copy"
.B "\fIdstfile\fP \- Destination file to copy"
.br
.RE
.RE
@@ -221,11 +241,11 @@ Types the contents of the file on stdout.
.br
.RS
.RS
.B "\fI\-n\fP \- don't rewind magtape before looking for file"
.B "\fI\-n\fP \- Don't rewind magtape before looking for file"
.br
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.B "\fIfilespec\fP\- filespec to type"
.B "\fIfilespec\fP\- Filespec to type"
.br
.RE
.RE
@@ -235,9 +255,9 @@ Deletes the specified file.
.br
.RS
.RS
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.B "\fIfilespec\fP\- filespec to delete"
.B "\fIfilespec\fP\- Filespec to delete"
.br
.RE
.RE
@@ -251,9 +271,9 @@ Echo and execute commands from a file.
.br
.RS
.RS
.B "\fI\-q\fP \- don't echo commands as they are read"
.B "\fI\-q\fP \- Don't echo commands as they are read"
.br
.B "\fIcmdFile\fP \- file containing fsio commands"
.B "\fIcmdFile\fP \- File containing \fBfsio\fP commands"
.br
.RE
.RE
@@ -263,7 +283,7 @@ Displays help text on stdout.
.br
.TP
.B "\fIexit\fP"
Causes fsio to exit (the quit command has the same effect).
Causes \fBfsio\fP to exit (the quit command has the same effect).
.br
.TP
.B "\fIrewind\fP dev:"
@@ -271,7 +291,7 @@ Positions the device to the start of the tape.
.br
.RS
.RS
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.RE
.RE
@@ -281,7 +301,7 @@ Positions the device to the end of the tape.
.br
.RS
.RS
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.RE
.RE
@@ -291,7 +311,7 @@ Positions the device by skipping forward over files.
.br
.RS
.RS
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.B "\fIn\fP \- # of files to skip (must be > 0)"
.br
@@ -303,7 +323,7 @@ Positions the device by skipping backward over files.
.br
.RS
.RS
.B "\fIdev:\fP \- name supplied on a previous mount"
.B "\fIdev:\fP \- Name supplied on a previous mount"
.br
.B "\fIn\fP \- # of files to skip (must be > 0)"
.br
@@ -331,13 +351,16 @@ 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"
.B "\fIos8\fP \- OS/8 on RX01, RX02 or RK05"
.br
.B "\fIunixv7\fP \- Unix V7"
.br
.SH SEE ALSO
.BR fsio-dos11 (1),
.BR fsio-rt11 (1)
.BR fsio-dosmt (1)
.BR fsio-os8 (1)
.BR fsio-unixv7 (1)
.SH AUTHOR
John Forecast, <john@forecast.name>
.br

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 John Forecast. All Rights Reserved.
* Copyright (C) 2018 - 2025 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:
@@ -85,7 +85,7 @@
* 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 if the file system is
* invalid and -1 if the file system is invalid and an erroir message
* invalid and -1 if the file system is invalid and an error message
* has already been printed.
*
* void (*umount)(struct mountedFS *mount);
@@ -97,8 +97,10 @@
*
* size_t (*size)(void)
*
* Return the number of byte used for the container file. The command
* line switch (-t type) may be used to override the default size.
* Return the number of bytes used for the container file. The command
* line switch (-t type) may be used to override the default size. If
* there is a problem computing the size of a container file (e.g. -t
* switch missing), print an error message and return (size_t)-1.
*
* int (*newfs)(struct mountedFS *mount, size_t size);
*
@@ -108,6 +110,15 @@
* by this command. This routine returns 1 if the file system was
* successfully created, 0 otherwise.
*
* int (*mkdir)(struct mountedFS *mount, uint8_t unit, char *fname);
*
* Create a new empty directory on the mounted file system. This routine
* returns 1 if the directory was successfully created, 0 otherwise. If
* the "-p" switch is present (SWISSET('p')), any missing intermediate
* directories will be created. If the "-p" switch is present and 0 is
* returned, an unknown number of intermediate directories may have
* been created.
*
* void (*set)(struct mountedFS *mount, uint8_t unit, uint8_t present);
*
* This routine is called when processing a "set" command. The arguments
@@ -123,7 +134,7 @@
* FS_UNITVALID set (see above), "present" is non-zero if a unit number
* was included on the command line. For example, RT-11 uses "present"
* to decide whether to display information about a single file system
* ("present" 0) or all file systems in the containder ("present" 1).
* ("present" 0) or all file systems in the container ("present" 1).
*
* void (*dir)(struct mountedFS *mount, uint8_t unit, char *fname);
*
@@ -284,6 +295,7 @@ int verbose = 0, quiet = 0;
static void doMount(void);
static void doUmount(void);
static void doNewfs(void);
static void doMkdir(void);
static void doSet(void);
static void doInfo(void);
static void doDir(void);
@@ -311,12 +323,13 @@ struct command {
cmd_t func; /* Command execution function */
} cmdTable[] = {
#ifdef DEBUG
{ "mount", OPTIONS("dfrt:x"), 3, 3, 0, doMount },
{ "mount", OPTIONS("dfo:rt:x"), 3, 3, 0, doMount },
#else
{ "mount", OPTIONS("frt:x"), 3, 3, 0, doMount },
{ "mount", OPTIONS("fo:rt:x"), 3, 3, 0, doMount },
#endif
{ "umount", NULL, 1, 1, 0, doUmount },
{ "newfs", OPTIONS("e:t:"), 2, 2, 0, doNewfs },
{ "newfs", OPTIONS("b:e:i:t:"), 2, 2, 0, doNewfs },
{ "mkdir", OPTIONS("p"), 1, 1, 0, doMkdir },
{ "set", NULL, 2, MAX_CMDLEN, 0, doSet },
{ "info", NULL, 1, 1, 0, doInfo },
{ "dir", OPTIONS("fn"), 1, 1, 0, doDir },
@@ -336,6 +349,8 @@ struct command {
{ NULL, NULL, 0, 0, 0, doExit }
};
char *command = NULL; /* Current command being executed */
/*
* Switches and values
*/
@@ -406,6 +421,7 @@ extern struct FSdef dos11FS;
extern struct FSdef rt11FS;
extern struct FSdef dosmtFS;
extern struct FSdef os8FS;
extern struct FSdef unixv7FS;
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -463,6 +479,9 @@ static void FSioInit(void)
os8FS.next = fileSystems;
fileSystems = &os8FS;
unixv7FS.next = fileSystems;
fileSystems = &unixv7FS;
}
/*++
@@ -609,7 +628,6 @@ static int checkDev(
*
* Inputs:
*
* cmd - current command name
* dev - pointer to device name + file specification
* unit - return optional unit number here
* present - return unit present indicator here (0 or 1)
@@ -626,7 +644,6 @@ static int checkDev(
*
--*/
static struct mountedFS *findMount(
char *cmd,
char *dev,
uint8_t *unit,
uint8_t *present,
@@ -655,13 +672,15 @@ static struct mountedFS *findMount(
unitno = strtoul(&dev[i], &endptr, 8);
if (*endptr != '\0') {
fprintf(stderr,
"%s: Device \"%s\" unit number invalid\n", cmd, origdev);
"%s: Device \"%s\" unit number invalid\n",
command, origdev);
return NULL;
}
if (unitno > 0377) {
fprintf(stderr,
"%s: Device \"%s\" unit number too large\n", cmd, origdev);
"%s: Device \"%s\" unit number too large\n",
command, origdev);
return NULL;
}
dev[i] ='\0';
@@ -670,7 +689,7 @@ static struct mountedFS *findMount(
}
fprintf(stderr,
"%s: Device \"%s\" contains non-alpha character\n",
cmd, origdev);
command, origdev);
return NULL;
}
@@ -683,12 +702,13 @@ static struct mountedFS *findMount(
((fs->filesys->flags & FS_UNITVALID) != 0))
break;
fprintf(stderr,
"%s: \"%s\" does not support unit numbers\n", cmd, fs->name);
"%s: \"%s\" does not support unit numbers\n",
command, fs->name);
return NULL;
}
if (fs == NULL)
fprintf(stderr, "%s: Device \"%s\" not mounted\n", cmd, origdev);
fprintf(stderr, "%s: Device \"%s\" not mounted\n", command, origdev);
} else {
if (getenv("FSioForceLocal") != NULL) {
fprintf(stderr, "Local file system access requires use of \"local:\"\n");
@@ -938,11 +958,14 @@ static void doNewfs(void)
/*
* Get the required container file size.
*/
if (filesys->size != NULL)
if (filesys->size != NULL) {
size = (*filesys->size)();
if (size == (size_t)-1)
return;
}
if ((mount.container = fopen(words[0], "w+")) != NULL) {
off_t offset = size - 1;
off_t offset = size ? size - 1 : 0;
mount.skip = 0;
@@ -971,6 +994,39 @@ static void doNewfs(void)
} else fprintf(stderr, "newfs: \"%s\" is not a supported file system type\n", words[1]);
}
/*++
* d o M k d i r
*
* Create a new empty directory on a mounted file system. This command is
* only available if the file system supports multiple directories.
*
* Inputs:
*
* None
*
* Outputs:
*
* None
*
* Returns:
*
* None
*
--*/
static void doMkdir(void)
{
struct mountedFS *mount;
char *fname;
uint8_t unit, present;
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if (mount->filesys->mkdir != NULL)
(*mount->filesys->mkdir)(mount, unit, fname);
else fprintf(stderr, "mkdir: \"%s\" does not support \"mkdir\" command\n",
mount->filesys->fstype);
}
}
/*++
* d o S e t
*
@@ -995,7 +1051,7 @@ static void doSet(void)
char *fname;
uint8_t unit, present;
if ((mount = findMount("set", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if (*fname == '\0') {
if (mount->filesys->set != NULL)
(*mount->filesys->set)(mount, unit, present);
@@ -1029,7 +1085,7 @@ static void doInfo(void)
char *fname;
uint8_t unit, present;
if ((mount = findMount("info", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if (*fname == '\0')
(*mount->filesys->info)(mount, unit, present);
else fprintf(stderr, "info: Does not expect a file name\n");
@@ -1060,7 +1116,7 @@ static void doDir(void)
char *fname;
uint8_t unit, present;
if ((mount = findMount("dir", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
(*mount->filesys->dir)(mount, unit, fname);
return;
}
@@ -1091,7 +1147,7 @@ static void doDump(void)
void *file;
uint8_t unit, present;
if ((mount = findMount("dump", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if ((file = (*mount->filesys->openFileR)(mount, unit, fname)) != NULL) {
unsigned int offset = 0, datasz = 2;
uint8_t data1;
@@ -1210,8 +1266,8 @@ static void doCopy(void)
void *fileSrc, *fileDest;
char *endptr;
mountSrc = findMount("copy", words[0], &unitSrc, &presentSrc, &fnameSrc);
mountDest = findMount("copy", words[1], &unitDest, &presentDest, &fnameDest);
mountSrc = findMount(words[0], &unitSrc, &presentSrc, &fnameSrc);
mountDest = findMount(words[1], &unitDest, &presentDest, &fnameDest);
if ((mountSrc != NULL) && (mountDest != NULL)) {
fsSrc = mountSrc->filesys;
@@ -1300,7 +1356,7 @@ static void doType(void)
*/
SWSET('a');
if ((mount = findMount("type", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if ((file = (*mount->filesys->openFileR)(mount, unit, fname)) != NULL) {
char buf[BFRSIZ];
size_t len, i;
@@ -1344,7 +1400,7 @@ static void doDelete(void)
void *file;
uint8_t unit, present;
if ((mount = findMount("delete", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if (mount->filesys->deleteFile != NULL) {
if ((mount->flags & FS_READONLY) == 0) {
if ((file = (*mount->filesys->openFileR)(mount, unit, fname)) != NULL)
@@ -1479,6 +1535,9 @@ static void doHelp(void)
"Create a new container file with an empty file system. The \"-t type\"\n"
"switch may be used to control the size of the container file, this\n"
"switch is file-system dependent.\n\n"
" mkdir [-p] dev:dirspec\n\n"
"Create a new empty directory on a mounted file system. The \"-p\"\n"
"switch may be used to create any missing intermediate directories.\n\n"
" set dev: args ...\n\n"
"Set parameter(s) on a mounted file system.\n\n"
" info dev:\n\n"
@@ -1597,7 +1656,7 @@ static void doRewind(void)
char *fname;
uint8_t unit, present;
if ((mount = findMount("rewind", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if ((mount->filesys->flags & FS_TAPE) == 0) {
fprintf(stderr, "rewind: Command only valid on magtapes\n");
return;
@@ -1633,7 +1692,7 @@ static void doEOM(void)
char *fname;
uint8_t unit, present;
if ((mount = findMount("eom", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if ((mount->filesys->flags & FS_TAPE) == 0) {
fprintf(stderr, "eom: Command only valid on magtapes\n");
return;
@@ -1670,7 +1729,7 @@ static void doSkipForw(void)
char *fname;
uint8_t unit, present;
if ((mount = findMount("skipf", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if ((mount->filesys->flags & FS_TAPE) == 0) {
fprintf(stderr, "skipf: Command only valid on magtapes\n");
return;
@@ -1716,7 +1775,7 @@ static void doSkipRev(void)
char *fname;
uint8_t unit, present;
if ((mount = findMount("skipf", words[0], &unit, &present, &fname)) != NULL) {
if ((mount = findMount(words[0], &unit, &present, &fname)) != NULL) {
if ((mount->filesys->flags & FS_TAPE) == 0) {
fprintf(stderr, "skipr: Command only valid on magtapes\n");
return;
@@ -1869,6 +1928,7 @@ static void FSioExecute(
/*
* Execute the command.
*/
command = cmdTable[idx].name;
(*cmdTable[idx].func)();
} else fprintf(stderr, "Unknown command \"%s\"\n", words[0]);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 John Forecast. All Rights Reserved.
* Copyright (C) 2018 - 2025 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:
@@ -35,12 +35,13 @@
/*
* Mode for open files
*/
enum openMode { M_RD, M_WR };
enum openMode { M_RD, M_WR, M_UNKNOWN };
#include "dos11.h"
#include "rt11.h"
#include "dosmt.h"
#include "os8.h"
#include "unixv7.h"
/*
* All of the supported file systems are natively little endian so we only
@@ -81,7 +82,7 @@ enum openMode { M_RD, M_WR };
#endif
extern uint32_t swPresent;
extern char *swValue[];
extern char *command, *swValue[];
#define SWISSET(c) ((swPresent & (1 << (c - 'a'))) != 0)
#define SWSET(c) swPresent |= (1 << (c - 'a'))
@@ -114,6 +115,7 @@ struct FSdef {
void (*umount)(struct mountedFS *);
size_t (*size)(void);
int (*newfs)(struct mountedFS *, size_t);
int (*mkdir)(struct mountedFS *, uint8_t, char *);
void (*set)(struct mountedFS *, uint8_t, uint8_t);
void (*info)(struct mountedFS *, uint8_t, uint8_t);
void (*dir)(struct mountedFS *, uint8_t, char *);
@@ -157,11 +159,13 @@ struct mountedFS {
struct RT11data _rt11;
struct DOSMTdata _dosmt;
struct OS8data _os8;
struct UNIXV7data _unixv7;
} FSdata;
#define dos11data FSdata._dos11
#define rt11data FSdata._rt11
#define dosmtdata FSdata._dosmt
#define os8data FSdata._os8
#define unixv7data FSdata._unixv7
};
extern int FSioReadBlob(struct mountedFS *, off_t, unsigned int, void *);

View File

@@ -26,6 +26,8 @@ umount - removes knowledge of a container file from fsio
newfs - create a new container with an empty file system
mkdir - create a new directory
set - set file system parameters
info - display information about the file system
@@ -87,19 +89,27 @@ Full command syntax:
1. mount
mount [-dfr] [-t type] dev[:] container type
mount [-dfr] [-o nnn] [-t type] dev[:] container type
Make the specified container file available to fsio for I/O.
-d Generate debug output if fsio is built with the DEBUG symbol
defined
-f Force the mount to happen even if we are unable to completely
validate the container file format
-r If present, the file system is only available for read access
-o nnn This is only valid for Unix V7 file systems for specifying
the starting offset of a partition within the container
file.
-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".
"rx02" or "rk05". It is not required for Unix V7 file systems
but, if supplied, allows for an additional integrity check
before mounting the file system.
dev[:] User supplied name to be used for accessing files within the
container file. Files within the container are named by using
@@ -126,7 +136,7 @@ Full command syntax:
3. newfs
newfs [-t type] container type
newfs [-b size] [-t type] container type
Create a new container file with an empty file system. The container
will be a fixed size (depending on file system type) and may not exist
@@ -137,7 +147,10 @@ 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
os8 RK05 image (2.5MB, 3248 blocks)
unixv7 RK05 image (2.5MB, 4872 blocks)
-b size Specify # of blocks for the container (only valid for unixv7)
-t type Use a different size for the container file. The size used
will be file system dependent.
@@ -153,11 +166,30 @@ Full command syntax:
rx01 RX01 image (2002 sectors of 128 bytes each)
rx02 RX02 imgae (2002 sectors of 256 bytes each)
For unixv7, the following disk types are valid:
rk05 RK05 image (4871 blocks)
rl01 RL01 image (5MB, 10240 blocks)
rl02 RL02 image (10MB, 20480 blocks)
rk06 RK06 image (13MB, 27126 blocks)
rk07 RK07 image (26MB, 53790 blocks)
container The name of the file to create
type The type of the file system to create in the container
4. set
4. mkdir
mkdir [-p] dev:dirspec
Creates a new empty directory on a mounted file system.
-p If present, create any missing intermediate directories.
dev: The name of a previosly mounted file system
dirspec Specification of the directory to create using the dev: syntax.
5. set
set dev: args ...
@@ -166,7 +198,7 @@ Full command syntax:
dev: The name of a previously mounted file system
5. info
6. info
info dev:
@@ -175,7 +207,7 @@ Full command syntax:
dev: The name of a previously mounted file system
6. dir
7. dir
dir [-fn] dev:dirspec
@@ -188,7 +220,7 @@ Full command syntax:
dev: The name of a previosly mounted file system
dirspec Specification of the directory to list using the dev: syntax.
7. dump
8. dump
dump [-bcdnwx] dev:src
@@ -209,7 +241,7 @@ Full command syntax:
dev: The name of a previosly mounted file system
src The name of the source file (e.g. dp:input.dat)
8. copy
9. copy
copy [-anpc blocks] dev1:src dev2:dest
@@ -244,7 +276,7 @@ Full command syntax:
Note that wildcard naming is not supported and the source and destination
file names must be fully specified.
9. type
10. type
type [-n] dev:src
@@ -257,7 +289,7 @@ Full command syntax:
dev: The name of a previously mounted file system
src The name of the source file (e.g. dp:input.txt)
10. delete
11. delete
delete dev:file
@@ -266,13 +298,13 @@ Full command syntax:
dev: The name of a previously mounted file system
file The name of the file to be deleted
11. status
12. status
status
Displays the currently mounted file systems.
12. do
13. do
do [-q] cmdFile
@@ -280,19 +312,19 @@ Full command syntax:
-q By default, command lines are echoed. Use -q to not echo.
13. help
14. help
help
Display help text on the terminal.
14. exit
15. exit
exit
Terminates the fsio application.
15. rewind
16. rewind
rewind dev:
@@ -300,7 +332,7 @@ Full command syntax:
dev: The name of a previously mounted file system
16. eom
17. eom
eom dev:
@@ -309,7 +341,7 @@ Full command syntax:
dev: The name of a previously mounted file system
17. skipf
18. skipf
skipf dev: n
@@ -320,7 +352,7 @@ Full command syntax:
dev: The name of a previously mounted file system
n Number of files to skip (must be > 0)
18. skipr
19. skipr
skipr dev: n

View File

@@ -83,6 +83,36 @@ pair <cr><lf> which RT-11 requires. In addition, unless the file ends
exactly on a block (512 bytes) boundary, a ^Z (octal 32) will be appended
to the file indicating end-of-file.
Research Unix V7
----------------
For Unix V7, fsio understands the native disk format so we can transfer
directly into the bootable SIMH disk ("unix_v7_rl.dsk" in the examples). Note
that Unix disks may contain multiple partitions but the partition layout was
not typically recorded on the disk, it was hard coded into the device driver.
fsio does support the "-o nnn" switch to mount to specify the block offset of
the partition to be mounted if it is not the first on the disk. The example
below will copy an ASCII file into the root directory of the partition (if
fsio is running on a Unix-like system, the "-a" switch is not needed):
pi@host:~ $ fsio
fsio> mount dl unix_v7_rl.dsk unixv7
Pack name: , File system name: , Total blocks: 18000
fsio> copy -a file.txt dl:file.txt
fsio> quit
pi@host:~ $
By default, new files will be created with UID 0, GID 0. To override this use:
fsio> set dl: uid 1
fsio> set dl: gid 100
fsio> copy -a file.txt dl:file.txt
Research Unix V7 was distributed by DEC as v7m and later as Ultrix-11.
Ultrix-11 V3.0/V3.1 used a modified disk layout with a 1K byte block size
which is incompatible with fsio but it did come with /etc/rawfs which allows
access to disks using a 512 byte block size.
Foreign File System Support
---------------------------

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 John Forecast. All Rights Reserved.
* Copyright (C) 2018 - 2025 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:
@@ -356,6 +356,7 @@ struct FSdef localFS = {
NULL,
NULL,
NULL,
NULL,
localInfo,
localDir,
localOpenFileR,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 John Forecast. All Rights Reserved.
* Copyright (C) 2019 - 2025 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:
@@ -2384,7 +2384,7 @@ static void os8Umount(
*
* Returns:
*
* Size of the container file in block of default file system size
* Size of the container file in blocks of default file system size
*
--*/
static size_t os8Size(void)
@@ -2410,7 +2410,7 @@ static size_t os8Size(void)
* Inputs:
*
* mount - pointer to a mounted file system descriptor
* (nit in the mounted file system list)
* (not in the mounted file system list)
* size - the sized (in blocks) of the filesystem
*
* Outputs:
@@ -2440,7 +2440,8 @@ static int os8Newfs(
dev++;
}
dev = OS8Devices;
fprintf(stderr, "newfs: Unknown device type \"%s\"\n", SWGETVAL('t'));
return 0;
}
found:
mount->skip = dev->skip;
@@ -2862,8 +2863,6 @@ static void os8DeleteFile(
data->buf[file->offset + OS8_DI_FNAME1] = 0;
data->buf[file->offset + OS8_ED_LENGTH] =
data->buf[file->offset + file->extra + OS8_DI_LENGTH];
data->buf[OS8_DH_ENTRIES] =
htole16(os8Value(-(os8Neg(le16toh(data->buf[OS8_DH_ENTRIES])) - 1)));
os8SlideUp(mount, file->offset + OS8_ED_SIZE,
file->offset + file->entrysz, file->entrysz, file->remain);
@@ -2905,6 +2904,12 @@ static void os8CloseFile(
struct os8OpenFile *file = filep;
if (file->mode == M_WR) {
if (SWISSET('a')) {
char ch ='\032';
os8WriteBytes(file, &ch, 1);
}
if (file->current != 0)
/*
* Flush the current buffer.
@@ -2946,7 +2951,41 @@ static size_t os8ReadFile(
)
{
struct os8OpenFile *file = filep;
char *bufr = buf;
if (SWISSET('a')) {
char ch;
size_t count = 0;
if (file->eof != 0)
return 0;
/*
* Read a full or partial line from the open file.
*/
while ((buflen != 0) && (os8ReadBytes(file, &ch, 1) == 1)) {
if (ch == '\032') {
/*
* ^Z indicating EOF
*/
file->eof = 1;
break;
}
/*
* Ignore NULL bytes in ASCII mode
*/
if (ch != '\0') {
ch &= 0177;
bufr[count++] = ch;
buflen--;
if (ch == '\n')
break;
}
}
return count;
}
return os8ReadBytes(file, buf, buflen);
}
@@ -2997,6 +3036,7 @@ struct FSdef os8FS = {
os8Umount,
os8Size,
os8Newfs,
NULL,
os8Set,
os8Info,
os8Dir,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 John Forecast. All Rights Reserved.
* Copyright (C) 2019 - 2025 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:
@@ -217,6 +217,7 @@ struct os8OpenFile {
uint16_t wordpos; /* Current word offset */
uint8_t bytepos; /* Current byte position */
off_t written; /* # of bytes written to the file */
uint8_t eof; /* EOF seen on last read */
};
/*

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 John Forecast. All Rights Reserved.
* Copyright (C) 2018 - 2025 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:
@@ -1565,7 +1565,7 @@ static int validate(
position += le16toh(data->buf[off + RT11_DI_LENGTH]);
if ((status & RT11_E_MPTY) != 0)
if ((status & RT11_E_EOS) != 0)
break;
/*
@@ -1656,8 +1656,8 @@ int rt11ReadBytes(
* Inputs:
*
* file - pointer to an open file descriptor
* buf - pointer to a buffer to receive the data
* len - # of bytes of data to read
* buf - pointer to a buffer with the data to be written
* len - # of bytes of data to write
*
* Outputs:
*
@@ -1881,9 +1881,15 @@ static int rt11Mount(
}
printf("%s%o:\n", mount->name, i);
if (version != NULL)
printf(" Version: %s, System ID: %12s\n",
version, (char *)&data->buf[RT11_HB_SYSID]);
if (version != NULL) {
char sysid[16];
memset(sysid, 0, sizeof(sysid));
strncpy(sysid, (char *)&data->buf[RT11_HB_SYSID],
strlen(RT11_SYSID));
printf(" Version: %s, System ID: %s\n", version, sysid);
}
printf(" Total blocks: %5d, Free blocks: %5d\n"
" Directory segments: %2d (Highest in use: %d)\n"
" Extra bytes/directory entry: %d\n",
@@ -1958,7 +1964,8 @@ static size_t rt11Size(void)
}
if (size == ((RT11_MAXPARTSZ - 1) * RT11_BLOCKSIZE))
fprintf(stderr,
"newfs: Invalid device type \"%s\", using default\n", type);
"%s: Invalid device type \"%s\", using default\n",
command, type);
}
return size;
}
@@ -2027,7 +2034,6 @@ static int rt11Newfs(
* Remove possible first track
*/
size = (size - mount->skip) / RT11_BLOCKSIZE;
// size = ((size * RT11_BLOCKSIZE) - mount->skip) / RT11_BLOCKSIZE;
/*
* Mark partition 0 as valid
@@ -2570,6 +2576,7 @@ struct FSdef rt11FS = {
rt11Size,
rt11Newfs,
NULL,
NULL,
rt11Info,
rt11Dir,
rt11OpenFileR,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 John Forecast. All Rights Reserved.
* Copyright (C) 2018 - 2025 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:
@@ -568,7 +568,7 @@ int tapeWriteEOM(
*
* Returns:
*
* 1 if EOM record successfully written, 0 otherwise
* 1 if TM record successfully written, 0 otherwise
*
--*/
int tapeWriteTM(

3080
converters/fsio/unixv7.c Normal file

File diff suppressed because it is too large Load Diff

258
converters/fsio/unixv7.h Normal file
View File

@@ -0,0 +1,258 @@
/*
Copyright (c) 2025, John Forecast
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
JOHN FORECAST BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of John Forecast shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from John Forecast.
*/
#ifndef __UNIXV7_H__
#define __UNIXV7_H__
/*
* General disk layout:
*
* Block
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* 0 | Reserved |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* 1 | Super Block |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* 2 | I nodes |
* | ... |
* | ... |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | Data Blocks |
* | ... |
* | ... |
* | ... |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* End of Volume
*/
/*
* Common data types
*/
typedef int16_t v7_short;
typedef uint16_t v7_ushort;
typedef int16_t v7_int;
typedef uint16_t v7_uint;
typedef int32_t v7_long;
typedef uint32_t v7_ulong;
typedef int32_t v7_daddr_t;
typedef uint16_t v7_ino_t;
typedef int32_t v7_time_t;
typedef int32_t v7_off_t;
/*
* 32-bit longword values are stored with the high 16-bit word first
*/
#define V7_LONG(v) \
((v7_long)((((v) & 0xFFFF) << 16) | (((v) & 0xFFFF0000) >> 16)))
#define V7_ULONG(v) \
((v7_ulong)((((v) & 0xFFFF) << 16) | (((v) & 0xFFFF0000) >> 16)))
#define V7_BLOCKSIZE 512
#define V7_BSHIFT 9 /* Log2(V7_BLOCKSIZE) */
#define V7_BMASK 0777 /* V7_BLOCKSIZE - 1 */
#define V7_NINDIR ((int)(V7_BLOCKSIZE / sizeof(v7_daddr_t)))
#define V7_NSHIFT 7 /* Log2(NINDIR) */
#define V7_NMASK 0177 /* NINDIR - 1 */
#define V7_ROOTINO ((v7_ino_t)2) /* i number of all roots */
#define V7_SUPERBLK 1 /* Super block address */
#define V7_DIRSIZ 14 /* Max characters per directory */
#define V7_NICFREE 50 /* Number of superblock free blocks */
#define V7_NICINOD 100 /* Number of superblock inodes */
#define V7_STEPSIZE 9 /* Default step for freelist spacing */
#define V7_CYLSIZE 400 /* Default cylinder size for spacing */
/*
* Super-block
*/
#pragma pack(push, 1)
struct v7_filsys {
v7_ushort s_isize; /* Size in blocks of i-list */
v7_daddr_t s_fsize; /* Size in blocks of entire volume */
v7_short s_nfree; /* Number of addresses in s_free */
v7_daddr_t s_free[V7_NICFREE];/* Free block list */
v7_short s_ninode; /* Number of i-nodes in s_free */
v7_ino_t s_inode[V7_NICINOD];/* Free i-node list */
char s_flock; /* Lock during free list manip. */
char s_ilock; /* Lock during i-list manip. */
char s_fmod; /* Super-block modified flag */
char s_ronly; /* Mounted read-only flag */
v7_time_t s_time; /* Last super-block update */
/*
* Remainder not maintained by this version of the system
*/
v7_daddr_t s_tfree; /* Total free blocks */
v7_ino_t s_tinode; /* Total free inodes */
v7_short s_m; /* Interleave factor */
v7_short s_n; /* " " */
char s_fname[6]; /* File system name */
char s_fpack[6]; /* File system pack name */
};
/*
* On-disk free space list at the head of each free block.
*/
struct v7_fblk {
v7_int df_nfree; /* Number of addresses in df_free */
v7_daddr_t df_free[V7_NICFREE];
};
/*
* On-disk inode structure
*/
struct v7_dinode {
v7_ushort di_mode; /* Mode and type of file */
v7_short di_nlink; /* Number of links to file */
v7_short di_uid; /* Owner's user ID */
v7_short di_gid; /* Owner's group ID */
v7_off_t di_size; /* Number of bytes in file */
char di_addr[40]; /* Disk block addresses */
v7_time_t di_atime; /* Time last accessed */
v7_time_t di_mtime; /* Time last modified */
v7_time_t di_ctime; /* Time created */
};
#define V7_INOPB 8 /* 8 inodes per block */
#define itod(x) ((v7_daddr_t)((x + 15) >> 3))
#define itoo(x) ((v7_uint)((x + 15) & 07))
#define itoff(x) ((v7_uint)(x + 15))
/*
* The 40 address bytes:
*
* 39 used; 13 addresses of 3 bytes each
*/
#define NADDR 13
/*
* Mode bits
*/
#define V7_IFMT 0170000 /* Type of file */
#define V7_IFCHR 0020000 /* Character special */
#define V7_IFBLK 0060000 /* Block special */
#define V7_IFMPC 0030000 /* Multiplex character special */
#define V7_IFMPB 0070000 /* Multiplex block special */
#define V7_IFDIR 0040000 /* Directory */
#define V7_IFLNK 0120000 /* Symbolic link */
#define V7_IFREG 0100000 /* Regular */
#define V7_ISUID 0004000 /* Set user ID on execution */
#define V7_ISGID 0002000 /* Set group ID on execution */
#define V7_ISVTX 0001000 /* Save swapped text even after use */
#define V7_IREAD 0000400 /* Read permission, owner */
#define V7_IWRITE 0000200 /* Write permission, owner */
#define V7_IEXEC 0000100 /* Execute/Search permission, owner */
struct v7_direct {
v7_ino_t d_ino; /* Inode number */
char d_name[V7_DIRSIZ]; /* File name */
};
#pragma pack(pop)
/*
* Disk block addresses are stored on disk in 2 formats:
*
* 1 - In the inode addr array, 3 bytes each which limits disk size to 16GB
* 2 - In the free block list, 4 byte v7_long values
*/
#define V7_GET3ADDR(p, v) \
{ uint8_t *tmp = (uint8_t *)p; \
v = *tmp++ << 16; v |= *tmp++; v |= *tmp++ << 8; \
}
#define V7_PUT3ADDR(p, v) \
{ uint8_t *tmp = (uint8_t *)p; \
*tmp++ = (v >> 16) & 0xFF; *tmp++ = v & 0xFF; *tmp++ = (v >> 8) & 0xFF; \
}
#define V7_GET4ADDR(p, v) \
{ uint16_t *tmp = (uint16_t *)p; \
v = le16toh(*tmp++) << 16; v |= le16toh(*tmp); \
}
#define V7_PUT4ADDR(p, v) \
{ uint16_t *tmp = (uint16_t *)p; \
*tmp++ = htole16(v) >> 16; *tmp = htole16(v & 0xFFFF); \
}
#define V7_READ 0 /* Read operation */
#define V7_WRITE 1 /* Write operation */
/*
* Structure to describe a file/directory name. * and % may be used as wild
* card characters within each component of a name.
*/
#define UNIXV7_COMP 100 /* Maximum name depth */
struct unixv7FileSpec {
int depth; /* Actual depth of this name */
char wildcard; /* Wildcard options */
char access; /* Access mode (existing/new file) */
char *comp[UNIXV7_COMP];
};
#define UNIXV7_M_NONE 0000 /* Wild cards not allowed */
#define UNIXV7_M_ALLOW 0001 /* Wild cards allowed */
#define UNIXV7_A_EXIST 0000 /* Access an existing file */
#define UNIXV7_A_NEW 0001 /* Create a new file */
/*
* Device descriptor
*/
struct UNIXV7device {
char *name; /* Device name */
size_t diskSize; /* # of blocks on device */
};
/*
* Structure to define an open file.
*/
struct unixv7OpenFile {
char name[V7_DIRSIZ + 1]; /* file name */
v7_ino_t parent; /* inode number of parent directory */
v7_ino_t ino; /* inode number of file */
struct v7_dinode inode; /* on-disk inode copy */
enum openMode mode; /* Open mode (read/write) */
struct mountedFS *mount; /* Mounted file system descriptor */
off_t offset; /* Current read/write point */
uint32_t block; /* Current block in buffer */
char *buffer; /* Private buffer for file I/O */
};
/*
* Unix V7 specific data area.
*/
struct UNIXV7data {
unsigned int blocks; /* # of blocks in the file system */
unsigned int offset; /* Block offset to partition start */
uint16_t user; /* Default user ID */
uint16_t group; /* Default group ID */
union {
struct v7_filsys sb;
uint8_t super;
} superblk; /* Holds super block */
uint8_t buf[512]; /* Disk buffer */
uint8_t zero[512]; /* Always contains 0's */
};
#endif