readdir bug (was: [cc65] Atari Extended Memory Driver Anybody?)

From: Spiro Trikaliotis <ml-cc651trikaliotis.net>
Date: 2012-09-13 21:05:46
Hello,

as "thank you" for Uz' permanent support, I thought I'd try to work on
the readdir bug that does not allow to present more than 8 directory
entries.

As I am most familiar with that platform, I tried the C64 one.

* On Mon, Sep 10, 2012 at 02:03:52PM +0200 Oliver Schmidt wrote:
 
> If I'm not mistaken then we're talking here about the Atari - and the
> Atari readdir() implementation doesn't share anything with the CBM
> readdir() implementation. So it seems to me that both implementations
> coincidentally share the same bug. Or am I on the wrong track here?

In fact, currently, I'd think it is a compiler bug that triggers it.

I tried to do some test program to verify this. It can be found on

  http://www.trikaliotis.net/Download/cc65/test.c
  http://www.trikaliotis.net/Download/cc65/Makefile

Note: In order to compile test.c, you must have a directory cc65/ with
the full sources inside of it. If you do not want this, you have to make
sure that the file cc65/libsrc/cbm/dir.h is found in the include in line
8.


First, I tried to execute main1() in main(). mytest() called in main1()
tries to mimic the way readdir() reads the directory entries from the
floppy, but without additional logic. It writes everything into $C000
onwards.

Result: Every single byte is read correctly into $C000, regardless of
whether true drive emulation is on or off in VICE. Thus, the actual
device access seems to be correct.


Then, I tried to run main2() in main(). main2() is a slightly modified
version of the test program for readdir() from Oliver.

It uses the readdir() implementation included in this file. It has been
mostly instrumented, before doing some small modifications for testing
purposes.

It's diff to the original readdir is as follows:

--- cc65/libsrc/cbm/readdir.c	2012-08-02 08:10:52.000000000 +0200
+++ test.c	2012-09-13 20:39:54.990194000 +0200
[...]

 struct dirent* __fastcall__ readdir (register DIR* dir)
 {
@@ -57,6 +51,7 @@
      * least one byte if we come here.
      */
     if (buffer[0] == 'b') {
+printf("1: buffer = '%s', buffer[0] == 'b'\n", buffer);
         goto exitpoint;
     }
 
@@ -65,6 +60,7 @@
     j = 0;
     s = 0;
     b = buffer;
+printf("2: buffer = '%s'\n", buffer);
     while (i < count) {
         switch (s) {
 
@@ -98,30 +94,21 @@
             case 2:
                 /* Searching for file type */
                 if (*b != ' ') {
-                    entry.d_type = _cbm_filetype (*b);
-                    if (*b == 'd') {
-                        /* May be DEL or DIR, check next char */
-                        s = 3;
-                    } else {
-                        /* Done */
-                        return &entry;
-                    }
+#if 0
+                    entry.d_type = _CBM_T_PRG; // _cbm_filetype (*b);
+#endif
+                    return &entry;
                 }
                 break;
 
-            case 3:
-                /* 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;
-                }
-                return &entry;
         }
         ++i;
         ++b;
     }
 
+printf("7-entry: name='%s' (%u), off=%u, blocks=%u, type=%u\n", entry.d_name, entry.d_namlen, entry.d_off, entry.d_blocks, entry.d_type);
+return &entry;
+
     /* Something went wrong when parsing the directory entry */
     _errno = EIO;
 exitpoint:
@@ -129,4 +116,71 @@
 }

You see, I instrumented with some outputs, and I modified the case 2 by
making it as simple as possible.

The "#if 0" is important: If I leave the line as is, then the routine
processes all directory entries of the 1541 disk, regardless of how many
of them are there. (Of course, the values output are not correct, but
this is not the issue I want to show.)

If I change it to "#if 1" instead, then the buffer output in "1:" and
"2:" is WRONG after the 8th directory entry. That's the case where
normally, readdir() aborts after the 8th entry. Here, it does not
because I added the "return &entry;" after the printf("7-...").

Too me, it seems to be very likely that the compiler generated wrong
code, as I cannot find a reason why this small line should change the
behaviour so drastically.
However, I am stuck here, I do not understand why this happens exactly.

Any takers?

Regards,
Spiro.

-- 
Spiro R. Trikaliotis
http://www.trikaliotis.net/
----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo@musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.
Received on Thu Sep 13 21:06:09 2012

This archive was generated by hypermail 2.1.8 : 2012-09-13 21:06:14 CEST