From a83bf3dc04fad6674218aeca24f0cb84a58d41eb Mon Sep 17 00:00:00 2001 From: uz Date: Sun, 3 Jun 2012 13:59:31 +0000 Subject: [PATCH] Implement special read function that sets errno in case of a short read. Drop _dirskip in favour of the new function. git-svn-id: svn://svn.cc65.org/cc65/trunk@5672 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- libsrc/cbm/dir.h | 16 ++++--- libsrc/cbm/dir.inc | 7 ++- libsrc/cbm/dir.s | 105 +++++++++++++++++++++++-------------------- libsrc/cbm/opendir.c | 5 ++- libsrc/cbm/readdir.c | 29 ++++++------ 5 files changed, 87 insertions(+), 75 deletions(-) diff --git a/libsrc/cbm/dir.h b/libsrc/cbm/dir.h index d7a30518d..c7c9ae21b 100644 --- a/libsrc/cbm/dir.h +++ b/libsrc/cbm/dir.h @@ -30,12 +30,16 @@ struct DIR { -unsigned char __fastcall__ _dirskip (unsigned char count, struct DIR* dir); -/* Skip bytes from the directory and make sure, errno is set if this isn't - * possible. Return true if anything is ok and false otherwise. For - * simplicity we assume that read will never return less than count if there - * is no error and end-of-file is not reached. - * Note: count must not be more than 254. +unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count); +/* Read characters from the directory into the supplied buffer. Makes sure, + * errno is set in case of a short read. Return true if the read was + * successful and false otherwise. + */ + +unsigned char __fastcall__ _dirread1 (DIR* dir, void* buf); +/* Read one byte from the directory into the supplied buffer. Makes sure, + * errno is set in case of a short read. Return true if the read was + * successful and false otherwise. */ diff --git a/libsrc/cbm/dir.inc b/libsrc/cbm/dir.inc index 3536f87f7..481492313 100644 --- a/libsrc/cbm/dir.inc +++ b/libsrc/cbm/dir.inc @@ -21,7 +21,10 @@ .global _opendir .global _closedir .global _readdir - .global _telldir - .global _rewinddir +; .global _telldir +; .global _rewinddir + .global __dirread + .global __dirread1 .global __dirskip + diff --git a/libsrc/cbm/dir.s b/libsrc/cbm/dir.s index 903e20483..1916a4104 100644 --- a/libsrc/cbm/dir.s +++ b/libsrc/cbm/dir.s @@ -1,92 +1,99 @@ ; ; Ullrich von Bassewitz, 2012-06-01 ; -; unsigned char __fastcall__ _dirskip (unsigned char count, struct DIR* dir); -; /* Skip bytes from the directory and make sure, errno is set if this isn't -; * possible. Return true if anything is ok and false otherwise. For -; * simplicity we assume that read will never return less than count if there -; * is no error and end-of-file is not reached. -; * Note: count must not be more than 254. -; */ -; +; Helper functions for open-/read-/closedir + .include "dir.inc" .include "errno.inc" .include "zeropage.inc" - + + .import pushax .import _read - .import pushax, pushptr1idx - .import subysp, addysp1 -.proc __dirskip +;--------------------------------------------------------------------------- +; +; unsigned char __fastcall__ _dirread1 (DIR* dir, void* buf); +; /* Read one byte from the directory into the supplied buffer. Makes sure, +; * errno is set in case of a short read. Return true if the read was +; * successful and false otherwise. +; */ - sta ptr1 - stx ptr1+1 ; Save dir +__dirread1: -; Get count and allocate space on the stack + jsr pushax ; Push buf + lda #1 ; Load count = 1 - ldy #0 - lda (sp),y - pha - tay - jsr subysp +; Run directly into __dirread -; Save current value of sp +;--------------------------------------------------------------------------- +; +; unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count); +; /* Read characters from the directory into the supplied buffer. Makes sure, +; * errno is set in case of a short read. Return true if the read was +; * successful and false otherwise. +; */ - lda sp - pha - lda sp+1 - pha +__dirread: -; Push dir->fd +; Save count - ldy #DIR::fd+1 - jsr pushptr1idx + pha -; Push pointer to buffer +; Replace dir by dir->fd + ldy #2 + lda (sp),y + sta ptr1 + iny + lda (sp),y + sta ptr1+1 + ldy #DIR::fd+1 + lda (ptr1),y + pha + dey + lda (ptr1),y + ldy #2 + sta (sp),y pla - tax - pla - jsr pushax + iny + sta (sp),y -; Load count and call read +; Get count, save it again, clear the high byte and call read(). By the +; previous actions, the stack frame is as read() needs it, and read() will +; also drop it. pla pha ldx #0 jsr _read -; Check for errors. In case of errors, errno is already set. +; Check for errors. cpx #$FF - bne L2 + bne L3 -; read() returned an error +; read() returned an error, so errno is already set - pla ; Count - tay - lda #0 - tax -L1: jmp addysp1 ; Drop buffer plus count + pla ; Drop count + inx ; X = 0 +L1: txa ; Return zero +L2: rts ; read() was successful, check number of bytes read. We assume that read will ; not return more than count, so X is zero if we come here. -L2: sta tmp1 - pla ; count - tay +L3: sta tmp1 ; Save returned count + pla ; Our count cmp tmp1 - beq L1 ; Drop variables, return count + beq L2 ; Ok, return count ; Didn't read enough bytes. This is an error for us, but errno is not set lda #= 0) { /* Skip the disk header */ - if (_dirskip (32, &d)) { + if (_dirread (&d, buf, 32)) { /* Allocate memory for the DIR structure returned */ dir = malloc (sizeof (*dir)); diff --git a/libsrc/cbm/readdir.c b/libsrc/cbm/readdir.c index 10593e21b..58c244de6 100644 --- a/libsrc/cbm/readdir.c +++ b/libsrc/cbm/readdir.c @@ -18,36 +18,34 @@ 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; + register unsigned char count; unsigned char s; + 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; + if (!_dirread1 (dir, b)) { + goto exitpoint; } if (*b == '\0') { break; @@ -59,7 +57,7 @@ struct dirent* __fastcall__ readdir (register DIR* dir) * called again, read until end of directory. */ if (count > 0 && buffer[0] == 'b') { - while (read (dir->fd, buffer, 1) == 1) ; + while (_dirread1 (dir, buffer)) ; return 0; } @@ -120,10 +118,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; } -- 2.39.5