Blob Blame History Raw
From a4752748ad7a82e42b6187161dce0baf35f5e2bb Mon Sep 17 00:00:00 2001
From: Claus <claus@protovision.games>
Date: Mon, 4 Feb 2019 13:44:46 +0100
Subject: [PATCH 12/30] Fix for -L switch: used always index 0 and also did not
 check for maximum index (issue #7)

---
 cc1541.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/cc1541.c b/cc1541.c
index c8da428..f572e87 100644
--- a/cc1541.c
+++ b/cc1541.c
@@ -606,6 +606,41 @@ find_file(image_type type, unsigned char* image, char* filename, unsigned char *
     return -1;
 }
 
+/* sets image offset to the next DIR entry, returns 0 when the DIR end was reached */
+static int
+next_dir_entry(image_type type, unsigned char* image, int *offset)
+{
+    if (*offset % BLOCKSIZE == 7 * DIRENTRYSIZE) {
+        /* last entry in sector */
+        int sector_offset = (*offset / BLOCKSIZE) * BLOCKSIZE;
+        int track = image[sector_offset];
+        if (track == 0) {
+            /* this was the last DIR sector */
+            return 0;
+        } else {
+            /* follow the t/s link */
+            int sector = image[sector_offset + 1];
+            *offset = linear_sector(type, track, sector) * BLOCKSIZE;
+        }
+    } else {
+        *offset += DIRENTRYSIZE;
+    }
+    return 1;
+}
+
+static int
+num_dir_entries(image_type type, unsigned char* image)
+{
+    int entries = 0;
+    int offset = linear_sector(type, DIRTRACK, 1) * BLOCKSIZE;
+    do {
+        if (image[offset + 2] != 0) {
+            entries++;
+        }
+    } while (next_dir_entry(type, image, &offset));
+    return entries;
+}
+
 static void
 create_dir_entries(image_type type, unsigned char* image, imagefile* files, int num_files, int dir_sector_interleave, unsigned int shadowdirtrack)
 {
@@ -860,9 +895,16 @@ write_files(image_type type, unsigned char* image, imagefile* files, int num_fil
             if (file->localname != NULL) {
               /* find loopfile source file */
                 direntryindex = find_file(type, image, file->localname, &track, &sector, &file->nrSectors);
-            } else if(direntryindex >= file->direntryindex) {
-                fprintf(stderr, "Loop file index %d (%d) not found\n", file->loopindex, i + 1);
-                exit(-1);
+            } else {
+                if (direntryindex == file->direntryindex) {
+                    fprintf(stderr, "Loop file index %d cannot refer to itself\n", file->loopindex, i + 1);
+                    exit(-1);
+                }
+                int numfiles = num_dir_entries(type, image);
+                if (direntryindex >= numfiles) {
+                    fprintf(stderr, "Loop file index %d is higher than number of files %d\n", file->loopindex, numfiles);
+                    exit(-1);
+                }
             }
             if (direntryindex >= 0) {
                 file->track = track;
@@ -1523,6 +1565,7 @@ main(int argc, char* argv[])
               return -1;
             }
             files[nrFiles].mode |= MODE_LOOPFILE;
+            files[nrFiles].loopindex = loopindex - 1;
             evalhexescape(filename);
             strncpy(files[nrFiles].filename, filename, FILENAMEMAXSIZE);
             files[nrFiles].sectorInterleave = sectorInterleave ? sectorInterleave : defaultSectorInterleave;
-- 
2.21.0