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
This commit is contained in:
uz
2012-06-03 13:59:31 +00:00
parent 9d0a2c3007
commit a83bf3dc04
5 changed files with 91 additions and 79 deletions

View File

@@ -30,12 +30,16 @@ struct DIR {
unsigned char __fastcall__ _dirskip (unsigned char count, struct DIR* dir); unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count);
/* Skip bytes from the directory and make sure, errno is set if this isn't /* Read characters from the directory into the supplied buffer. Makes sure,
* possible. Return true if anything is ok and false otherwise. For * errno is set in case of a short read. Return true if the read was
* simplicity we assume that read will never return less than count if there * successful and false otherwise.
* is no error and end-of-file is not reached. */
* Note: count must not be more than 254.
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.
*/ */

View File

@@ -21,7 +21,10 @@
.global _opendir .global _opendir
.global _closedir .global _closedir
.global _readdir .global _readdir
.global _telldir ; .global _telldir
.global _rewinddir ; .global _rewinddir
.global __dirread
.global __dirread1
.global __dirskip .global __dirskip

View File

@@ -1,92 +1,99 @@
; ;
; Ullrich von Bassewitz, 2012-06-01 ; Ullrich von Bassewitz, 2012-06-01
; ;
; unsigned char __fastcall__ _dirskip (unsigned char count, struct DIR* dir); ; Helper functions for open-/read-/closedir
; /* 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.
; */
;
.include "dir.inc" .include "dir.inc"
.include "errno.inc" .include "errno.inc"
.include "zeropage.inc" .include "zeropage.inc"
.import pushax
.import _read .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 __dirread1:
stx ptr1+1 ; Save dir
; Get count and allocate space on the stack jsr pushax ; Push buf
lda #1 ; Load count = 1
ldy #0 ; Run directly into __dirread
;---------------------------------------------------------------------------
;
; 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.
; */
__dirread:
; Save count
pha
; Replace dir by dir->fd
ldy #2
lda (sp),y lda (sp),y
pha sta ptr1
tay iny
jsr subysp lda (sp),y
sta ptr1+1
; Save current value of sp
lda sp
pha
lda sp+1
pha
; Push dir->fd
ldy #DIR::fd+1 ldy #DIR::fd+1
jsr pushptr1idx lda (ptr1),y
pha
; Push pointer to buffer dey
lda (ptr1),y
ldy #2
sta (sp),y
pla pla
tax iny
pla sta (sp),y
jsr pushax
; 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 pla
pha pha
ldx #0 ldx #0
jsr _read jsr _read
; Check for errors. In case of errors, errno is already set. ; Check for errors.
cpx #$FF cpx #$FF
bne L2 bne L3
; read() returned an error ; read() returned an error, so errno is already set
pla ; Count pla ; Drop count
tay inx ; X = 0
lda #0 L1: txa ; Return zero
tax L2: rts
L1: jmp addysp1 ; Drop buffer plus count
; read() was successful, check number of bytes read. We assume that read will ; 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. ; not return more than count, so X is zero if we come here.
L2: sta tmp1 L3: sta tmp1 ; Save returned count
pla ; count pla ; Our count
tay
cmp tmp1 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 ; Didn't read enough bytes. This is an error for us, but errno is not set
lda #<EIO lda #<EIO
sta __errno sta __errno
stx __errno+1 stx __errno+1 ; X is zero
txa ; A=X=0 bne L1 ; Branch always
beq L1 ; Branch always
.endproc

View File

@@ -13,7 +13,8 @@
DIR* __fastcall__ opendir (const char*) DIR* __fastcall__ opendir (const char*)
{ {
unsigned char buf[32];
DIR* dir = 0; DIR* dir = 0;
DIR d; DIR d;
@@ -27,7 +28,7 @@ DIR* __fastcall__ opendir (const char*)
if (d.fd >= 0) { if (d.fd >= 0) {
/* Skip the disk header */ /* Skip the disk header */
if (_dirskip (32, &d)) { if (_dirread (&d, buf, 32)) {
/* Allocate memory for the DIR structure returned */ /* Allocate memory for the DIR structure returned */
dir = malloc (sizeof (*dir)); dir = malloc (sizeof (*dir));

View File

@@ -18,36 +18,34 @@
struct dirent* __fastcall__ readdir (register DIR* dir) struct dirent* __fastcall__ readdir (register DIR* dir)
{ {
static struct dirent entry;
register unsigned char* b; register unsigned char* b;
register unsigned char i; register unsigned char i;
unsigned char count; register unsigned char count;
unsigned char j;
unsigned char s; unsigned char s;
unsigned char j;
unsigned char buffer[0x40]; unsigned char buffer[0x40];
static struct dirent entry;
/* Remember the directory offset for this entry */ /* Remember the directory offset for this entry */
entry.d_off = dir->off; entry.d_off = dir->off;
/* Skip the basic line-link */ /* Skip the basic line-link */
if (!_dirskip (2, dir)) { if (!_dirread (dir, buffer, 2)) {
/* errno already set */ /* errno already set */
goto exit; goto exitpoint;
} }
dir->off += 2; dir->off += 2;
/* Read the number of blocks */ /* Read the number of blocks */
if (read (dir->fd, &entry.d_blocks, sizeof (entry.d_blocks)) != if (!_dirread (dir, &entry.d_blocks, sizeof (entry.d_blocks))) {
sizeof (entry.d_blocks)) { goto exitpoint;
goto error;
} }
/* Read the next file entry into the buffer */ /* Read the next file entry into the buffer */
for (count = 0, b = buffer; count < sizeof (buffer); ++count, ++b) { for (count = 0, b = buffer; count < sizeof (buffer); ++count, ++b) {
if (read (dir->fd, b, 1) != 1) { if (!_dirread1 (dir, b)) {
/* ### Check for EOF */ goto exitpoint;
goto error;
} }
if (*b == '\0') { if (*b == '\0') {
break; break;
@@ -59,7 +57,7 @@ struct dirent* __fastcall__ readdir (register DIR* dir)
* called again, read until end of directory. * called again, read until end of directory.
*/ */
if (count > 0 && buffer[0] == 'b') { if (count > 0 && buffer[0] == 'b') {
while (read (dir->fd, buffer, 1) == 1) ; while (_dirread1 (dir, buffer)) ;
return 0; return 0;
} }
@@ -120,10 +118,9 @@ struct dirent* __fastcall__ readdir (register DIR* dir)
++b; ++b;
} }
/* Something went wrong - terminating quote not found */ /* Something went wrong when parsing the directory entry */
error:
_errno = EIO; _errno = EIO;
exit: exitpoint:
return 0; return 0;
} }