From 315a07cbc76ce5b515b7256265a6fc32bd51652c Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Sun, 13 Feb 2022 22:50:37 -0800 Subject: [PATCH] SCP: Avoid writing out memory buffered devices on detach that haven't changed As discussed in #1109 --- scp.c | 22 +++++++++++++++++----- sim_defs.h | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/scp.c b/scp.c index 181ab7fe..df835885 100644 --- a/scp.c +++ b/scp.c @@ -8143,13 +8143,22 @@ else { } if (uptr->flags & UNIT_BUFABLE) { /* buffer? */ uint32 cap = ((uint32) uptr->capac) / dptr->aincr; /* effective size */ - if (uptr->flags & UNIT_MUSTBUF) /* dyn alloc? */ + if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */ uptr->filebuf = calloc (cap, SZ_D (dptr)); /* allocate */ - if (uptr->filebuf == NULL) /* no buffer? */ - return attach_err (uptr, SCPE_MEM); /* error */ + uptr->filebuf2 = calloc (cap, SZ_D (dptr)); /* allocate copy */ + if ((uptr->filebuf == NULL) || /* no buffer? */ + (uptr->filebuf2 == NULL)) { + free (uptr->filebuf); + uptr->filebuf = NULL; + free (uptr->filebuf2); + uptr->filebuf2 = NULL; + return attach_err (uptr, SCPE_MEM); /* error */ + } + } sim_messagef (SCPE_OK, "%s: buffering file in memory\n", sim_uname (uptr)); uptr->hwmark = (uint32)sim_fread (uptr->filebuf, /* read file */ SZ_D (dptr), cap, uptr->fileref); + memcpy (uptr->filebuf2, uptr->filebuf, cap * SZ_D (dptr));/* save initial contents */ uptr->flags = uptr->flags | UNIT_BUF; /* set buffered */ } uptr->flags = uptr->flags | UNIT_ATT; @@ -8268,7 +8277,8 @@ if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_OK; if ((uptr->flags & UNIT_BUF) && (uptr->filebuf)) { uint32 cap = (uptr->hwmark + dptr->aincr - 1) / dptr->aincr; - if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { + if (((uptr->flags & UNIT_RO) == 0) && + (memcmp (uptr->filebuf, uptr->filebuf2, (size_t)(SZ_D (dptr) * (uptr->capac / dptr->aincr))) != 0)) { sim_messagef (SCPE_OK, "%s: writing buffer to file: %s\n", sim_uname (uptr), uptr->filename); rewind (uptr->fileref); sim_fwrite (uptr->filebuf, SZ_D (dptr), cap, uptr->fileref); @@ -8276,8 +8286,10 @@ if ((uptr->flags & UNIT_BUF) && (uptr->filebuf)) { sim_printf ("%s: I/O error - %s", sim_uname (uptr), strerror (errno)); } if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */ - free (uptr->filebuf); /* free buf */ + free (uptr->filebuf); /* free buffers */ uptr->filebuf = NULL; + free (uptr->filebuf2); + uptr->filebuf2 = NULL; } uptr->flags = uptr->flags & ~UNIT_BUF; } diff --git a/sim_defs.h b/sim_defs.h index 4b5ceb15..9bbb99e4 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -585,6 +585,7 @@ struct UNIT { uint32 dynflags; /* dynamic flags */ t_addr capac; /* capacity */ t_addr pos; /* file position */ + void *filebuf2; /* copy of initial memory buffer */ void (*io_flush)(UNIT *up); /* io flush routine */ uint32 iostarttime; /* I/O start time */ int32 buf; /* buffer */