-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.
*/
.global _opendir
.global _closedir
.global _readdir
- .global _telldir
- .global _rewinddir
+; .global _telldir
+; .global _rewinddir
+ .global __dirread
+ .global __dirread1
.global __dirskip
+
;
; 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 #<EIO
sta __errno
- stx __errno+1
- txa ; A=X=0
- beq L1 ; Branch always
+ stx __errno+1 ; X is zero
+ bne L1 ; Branch always
-.endproc
DIR* __fastcall__ opendir (const char*)
-{
+{
+ unsigned char buf[32];
DIR* dir = 0;
DIR d;
if (d.fd >= 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));
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;
* 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;
}
++b;
}
- /* Something went wrong - terminating quote not found */
-error:
+ /* Something went wrong when parsing the directory entry */
_errno = EIO;
-exit:
+exitpoint:
return 0;
}