From 852c0bc1bcf43f8c29a1e3f8b9ebe1314b3b2b0d Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 14 Dec 2020 18:48:14 -0800 Subject: [PATCH] SCP: Avoid seeking on attached sequential devices on non seekable files As reported on #982 --- scp.c | 3 ++- sim_console.c | 49 +++++++++++++++++++++++++++++++++++++------------ sim_console.h | 1 + sim_fio.c | 11 +++++++++++ sim_fio.h | 1 + 5 files changed, 52 insertions(+), 13 deletions(-) diff --git a/scp.c b/scp.c index e3fb9a8c..2b86191f 100644 --- a/scp.c +++ b/scp.c @@ -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)); } } diff --git a/sim_console.c b/sim_console.c index 068ee78b..a349be4a 100644 --- a/sim_console.c +++ b/sim_console.c @@ -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) diff --git a/sim_console.h b/sim_console.h index aa0c5949..b73348ee 100644 --- a/sim_console.h +++ b/sim_console.h @@ -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); diff --git a/sim_fio.c b/sim_fio.c index e99799af..69a5c8c3 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -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 */ diff --git a/sim_fio.h b/sim_fio.h index aa96a8d6..d7f512e0 100644 --- a/sim_fio.h +++ b/sim_fio.h @@ -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);