From 3ab75c62144738bdf545236e72e572090f90f028 Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sat, 17 Oct 2015 10:58:29 -0700 Subject: [PATCH] Refactor : improved error handling of track write --- src/disk.c | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/disk.c b/src/disk.c index 8bbe7b5e..36793583 100644 --- a/src/disk.c +++ b/src/disk.c @@ -473,26 +473,50 @@ static bool load_track_data(void) { static bool save_track_data(void) { SCOPE_TRACE_DISK("save_track_data"); + size_t expected = 0; + uint8_t *buf = NULL; if (disk6.disk[disk6.drive].nibblized) { // .nib image - int track_pos = NIB_TRACK_SIZE * (disk6.disk[disk6.drive].phase >> 1); - fseek(disk6.disk[disk6.drive].fp, track_pos, SEEK_SET); - if (fwrite(disk6.disk[disk6.drive].track_image, 1, NIB_TRACK_SIZE, disk6.disk[disk6.drive].fp) != NIB_TRACK_SIZE) { - ERRLOG("could not write nib data ..."); - return false; - } + expected = NIB_TRACK_SIZE; + buf = disk6.disk[disk6.drive].track_image; } else { // .dsk, .do, .po images - uint8_t buf[DSK_TRACK_SIZE]; - denibblize_track(disk6.disk[disk6.drive].track_image, disk6.drive, buf); - int track_pos = DSK_TRACK_SIZE * (disk6.disk[disk6.drive].phase >> 1); - fseek(disk6.disk[disk6.drive].fp, track_pos, SEEK_SET); - if (fwrite(buf, 1, DSK_TRACK_SIZE, disk6.disk[disk6.drive].fp) != DSK_TRACK_SIZE) { - ERRLOG("could not write dsk data ..."); - return false; - } + uint8_t _buf[DSK_TRACK_SIZE] = { 0 }; + denibblize_track(disk6.disk[disk6.drive].track_image, disk6.drive, _buf); + expected = DSK_TRACK_SIZE; + buf = _buf; // !!! } - fflush(disk6.disk[disk6.drive].fp); + + const long track_pos = expected * (disk6.disk[disk6.drive].phase >> 1); + TEMP_FAILURE_RETRY(fseek(disk6.disk[disk6.drive].fp, track_pos, SEEK_SET)); + + size_t idx = 0; + do { + size_t ct = fwrite(buf+idx, 1, expected-idx, disk6.disk[disk6.drive].fp); + if (UNLIKELY(ct == 0)) { + if (ferror(disk6.disk[disk6.drive].fp)) { + // hopefully a transient error ... + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + usleep(10); + continue; + } else { + ERRLOG("OOPS, fatal error reading disk image %s at phase %d", disk6.disk[disk6.drive].file_name, disk6.disk[disk6.drive].phase); + break; + } + } else { + ERRLOG("OOPS, EOF attemping to read disk image %s at phase %d", disk6.disk[disk6.drive].file_name, disk6.disk[disk6.drive].phase); + break; + } + } + idx += ct; + + if (LIKELY(idx == expected)) { + break; + } + assert(idx < expected && "the world is not sane"); + } while (1); + + TEMP_FAILURE_RETRY(fflush(disk6.disk[disk6.drive].fp)); disk6.disk[disk6.drive].track_dirty = false; return true;