SCP: Avoid seeking on attached sequential devices on non seekable files

As reported on #982
This commit is contained in:
Mark Pizzolato 2020-12-14 18:48:14 -08:00
parent c32b3ab054
commit 852c0bc1bc
5 changed files with 52 additions and 13 deletions

3
scp.c
View file

@ -8736,7 +8736,8 @@ for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* reposition all */
for (j = 0; j < dptr->numunits; j++) { /* seq devices */
uptr = dptr->units + j;
if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == (UNIT_ATT + UNIT_SEQ))
if (sim_fseek (uptr->fileref, uptr->pos, SEEK_SET))
if (sim_can_seek (uptr->fileref) &&
(0 != sim_fseek (uptr->fileref, uptr->pos, SEEK_SET)))
return sim_messagef (SCPE_IERR, "Can't seek to %u in %s for %s\n", (unsigned)uptr->pos, uptr->filename, sim_uname (uptr));
}
}

View file

@ -151,7 +151,7 @@ static t_stat sim_os_ttinit (void);
static t_stat sim_os_ttrun (void);
static t_stat sim_os_ttcmd (void);
static t_stat sim_os_ttclose (void);
static t_bool sim_os_ttisatty (void);
static t_bool sim_os_fd_isatty (int fd);
static t_stat sim_set_rem_telnet (int32 flag, CONST char *cptr);
static t_stat sim_set_rem_bufsize (int32 flag, CONST char *cptr);
@ -3256,10 +3256,14 @@ t_bool sim_ttisatty (void)
static int answer = -1;
if (answer == -1)
answer = sim_os_ttisatty ();
answer = sim_os_fd_isatty (0);
return (t_bool)answer;
}
t_bool sim_fd_isatty (int fd)
{
return sim_os_fd_isatty (fd);
}
/* Platform specific routine definitions */
@ -3356,9 +3360,9 @@ sys$dassgn (tty_chan);
return SCPE_OK;
}
static t_bool sim_os_ttisatty (void)
static t_bool sim_os_fd_isatty (int fd)
{
return isatty (fileno (stdin));
return isatty (fd);
}
static t_stat sim_os_poll_kbd_data (void)
@ -3446,8 +3450,10 @@ return SCPE_OK;
#define RAW_MODE 0
static HANDLE std_input;
static HANDLE std_output;
static HANDLE std_error;
static DWORD saved_input_mode;
static DWORD saved_output_mode;
static DWORD saved_error_mode;
#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
#endif
@ -3495,12 +3501,16 @@ sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_ttinit()\n");
SetConsoleCtrlHandler( ControlHandler, TRUE );
std_input = GetStdHandle (STD_INPUT_HANDLE);
std_output = GetStdHandle (STD_OUTPUT_HANDLE);
std_error = GetStdHandle (STD_ERROR_HANDLE);
if ((std_input) && /* Not Background process? */
(std_input != INVALID_HANDLE_VALUE))
GetConsoleMode (std_input, &saved_input_mode); /* Save Input Mode */
if ((std_output) && /* Not Background process? */
(std_output != INVALID_HANDLE_VALUE))
GetConsoleMode (std_output, &saved_output_mode); /* Save Output Mode */
if ((std_error) && /* Not Background process? */
(std_error != INVALID_HANDLE_VALUE))
GetConsoleMode (std_error, &saved_error_mode); /* Save Output Mode */
return SCPE_OK;
}
@ -3557,11 +3567,26 @@ static t_stat sim_os_ttclose (void)
return SCPE_OK;
}
static t_bool sim_os_ttisatty (void)
static t_bool sim_os_fd_isatty (int fd)
{
DWORD Mode;
HANDLE handle;
return (std_input) && (std_input != INVALID_HANDLE_VALUE) && GetConsoleMode (std_input, &Mode);
switch (fd) {
case 0:
handle = std_input;
break;
case 1:
handle = std_output;
break;
case 2:
handle = std_error;
break;
default:
handle = NULL;
}
return (handle) && (handle != INVALID_HANDLE_VALUE) && GetConsoleMode (handle, &Mode);
}
static t_stat sim_os_poll_kbd (void)
@ -3712,7 +3737,7 @@ static t_stat sim_os_ttclose (void)
return SCPE_OK;
}
static t_bool sim_os_ttisatty (void)
static t_bool sim_os_fd_isatty (int fd)
{
return 1;
}
@ -3924,7 +3949,7 @@ static t_stat sim_os_ttclose (void)
return SCPE_OK;
}
static t_bool sim_os_ttisatty (void)
static t_bool sim_os_fd_isatty (int fd)
{
return 1;
}
@ -4067,9 +4092,9 @@ static t_stat sim_os_ttclose (void)
return sim_ttcmd ();
}
static t_bool sim_os_ttisatty (void)
static t_bool sim_os_fd_isatty (int fd)
{
return isatty (fileno (stdin));
return isatty (fd);
}
static t_stat sim_os_poll_kbd (void)
@ -4241,9 +4266,9 @@ static t_stat sim_os_ttclose (void)
return sim_ttcmd ();
}
static t_bool sim_os_ttisatty (void)
static t_bool sim_os_fd_isatty (int fd)
{
return isatty (fileno (stdin));
return isatty (fd);
}
static t_stat sim_os_poll_kbd (void)

View file

@ -122,6 +122,7 @@ t_stat sim_ttrun (void);
t_stat sim_ttcmd (void);
t_stat sim_ttclose (void);
t_bool sim_ttisatty (void);
t_bool sim_fd_isatty (int fd);
int32 sim_tt_inpcvt (int32 c, uint32 mode);
int32 sim_tt_outcvt (int32 c, uint32 mode);
t_stat sim_tt_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);

View file

@ -44,6 +44,7 @@
sim_fwrite - endian independent write (formerly fxwrite)
sim_fseek - conditionally extended (>32b) seek (
sim_fseeko - extended seek (>32b if available)
sim_can_seek - test for seekable (regular file)
sim_fsize - get file size
sim_fsize_name - get file size of named file
sim_fsize_ex - get file size as a t_offset
@ -235,6 +236,16 @@ uint32 sim_fsize (FILE *fp)
return (uint32)(sim_fsize_ex (fp));
}
t_bool sim_can_seek (FILE *fp)
{
struct stat statb;
if ((0 != fstat (fileno (fp), &statb)) ||
(0 == (statb.st_mode & S_IFREG)))
return FALSE;
return TRUE;
}
/* OS-dependent routines */
/* Optimized file open */

View file

@ -60,6 +60,7 @@ typedef int32 t_offset;
FILE *sim_fopen (const char *file, const char *mode);
int sim_fseek (FILE *st, t_addr offset, int whence);
int sim_fseeko (FILE *st, t_offset offset, int whence);
t_bool sim_can_seek (FILE *st);
int sim_set_fsize (FILE *fptr, t_addr size);
int sim_set_fifo_nonblock (FILE *fptr);
size_t sim_fread (void *bptr, size_t size, size_t count, FILE *fptr);