Files
open-simh.simtools/extracters/rstsflx/diskio.c
Paul Koning bf7c17ab4a Add RSTSFLX V2.6. This is a file system access utility for RSTS
file systems.  It supports reading and writing as well as a number
of other operations, such as octal dump, file system initialize,
and file system check ("clean").

This was originally maintained as a Subversion repository at
svn://akdesign.dyndns.org/flx/branches/V2.6.
as suggested by Timothe Litt on the SIMH mailing list.
2016-04-27 15:00:42 -04:00

263 lines
6.9 KiB
C

/* subroutines to do rsts disk (logical block) I/O */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "flx.h"
#include "diskio.h"
#include "absio.h"
#define DEFDEVICE "rsts.dsk"
#define NOLAST 0
#define LASTREAD 1
#define LASTWRITE 2
#ifndef S_ISCHR
#define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR)
#endif
typedef struct {
const char *name; /* Name of the disk */
long tsize; /* Total container size */
long rsize; /* Size RSTS uses */
int dec166; /* TRUE if disk has factor bad block table */
} diskent;
int dcs; /* device clustersize */
long diskblocks; /* device block count */
const char *rname; /* file name of disk/container */
const char *rssize; /* and associated size */
long rsize; /* explicitly supplied size (for real disks) */
int absflag; /* doing absolute I/O to real disk if non-zero */
FILE *rstsfile; /* rsts disk or container file */
int lastio; /* what type of I/O, if any, was last done */
long nextblk; /* next block after end of last I/O */
const diskent sizetbl[] = {
{ "rx50", 800, 800, FALSE },
{ "rf11", 1024, 1024, FALSE },
{ "rs03", 1024, 1024, FALSE },
{ "rs04", 2048, 2048, FALSE },
{ "rk05", 4800, 4800, FALSE },
{ "rl01", 10240, 10220, TRUE },
{ "rl02", 20480, 20460, TRUE },
{ "rk06", 27126, 27104, TRUE },
{ "rk07", 53790, 53768, TRUE },
{ "rp04", 171798, 171796, FALSE },
{ "rp05", 171798, 171796, FALSE },
{ "rp06", 340670, 340664, FALSE },
{ "rp07", 1008000, 1007950, TRUE },
{ "rm02", 131680, 131648, TRUE },
{ "rm03", 131680, 131648, TRUE },
{ "rm05", 500384, 500352, TRUE },
{ "rm80", 251328, 242575, TRUE },
{ NULL, 0, 0, 0 }};
/* getsize takes as input a container file size specifier, which is either
* a decimal string or a disk type name, and returns the corresponding
* size. In the case of disk names, it returns both the size as RSTS
* knows it, and the full hardware-defined size. In addition, it returns
* a flag indicating whether that type has a bad block table.
* In the case of a numeric size, it looks for a match in the table
* (against either RSTS size or "full" size) and returns what the
* table entry specifies. If no match is found, it returns the
* specified value for both and the dec166 flag is false.
* If the size specifier is invalid, the RSTS size is returned as zero
* and the other two return values are undefined.
*/
void getsize (const char *name, long *tsize, long *rsize, int *dec166)
{
const diskent *d;
char *n, *n2, *pp;
if (isdigit (*name)) /* numeric size given */
{
*rsize = strtoul (name, &pp, 10); /* scan size */
if (*pp != '\0') *rsize = 0;
*tsize = *rsize;
*dec166 = FALSE;
for (d = sizetbl; d->name != NULL; d++)
if (d->rsize == *rsize || d->tsize == *rsize)
{
*tsize = d->tsize;
*rsize = d->rsize;
*dec166 = d->dec166;
break;
}
}
else
{
if ((n = (char *) malloc (strlen (name) + 1)) == NULL) rabort(NOMEM);
strcpy (n, name);
for (n2 = n; *n2; n2++) *n2 = tolower (*n2);
for (d = sizetbl; d->name != NULL; d++)
if (strcmp (d->name, n) == 0) break;
free (n);
*tsize = d->tsize;
*rsize = d->rsize;
*dec166 = d->dec166;
}
}
/* adjsize takes as input a container file size. it returns the
* corresponding RSTS size, based on a match against a table of
* known disk sizes. if it finds a match, it returns the RSTS
* size given in the table; otherwise it returns the value that
* was passed.
*/
long adjsize (long tsize)
{
const diskent *d;
for (d = sizetbl; d->name != NULL; d++)
if (d->tsize == tsize)
return d->rsize;
return tsize;
}
void setrname ()
{
long t1;
int t2;
if ((rname = sw.rstsdevice) == NULL)
if ((rname = defdevice) == NULL)
if ((rname = getenv ("RSTSDISK")) == NULL)
rname = DEFDEVICE;
if ((rssize = sw.disksize) == NULL)
if ((rssize = defsize) == NULL)
if ((rssize = getenv ("RSTSDISKSIZE")) == NULL)
rssize = NULL;
rsize = 0;
absflag = FALSE;
if (rssize != NULL) {
getsize (rssize, &t1, &rsize, &t2); /* scan size */
if (rsize == 0) {
printf ("Invalid device size %s\n", rssize);
return; /* and quit */
}
}
absname (rname); /* see if name is special */
if (absflag && rsize == 0) {
printf ("Disk size must be specified explicitly for disk %s\n",
rname);
return;
}
}
void ropen (const char *mode)
{
long d;
struct stat sbuf;
fiblk = -1; /* indicate no valid FIBUF */
lastio = NOLAST; /* and no previous I/O */
womsat = FALSE; /* SATT is clean */
setrname ();
if (absflag) { /* open real disk */
if (absopen (rname, mode)) {
printf ("Error opening RSTS device %s\n", rname);
perror (progname); /* report any details */
rabort (NOMSG);
}
diskblocks = rsize; /* set block count */
} else { /* not absolute disk */
if ((rstsfile = fopen (rname, mode)) == NULL) {
printf ("Error opening RSTS device %s\n", rname);
perror (progname); /* report any details */
rabort (NOMSG);
}
if (fstat (fileno(rstsfile), &sbuf)) { /* get info about disk/file */
printf ("Can't stat RSTS device %s", rname);
perror (progname);
fclose (rstsfile); /* close it */
rabort (NOMSG);
}
diskblocks = UP(sbuf.st_size,BLKSIZE) / BLKSIZE;
if (diskblocks == 0) {
if (!S_ISCHR(sbuf.st_mode) &&
!S_ISBLK(sbuf.st_mode))
{
printf ("Null RSTS container file %s\n", rname);
fclose (rstsfile);
rabort (NOMSG);
}
if (rsize == 0) {
printf ("Size not specified for RSTS disk %s\n", rname);
fclose (rstsfile);
rabort (NOMSG);
}
diskblocks = rsize;
}
}
diskblocks = adjsize (diskblocks); /* adjust for bad block tbl */
d = (diskblocks - 1) >> 16; /* high order bits of last LBN */
dcs = 1; /* compute DCS */
while (d) {
d >>= 1;
dcs <<= 1;
}
if (dcs > 64) rabort(BADDCS); /* Sorry, disk too big! */
}
void rseek (long block)
{
if (block >= diskblocks) rabort(BADBLK);
if (absflag) absseek (block);
else fseek (rstsfile, block * BLKSIZE, SEEK_SET);
if (sw.debug != NULL)
printf ("seek to: %ld\n", block);
}
void rread (long block, long size, void *buffer)
{
long iosize;
if (lastio != LASTREAD || nextblk != block) {
rseek (block);
lastio = LASTREAD;
}
if (absflag) {
if (absread (block, size, buffer))
iosize = 0;
else iosize = size;
}
else iosize = fread (buffer, 1, size, rstsfile);
if (sw.debug != NULL)
printf ("size requested: %ld, read: %ld\n", size, iosize);
if (iosize != size) rabort(DISKIO);
nextblk = block + size / BLKSIZE;
}
void rwrite (long block, long size, void *buffer)
{
long iosize;
if (lastio != LASTWRITE || nextblk != block) {
rseek (block);
lastio = LASTWRITE;
}
if (absflag) {
if (abswrite (block, size, buffer))
iosize = 0;
else iosize = size;
}
else iosize = fwrite (buffer, 1, size, rstsfile);
if (iosize != size) rabort(DISKIO);
nextblk = block + size / BLKSIZE;
}
void rclose ()
{
if (absflag) absclose ();
else fclose (rstsfile);
}