mirror of
https://github.com/open-simh/simtools.git
synced 2026-01-18 17:08:20 +00:00
Dismount command lost drive parameter in previous commit. Under windows, limit confusion by assigning pseudo-drive letters for images more carefully. Avoid letters used by Windows. Dir /detail wasn't reporting rab$b_fsz correctly. qualifier list keyword syntax error now reported correctly. Include Windows release .exes in git. Improve conditional compilation in compat.
256 lines
6.7 KiB
C
256 lines
6.7 KiB
C
/* diskio.c - ANSI C Disk I/O - for .ISO and simulator disks */
|
|
|
|
/* Timothe Litt Feb 2016
|
|
*
|
|
* This is part of ODS2 written by Paul Nankervis,
|
|
* email address: Paulnank@au1.ibm.com
|
|
*
|
|
* ODS2 is distributed freely for all members of the
|
|
* VMS community to use. However all derived works
|
|
* must maintain comments in their source to acknowledge
|
|
* the contibution of the original author.
|
|
*/
|
|
|
|
#ifndef _FILE_OFFSET_BITS
|
|
#define _FILE_OFFSET_BITS 64
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <string.h>
|
|
|
|
#if __FILE_OFFSET_BITS == 64
|
|
# undef fseek
|
|
# ifdef _WIN32
|
|
# define fseek _fseeki64
|
|
# undef off_t
|
|
# define off_t __int64
|
|
# else
|
|
# define fseek fseeko
|
|
# endif
|
|
#endif
|
|
|
|
#include "compat.h"
|
|
#include "phyio.h"
|
|
#include "ssdef.h"
|
|
|
|
unsigned init_count = 0;
|
|
unsigned read_count = 0;
|
|
unsigned write_count = 0;
|
|
|
|
#define MAX_DEVS 64
|
|
FILE *handles[1+MAX_DEVS];
|
|
|
|
void phyio_show(void)
|
|
{
|
|
printf("PHYIO_SHOW Initializations: %d Reads: %d Writes: %d\n",
|
|
init_count,read_count,write_count);
|
|
}
|
|
|
|
void phyio_help(FILE *fp ) {
|
|
fprintf( fp, "Specify the file containing a disk image to be mounted.\n" );
|
|
fprintf( fp, "E.g. mount mydisk.iso\n" );
|
|
fprintf( fp, "A drive letter will be assigned to the image. Use that\n" );
|
|
fprintf( fp, "letter to refer to the VMS volume in subsequent commands\n" );
|
|
return;
|
|
}
|
|
|
|
static char *diskfiles[26];
|
|
static char drives[26][4];
|
|
|
|
/* Deeper code assumes that the device name is terminated by ':' and that this is
|
|
* the physical device. To keep it happy, map the next free drive letter to this
|
|
* filename, and use it to identify the device. phyio_init will check the mapping table
|
|
* to get the actual filename to open.
|
|
*
|
|
* To minimize confusion, under Windows, try to pick a pseudo-drive letter that
|
|
* isn't in use by windows. Avoid A & B unless all >= C are in use. If we can't
|
|
* find a non-conflicting letter, use the first letter not in use. Under any other
|
|
* OS, just use the first free letter.
|
|
*/
|
|
|
|
char *diskio_mapfile( const char *filename, int options ) {
|
|
int l, L = -1;
|
|
#ifdef _WIN32
|
|
int ff = -1, ffa = -1;
|
|
#endif
|
|
|
|
for( l = 0; l < 26; l++ ) {
|
|
if( diskfiles[l] == NULL && L < 0) {
|
|
#ifdef _WIN32
|
|
char dl[3] = { 'A', ':', '\0' };
|
|
dl[0] += l;
|
|
if( ff < 0 )
|
|
ff = l;
|
|
if( driveFromLetter( dl ) == NULL) {
|
|
if( dl[0] >= 'C' ) {
|
|
if( L < 0 )
|
|
L = l;
|
|
} else {
|
|
if( ffa < 0 )
|
|
ffa = l;
|
|
}
|
|
}
|
|
#else
|
|
L = l;
|
|
#endif
|
|
}
|
|
if( diskfiles[l] && strcmp( diskfiles[l], filename ) == 0 ) {
|
|
printf( "%s is already mounted as drive %s\n", filename, drives[l] );
|
|
return NULL;
|
|
}
|
|
}
|
|
#ifdef _WIN32
|
|
if( L < 0 ) {
|
|
if( ffa >= 0 )
|
|
L = ffa;
|
|
else {
|
|
if( ff >= 0 )
|
|
L = ff;
|
|
}
|
|
}
|
|
#endif
|
|
if( L < 0 ) {
|
|
printf( "No free drive letters for %s\n", filename );
|
|
return NULL;
|
|
}
|
|
snprintf(drives[L], 3, "%c:", L + 'A');
|
|
drives[L][3] = options;
|
|
free(diskfiles[L]);
|
|
diskfiles[L] = (char *) malloc( (l = strlen(filename) + 1) );
|
|
snprintf( diskfiles[L], l, "%s", filename );
|
|
|
|
printf( "%s assigned to %s\n", drives[L], diskfiles[L] );
|
|
|
|
return drives[L];
|
|
}
|
|
|
|
int diskio_showdrives( void ) {
|
|
int n = 0;
|
|
int l;
|
|
size_t max;
|
|
int sts = 1;
|
|
|
|
max = sizeof( "Filename" ) -1;
|
|
|
|
for( l = 0; l < 26; l++ ) {
|
|
if( diskfiles[l] != NULL && strlen(diskfiles[l]) > max )
|
|
max = strlen(diskfiles[l]);
|
|
}
|
|
for( l = 0; l < 26; l++ ) {
|
|
if( diskfiles[l] == NULL )
|
|
continue;
|
|
|
|
if( !n++ ) {
|
|
printf( "Drv Sts Filename\n"
|
|
"--- --- " );
|
|
while( max-- ) fputc( '-', stdout );
|
|
printf( "\n" );
|
|
}
|
|
printf( " %s %-3s %s\n", drives[l], (drives[l][3] &1)? "RW": "RO", diskfiles[l] );
|
|
}
|
|
if( n == 0 ) {
|
|
printf( "No drives assigned\n" );
|
|
sts = 0;
|
|
}
|
|
return sts;
|
|
}
|
|
|
|
int diskio_unmapdrive( const char *drive ) {
|
|
if( diskfiles[drive[0]-'A'] == NULL ) {
|
|
return 0;
|
|
}
|
|
free(diskfiles[drive[0]-'A']);
|
|
diskfiles[drive[0]-'A'] = NULL;
|
|
return 1;
|
|
}
|
|
|
|
unsigned phyio_init( int devlen,char *devnam,unsigned *handle,struct phyio_info *info ) {
|
|
size_t hi;
|
|
int i;
|
|
|
|
UNUSED ( devlen );
|
|
|
|
info->status = 0;
|
|
info->sectors = 0;
|
|
info->sectorsize = 0;
|
|
*handle = ~0;
|
|
|
|
for( hi = 1; hi < MAX_DEVS && handles[hi] != NULL; hi++ )
|
|
;
|
|
|
|
if( hi >= MAX_DEVS ) {
|
|
return SS$_IVCHAN;
|
|
}
|
|
|
|
if( (devnam[0] < 'A' || devnam[0] > 'Z') || devnam[1] != ':' ) {
|
|
printf ( "%s is not a mapped device name\n", devnam );
|
|
return SS$_NOSUCHFILE;
|
|
}
|
|
|
|
i = *devnam - 'A';
|
|
if( diskfiles[i] == NULL ) {
|
|
printf ( "%s is not a mapped device name\n", devnam );
|
|
return SS$_NOSUCHFILE;
|
|
}
|
|
|
|
handles[hi] = openf ( diskfiles[i], (drives[i][3] & 1)? "rb+": "rb" );
|
|
if( handles[hi] == NULL ) {
|
|
perror( diskfiles[i] );
|
|
return SS$_NOSUCHFILE;
|
|
}
|
|
|
|
++init_count;
|
|
|
|
*handle = hi;
|
|
return SS$_NORMAL;
|
|
}
|
|
|
|
unsigned phyio_close(unsigned handle) {
|
|
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
|
|
return SS$_NOIOCHAN;
|
|
}
|
|
fclose ( handles[handle] );
|
|
handles[handle] = NULL;
|
|
|
|
return SS$_NORMAL;
|
|
}
|
|
|
|
unsigned phyio_read( unsigned handle,unsigned block,unsigned length,char *buffer ) {
|
|
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
|
|
return SS$_IVCHAN;
|
|
}
|
|
|
|
if( fseek( handles[handle], block * 512, SEEK_SET ) == -1 ) {
|
|
perror( "seek" );
|
|
return SS$_DATACHECK;
|
|
}
|
|
if( fread( buffer, 1, length, handles[handle] ) != length ) {
|
|
perror( "read" );
|
|
return SS$_DATACHECK;
|
|
}
|
|
|
|
++read_count;
|
|
return SS$_NORMAL;
|
|
}
|
|
|
|
unsigned phyio_write( unsigned handle,unsigned block,unsigned length,char *buffer ) {
|
|
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
|
|
return SS$_IVCHAN;
|
|
}
|
|
|
|
if( fseek( handles[handle], block * 512, SEEK_SET ) == -1 ) {
|
|
perror( "seek" );
|
|
return SS$_DATACHECK;
|
|
}
|
|
abort();
|
|
if( fwrite( buffer, 1, length, handles[handle] ) != length ) {
|
|
perror( "write" );
|
|
return SS$_DATACHECK;
|
|
}
|
|
++write_count;
|
|
return SS$_NORMAL;
|
|
}
|
|
|