]> git.sur5r.net Git - cc65/blob - libsrc/cbm/readdir.c
10593e21b0b4f00b36103841767d9b5750a4703d
[cc65] / libsrc / cbm / readdir.c
1 /*
2  * Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
3  */
4
5
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <dirent.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <cbm.h>
14 #include "dir.h"
15
16 #include <stdio.h>
17
18
19 struct dirent* __fastcall__ readdir (register DIR* dir)
20 {
21     static struct dirent entry;
22     register unsigned char* b;
23     register unsigned char i;
24     unsigned char count;
25     unsigned char j;
26     unsigned char s;
27     unsigned char buffer[0x40];
28
29
30     /* Remember the directory offset for this entry */
31     entry.d_off = dir->off;
32
33     /* Skip the basic line-link */
34     if (!_dirskip (2, dir)) {
35         /* errno already set */
36         goto exit;
37     }
38     dir->off += 2;
39
40     /* Read the number of blocks */
41     if (read (dir->fd, &entry.d_blocks, sizeof (entry.d_blocks)) !=
42         sizeof (entry.d_blocks)) {
43         goto error;
44     }
45
46     /* Read the next file entry into the buffer */
47     for (count = 0, b = buffer; count < sizeof (buffer); ++count, ++b) {
48         if (read (dir->fd, b, 1) != 1) {
49             /* ### Check for EOF */
50             goto error;
51         }
52         if (*b == '\0') {
53             break;
54         }
55     }
56
57     /* End of directory is reached if the buffer contains "blocks free". It is
58      * sufficient here to check for the leading 'b'. To avoid problems if we're
59      * called again, read until end of directory.
60      */
61     if (count > 0 && buffer[0] == 'b') {
62         while (read (dir->fd, buffer, 1) == 1) ;
63         return 0;
64     }
65
66     /* Bump the directory offset */
67     dir->off += count;
68
69     /* Parse the buffer for the filename and file type */
70     i = 0;
71     j = 0;
72     s = 0;
73     b = buffer;
74     while (i < count) {
75         switch (s) {
76
77             case 0:
78                 /* Searching for start of file name */
79                 if (*b == '"') {
80                     s = 1;
81                 }
82                 break;
83
84             case 1:
85                 /* Within file name */
86                 if (*b == '"') {
87                     entry.d_name[j] = '\0';
88                     entry.d_namlen = j;
89                     s = 2;
90                 } else if (j < sizeof (entry.d_name) - 1) {
91                     entry.d_name[j] = *b;
92                     ++j;
93                 }
94                 break;
95
96             case 2:
97                 /* Searching for file type */
98                 if (*b != ' ') {
99                     entry.d_type = _cbm_filetype (*b);
100                     if (*b == 'd') {
101                         /* May be DEL or DIR, check next char */
102                         s = 3;
103                     } else {
104                         /* Done */
105                         return &entry;
106                     }
107                 }
108                 break;
109
110             case 3:
111                 /* Distinguish DEL or DIR file type entries */
112                 switch (*b) {
113                     case 'e':                                   break;
114                     case 'i': entry.d_type = CBM_T_DIR;         break;
115                     default:  entry.d_type = CBM_T_OTHER;       break;
116                 }
117                 return &entry;
118         }
119         ++i;
120         ++b;
121     }
122
123     /* Something went wrong - terminating quote not found */
124 error:
125     _errno = EIO;
126 exit:
127     return 0;
128 }
129
130
131