DISK: Fix RAW device (CDROM) access behaviors
- Only open RAW CDROM devices in read only mode (UNIT_RO) to avoid potential write attempts. - Make sure to properly reopen RAW CDROM devices after media is inserted into the drive after an attach thas with no media present OR after an Eject. As discussed in #533
This commit is contained in:
parent
e3543cbbdd
commit
70d8f759c6
1 changed files with 67 additions and 22 deletions
77
sim_disk.c
77
sim_disk.c
|
@ -92,6 +92,8 @@ struct disk_context {
|
||||||
uint32 xfer_element_size; /* Disk Bus Transfer size (1 - byte, 2 - word, 4 - longword) */
|
uint32 xfer_element_size; /* Disk Bus Transfer size (1 - byte, 2 - word, 4 - longword) */
|
||||||
uint32 storage_sector_size;/* Sector size of the containing storage */
|
uint32 storage_sector_size;/* Sector size of the containing storage */
|
||||||
uint32 removable; /* Removable device flag */
|
uint32 removable; /* Removable device flag */
|
||||||
|
uint32 is_cdrom; /* Host system CDROM Device */
|
||||||
|
uint32 media_removed; /* Media not available flag */
|
||||||
uint32 auto_format; /* Format determined dynamically */
|
uint32 auto_format; /* Format determined dynamically */
|
||||||
#if defined _WIN32
|
#if defined _WIN32
|
||||||
HANDLE disk_handle; /* OS specific Raw device handle */
|
HANDLE disk_handle; /* OS specific Raw device handle */
|
||||||
|
@ -282,7 +284,7 @@ static t_stat sim_os_disk_unload_raw (FILE *f);
|
||||||
static t_bool sim_os_disk_isavailable_raw (FILE *f);
|
static t_bool sim_os_disk_isavailable_raw (FILE *f);
|
||||||
static t_stat sim_os_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
|
static t_stat sim_os_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
|
||||||
static t_stat sim_os_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects);
|
static t_stat sim_os_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectswritten, t_seccnt sects);
|
||||||
static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable);
|
static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable, uint32 *is_cdrom);
|
||||||
static char *HostPathToVhdPath (const char *szHostPath, char *szVhdPath, size_t VhdPathSize);
|
static char *HostPathToVhdPath (const char *szHostPath, char *szVhdPath, size_t VhdPathSize);
|
||||||
static char *VhdPathToHostPath (const char *szVhdPath, char *szHostPath, size_t HostPathSize);
|
static char *VhdPathToHostPath (const char *szVhdPath, char *szHostPath, size_t HostPathSize);
|
||||||
static t_offset get_filesystem_size (UNIT *uptr);
|
static t_offset get_filesystem_size (UNIT *uptr);
|
||||||
|
@ -383,6 +385,8 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_bool sim_disk_isavailable (UNIT *uptr)
|
t_bool sim_disk_isavailable (UNIT *uptr)
|
||||||
{
|
{
|
||||||
|
struct disk_context *ctx;
|
||||||
|
|
||||||
if (!(uptr->flags & UNIT_ATT)) /* attached? */
|
if (!(uptr->flags & UNIT_ATT)) /* attached? */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
switch (DK_GET_FMT (uptr)) { /* case on format */
|
||||||
|
@ -392,7 +396,28 @@ switch (DK_GET_FMT (uptr)) { /* case on format */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
break;
|
break;
|
||||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
||||||
return sim_os_disk_isavailable_raw (uptr->fileref);
|
ctx = (struct disk_context *)uptr->disk_ctx;
|
||||||
|
|
||||||
|
if (sim_os_disk_isavailable_raw (uptr->fileref)) {
|
||||||
|
if (ctx->media_removed) {
|
||||||
|
int32 saved_switches = sim_switches;
|
||||||
|
int32 saved_quiet = sim_quiet;
|
||||||
|
char *path = (char *)malloc (1 + strlen (uptr->filename));
|
||||||
|
|
||||||
|
sim_switches = 0;
|
||||||
|
sim_quiet = 1;
|
||||||
|
strcpy (path, uptr->filename);
|
||||||
|
sim_disk_attach (uptr, path, ctx->sector_size, ctx->xfer_element_size,
|
||||||
|
FALSE, ctx->dbit, NULL, 0, 0);
|
||||||
|
sim_quiet = saved_quiet;
|
||||||
|
sim_switches = saved_switches;
|
||||||
|
free (path);
|
||||||
|
ctx->media_removed = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ctx->media_removed = 1;
|
||||||
|
return !ctx->media_removed;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -797,11 +822,15 @@ return r;
|
||||||
|
|
||||||
t_stat sim_disk_unload (UNIT *uptr)
|
t_stat sim_disk_unload (UNIT *uptr)
|
||||||
{
|
{
|
||||||
|
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||||
|
|
||||||
switch (DK_GET_FMT (uptr)) { /* case on format */
|
switch (DK_GET_FMT (uptr)) { /* case on format */
|
||||||
case DKUF_F_STD: /* Simh */
|
case DKUF_F_STD: /* Simh */
|
||||||
case DKUF_F_VHD: /* VHD format */
|
case DKUF_F_VHD: /* VHD format */
|
||||||
|
ctx->media_removed = 1;
|
||||||
return sim_disk_detach (uptr);
|
return sim_disk_detach (uptr);
|
||||||
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
case DKUF_F_RAW: /* Raw Physical Disk Access */
|
||||||
|
ctx->media_removed = 1;
|
||||||
return sim_os_disk_unload_raw (uptr->fileref); /* remove/eject disk */
|
return sim_os_disk_unload_raw (uptr->fileref); /* remove/eject disk */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1302,7 +1331,7 @@ char tbuf[4*CBUFSIZE];
|
||||||
FILE *(*open_function)(const char *filename, const char *mode) = sim_fopen;
|
FILE *(*open_function)(const char *filename, const char *mode) = sim_fopen;
|
||||||
FILE *(*create_function)(const char *filename, t_offset desiredsize) = NULL;
|
FILE *(*create_function)(const char *filename, t_offset desiredsize) = NULL;
|
||||||
t_offset (*size_function)(FILE *file);
|
t_offset (*size_function)(FILE *file);
|
||||||
t_stat (*storage_function)(FILE *file, uint32 *sector_size, uint32 *removable) = NULL;
|
t_stat (*storage_function)(FILE *file, uint32 *sector_size, uint32 *removable, uint32 *is_cdrom) = NULL;
|
||||||
t_bool created = FALSE, copied = FALSE;
|
t_bool created = FALSE, copied = FALSE;
|
||||||
t_bool auto_format = FALSE;
|
t_bool auto_format = FALSE;
|
||||||
t_offset capac, filesystem_capac;
|
t_offset capac, filesystem_capac;
|
||||||
|
@ -1523,6 +1552,7 @@ ctx->capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capaci
|
||||||
ctx->xfer_element_size = (uint32)xfer_element_size; /* save xfer_element_size */
|
ctx->xfer_element_size = (uint32)xfer_element_size; /* save xfer_element_size */
|
||||||
ctx->dptr = dptr; /* save DEVICE pointer */
|
ctx->dptr = dptr; /* save DEVICE pointer */
|
||||||
ctx->dbit = dbit; /* save debug bit */
|
ctx->dbit = dbit; /* save debug bit */
|
||||||
|
ctx->media_removed = 0; /* default present */
|
||||||
sim_debug (ctx->dbit, ctx->dptr, "sim_disk_attach(unit=%d,filename='%s')\n", (int)(uptr-ctx->dptr->units), uptr->filename);
|
sim_debug (ctx->dbit, ctx->dptr, "sim_disk_attach(unit=%d,filename='%s')\n", (int)(uptr-ctx->dptr->units), uptr->filename);
|
||||||
ctx->auto_format = auto_format; /* save that we auto selected format */
|
ctx->auto_format = auto_format; /* save that we auto selected format */
|
||||||
ctx->storage_sector_size = (uint32)sector_size; /* Default */
|
ctx->storage_sector_size = (uint32)sector_size; /* Default */
|
||||||
|
@ -1578,7 +1608,7 @@ uptr->pos = 0;
|
||||||
|
|
||||||
/* Get Device attributes if they are available */
|
/* Get Device attributes if they are available */
|
||||||
if (storage_function)
|
if (storage_function)
|
||||||
storage_function (uptr->fileref, &ctx->storage_sector_size, &ctx->removable);
|
storage_function (uptr->fileref, &ctx->storage_sector_size, &ctx->removable, &ctx->is_cdrom);
|
||||||
|
|
||||||
if ((created) && (!copied)) {
|
if ((created) && (!copied)) {
|
||||||
t_stat r = SCPE_OK;
|
t_stat r = SCPE_OK;
|
||||||
|
@ -1592,7 +1622,7 @@ if ((created) && (!copied)) {
|
||||||
2) it allocates storage for the whole disk at creation time to
|
2) it allocates storage for the whole disk at creation time to
|
||||||
avoid strange failures which may happen during simulator execution
|
avoid strange failures which may happen during simulator execution
|
||||||
if the containing disk is full
|
if the containing disk is full
|
||||||
3) it leaves a Sinh Format disk at the intended size so it may
|
3) it leaves a Simh Format disk at the intended size so it may
|
||||||
subsequently be autosized with the correct size.
|
subsequently be autosized with the correct size.
|
||||||
*/
|
*/
|
||||||
if (secbuf == NULL)
|
if (secbuf == NULL)
|
||||||
|
@ -2256,6 +2286,7 @@ static FILE *sim_os_disk_open_raw (const char *rawdevicename, const char *openmo
|
||||||
{
|
{
|
||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
DWORD DesiredAccess = 0;
|
DWORD DesiredAccess = 0;
|
||||||
|
uint32 is_cdrom;
|
||||||
|
|
||||||
if (strchr (openmode, 'r'))
|
if (strchr (openmode, 'r'))
|
||||||
DesiredAccess |= GENERIC_READ;
|
DesiredAccess |= GENERIC_READ;
|
||||||
|
@ -2274,14 +2305,27 @@ if (!memcmp ("\\.\\", rawdevicename, 3)) {
|
||||||
strcpy (tmpname + 1, rawdevicename);
|
strcpy (tmpname + 1, rawdevicename);
|
||||||
Handle = CreateFileA (tmpname, DesiredAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_WRITE_THROUGH, NULL);
|
Handle = CreateFileA (tmpname, DesiredAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_WRITE_THROUGH, NULL);
|
||||||
free (tmpname);
|
free (tmpname);
|
||||||
if (Handle != INVALID_HANDLE_VALUE)
|
if (Handle != INVALID_HANDLE_VALUE) {
|
||||||
|
if ((sim_os_disk_info_raw (Handle, NULL, NULL, &is_cdrom)) ||
|
||||||
|
(DesiredAccess & GENERIC_WRITE) && is_cdrom) {
|
||||||
|
CloseHandle (Handle);
|
||||||
|
errno = EACCES;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return (FILE *)Handle;
|
return (FILE *)Handle;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Handle = CreateFileA (rawdevicename, DesiredAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_WRITE_THROUGH, NULL);
|
Handle = CreateFileA (rawdevicename, DesiredAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_WRITE_THROUGH, NULL);
|
||||||
if (Handle == INVALID_HANDLE_VALUE) {
|
if (Handle == INVALID_HANDLE_VALUE) {
|
||||||
_set_errno_from_status (GetLastError ());
|
_set_errno_from_status (GetLastError ());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if ((sim_os_disk_info_raw (Handle, NULL, NULL, &is_cdrom)) ||
|
||||||
|
(DesiredAccess & GENERIC_WRITE) && is_cdrom) {
|
||||||
|
CloseHandle (Handle);
|
||||||
|
errno = EACCES;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return (FILE *)Handle;
|
return (FILE *)Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2364,7 +2408,7 @@ static t_stat sim_os_disk_unload_raw (FILE *Disk)
|
||||||
DWORD BytesReturned;
|
DWORD BytesReturned;
|
||||||
uint32 Removable = FALSE;
|
uint32 Removable = FALSE;
|
||||||
|
|
||||||
sim_os_disk_info_raw (Disk, NULL, &Removable);
|
sim_os_disk_info_raw (Disk, NULL, &Removable, NULL);
|
||||||
if (Removable) {
|
if (Removable) {
|
||||||
if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
|
if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
|
||||||
IOCTL_STORAGE_EJECT_MEDIA, /* dwIoControlCode */
|
IOCTL_STORAGE_EJECT_MEDIA, /* dwIoControlCode */
|
||||||
|
@ -2390,7 +2434,7 @@ static t_bool sim_os_disk_isavailable_raw (FILE *Disk)
|
||||||
DWORD BytesReturned;
|
DWORD BytesReturned;
|
||||||
uint32 Removable = FALSE;
|
uint32 Removable = FALSE;
|
||||||
|
|
||||||
sim_os_disk_info_raw (Disk, NULL, &Removable);
|
sim_os_disk_info_raw (Disk, NULL, &Removable, NULL);
|
||||||
if (Removable) {
|
if (Removable) {
|
||||||
if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
|
if (!DeviceIoControl((HANDLE)Disk, /* handle to disk */
|
||||||
IOCTL_STORAGE_CHECK_VERIFY, /* dwIoControlCode */
|
IOCTL_STORAGE_CHECK_VERIFY, /* dwIoControlCode */
|
||||||
|
@ -2408,26 +2452,27 @@ if (Removable) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat sim_os_disk_info_raw (FILE *Disk, uint32 *sector_size, uint32 *removable)
|
static t_stat sim_os_disk_info_raw (FILE *Disk, uint32 *sector_size, uint32 *removable, uint32 *is_cdrom)
|
||||||
{
|
{
|
||||||
DWORD IoctlReturnSize;
|
DWORD IoctlReturnSize;
|
||||||
STORAGE_DEVICE_NUMBER Device;
|
STORAGE_DEVICE_NUMBER Device;
|
||||||
|
|
||||||
ZeroMemory (&Device, sizeof (Device));
|
ZeroMemory (&Device, sizeof (Device));
|
||||||
if (DeviceIoControl((HANDLE)Disk, /* handle to volume */
|
DeviceIoControl((HANDLE)Disk, /* handle to volume */
|
||||||
IOCTL_STORAGE_GET_DEVICE_NUMBER, /* dwIoControlCode */
|
IOCTL_STORAGE_GET_DEVICE_NUMBER, /* dwIoControlCode */
|
||||||
NULL, /* lpInBuffer */
|
NULL, /* lpInBuffer */
|
||||||
0, /* nInBufferSize */
|
0, /* nInBufferSize */
|
||||||
(LPVOID) &Device, /* output buffer */
|
(LPVOID) &Device, /* output buffer */
|
||||||
(DWORD) sizeof(Device), /* size of output buffer */
|
(DWORD) sizeof(Device), /* size of output buffer */
|
||||||
(LPDWORD) &IoctlReturnSize, /* number of bytes returned */
|
(LPDWORD) &IoctlReturnSize, /* number of bytes returned */
|
||||||
(LPOVERLAPPED) NULL)) /* OVERLAPPED structure */
|
(LPOVERLAPPED) NULL); /* OVERLAPPED structure */
|
||||||
sim_printf ("Device OK - Type: %s, Number: %d\n", _device_type_name (Device.DeviceType), (int)Device.DeviceNumber);
|
|
||||||
|
|
||||||
if (sector_size)
|
if (sector_size)
|
||||||
*sector_size = 512;
|
*sector_size = 512;
|
||||||
if (removable)
|
if (removable)
|
||||||
*removable = 0;
|
*removable = 0;
|
||||||
|
if (is_cdrom)
|
||||||
|
*is_cdrom = (Device.DeviceType == FILE_DEVICE_CD_ROM) || (Device.DeviceType == FILE_DEVICE_DVD);
|
||||||
#ifdef IOCTL_STORAGE_READ_CAPACITY
|
#ifdef IOCTL_STORAGE_READ_CAPACITY
|
||||||
if (1) {
|
if (1) {
|
||||||
STORAGE_READ_CAPACITY S;
|
STORAGE_READ_CAPACITY S;
|
||||||
|
@ -2496,8 +2541,6 @@ if (1) {
|
||||||
*removable = H.MediaRemovable;
|
*removable = H.MediaRemovable;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (removable && *removable)
|
|
||||||
sim_printf ("Removable Device\n");
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2644,12 +2687,14 @@ if (sectswritten)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable)
|
static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable, uint32 *is_cdrom)
|
||||||
{
|
{
|
||||||
if (sector_size)
|
if (sector_size)
|
||||||
*sector_size = 512;
|
*sector_size = 512;
|
||||||
if (removable)
|
if (removable)
|
||||||
*removable = 0;
|
*removable = 0;
|
||||||
|
if (is_cdrom)
|
||||||
|
*is_cdrom = 0;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2702,7 +2747,7 @@ static t_stat sim_os_disk_wrsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *s
|
||||||
return SCPE_NOFNC;
|
return SCPE_NOFNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable)
|
static t_stat sim_os_disk_info_raw (FILE *f, uint32 *sector_size, uint32 *removable, uint32 *is_cdrom)
|
||||||
{
|
{
|
||||||
return SCPE_NOFNC;
|
return SCPE_NOFNC;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue