]> git.sur5r.net Git - cc65/blobdiff - libsrc/cbm/readdir.c
Merge remote-tracking branch 'upstream/master'
[cc65] / libsrc / cbm / readdir.c
index 10593e21b0b4f00b36103841767d9b5750a4703d..d6947316bf0039466b7c0ac7b810c787572b509b 100644 (file)
@@ -4,9 +4,6 @@
 
 
 
-#include <stdlib.h>
-#include <string.h>
-#include <dirent.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
 
 struct dirent* __fastcall__ readdir (register DIR* dir)
 {
-    static struct dirent entry;
     register unsigned char* b;
     register unsigned char i;
-    unsigned char count;
-    unsigned char j;
-    unsigned char s;
+    register unsigned char count;
+    static unsigned char s;
+    static unsigned char j;
     unsigned char buffer[0x40];
+    static struct dirent entry;
 
 
     /* Remember the directory offset for this entry */
     entry.d_off = dir->off;
 
     /* Skip the basic line-link */
-    if (!_dirskip (2, dir)) {
+    if (!_dirread (dir, buffer, 2)) {
         /* errno already set */
-        goto exit;
+        goto exitpoint;
     }
-    dir->off += 2;
 
     /* Read the number of blocks */
-    if (read (dir->fd, &entry.d_blocks, sizeof (entry.d_blocks)) !=
-        sizeof (entry.d_blocks)) {
-        goto error;
+    if (!_dirread (dir, &entry.d_blocks, sizeof (entry.d_blocks))) {
+        goto exitpoint;
     }
 
     /* Read the next file entry into the buffer */
-    for (count = 0, b = buffer; count < sizeof (buffer); ++count, ++b) {
-        if (read (dir->fd, b, 1) != 1) {
-            /* ### Check for EOF */
-            goto error;
+    for (count = 0, b = buffer; count < sizeof (buffer); ++b) {
+        if (!_dirread1 (dir, b)) {
+            goto exitpoint;
         }
+        ++count;
         if (*b == '\0') {
             break;
         }
     }
 
+    /* Bump the directory offset and include the bytes for line-link and size */
+    dir->off += count + 4;
+
     /* End of directory is reached if the buffer contains "blocks free". It is
-     * sufficient here to check for the leading 'b'. To avoid problems if we're
-     * called again, read until end of directory.
+     * sufficient here to check for the leading 'b'. buffer will contain at
+     * least one byte if we come here.
      */
-    if (count > 0 && buffer[0] == 'b') {
-        while (read (dir->fd, buffer, 1) == 1) ;
-        return 0;
+    if (buffer[0] == 'b') {
+        goto exitpoint;
     }
 
-    /* Bump the directory offset */
-    dir->off += count;
-
     /* Parse the buffer for the filename and file type */
     i = 0;
     j = 0;
@@ -84,9 +78,17 @@ struct dirent* __fastcall__ readdir (register DIR* dir)
             case 1:
                 /* Within file name */
                 if (*b == '"') {
+                    /* End of file name found. */
                     entry.d_name[j] = '\0';
                     entry.d_namlen = j;
-                    s = 2;
+                    if (entry.d_off > 2) {
+                        /* Proceed with file type */
+                        s = 2;
+                    } else {
+                        /* This is a disk header, so we're done */
+                        entry.d_type = _CBM_T_HEADER;
+                        return &entry;
+                    }
                 } else if (j < sizeof (entry.d_name) - 1) {
                     entry.d_name[j] = *b;
                     ++j;
@@ -111,8 +113,8 @@ struct dirent* __fastcall__ readdir (register DIR* dir)
                 /* Distinguish DEL or DIR file type entries */
                 switch (*b) {
                     case 'e':                                   break;
-                    case 'i': entry.d_type = CBM_T_DIR;         break;
-                    default:  entry.d_type = CBM_T_OTHER;       break;
+                    case 'i': entry.d_type = _CBM_T_DIR;        break;
+                    default:  entry.d_type = _CBM_T_OTHER;      break;
                 }
                 return &entry;
         }
@@ -120,10 +122,9 @@ struct dirent* __fastcall__ readdir (register DIR* dir)
         ++b;
     }
 
-    /* Something went wrong - terminating quote not found */
-error:
+    /* Something went wrong when parsing the directory entry */
     _errno = EIO;
-exit:
+exitpoint:
     return 0;
 }