1 /* This is a very simplified version of the POSIX opendir(), */
2 /* readdir(), and closedir() -- for Commodore computers. */
3 /* Created by Josef Soucek, 2003. E-mail: josef.soucek@ct.cz */
4
5 /* 2003-01-21 -- Version 0.1 */
6 /* 2009-10-10 -- Version 0.3 */
7 /* 2011-04-07 -- Version 0.4, groepaz */
8 /* 2011-04-14 -- Version 0.5, Greg King */
9
10 /* Tested with floppy-drive and IDE64 devices. */
11 /* Not tested with messed (buggy) directory listings. */
12 /* Limits filenames to 16 chars. (VICE supports more */
13 /* in directory listings). */
14
15
16 #include <stdarg.h>
17 #include <cbm.h>
18 #include <errno.h>
19
20
21
22 /* Opens directory listing. Returns 0 if opening directory was successful;
23 ** otherwise, an error-code corresponding to cbm_open(). As an optional
24 ** argument, the name of the directory may be passed to the function. If
25 ** no explicit name is specified, "$" is used.
26 */
cbm_opendir(unsigned char lfn,unsigned char device,...)27 unsigned char cbm_opendir (unsigned char lfn, unsigned char device, ...)
28 {
29 va_list ap;
30 const char* name = "$";
31
32 /* The name used in cbm_open may optionally be passed */
33 if (__argsize__ == 4) {
34 va_start (ap, device);
35 name = va_arg (ap, const char*);
36 va_end (ap);
37 }
38
39 /* Open the directory */
40 if (cbm_open (lfn, device, CBM_READ, name) == 0) {
41 if ((_oserror = cbm_k_chkin (lfn)) == 0) {
42 /* Ignore start address */
43 cbm_k_basin();
44 cbm_k_basin();
45 cbm_k_clrch();
46 if (cbm_k_readst()) {
47 cbm_close(lfn);
48 _oserror = 4; /* directory cannot be read */
49 }
50 }
51 }
52 return _oserror;
53 }
54
55
56
57 /* Reads one directory line into cbm_dirent structure.
58 ** Returns 0 if reading directory-line was successful.
59 ** Returns non-zero if reading directory failed, or no more file-names to read.
60 ** Returns 2 on last line. Then, l_dirent->size = the number of "blocks free."
61 */
cbm_readdir(unsigned char lfn,register struct cbm_dirent * l_dirent)62 unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_dirent* l_dirent)
63 {
64 unsigned char byte, i = 0;
65 unsigned char is_header = 0;
66 unsigned char rv = 1;
67
68 if (!cbm_k_chkin(lfn)) {
69 if (!cbm_k_readst()) {
70 /* skip 2 bytes, next-BASIC-line pointer */
71 cbm_k_basin();
72 cbm_k_basin();
73
74 /* File-size or drive/partition number */
75 l_dirent->size = cbm_k_basin() | (cbm_k_basin() << 8);
76
77 byte = cbm_k_basin();
78 switch (byte) {
79
80 /* "B" BLOCKS FREE. */
81 case 'b':
82 /* Read until end; careless callers might call us again. */
83 while (!cbm_k_readst()) {
84 cbm_k_basin();
85 }
86 rv = 2; /* EOF */
87 goto ret_val;
88
89 /* Reverse-text shows when this is the directory header. */
90 case 0x12: /* RVS_ON */
91 is_header = 1;
92 }
93
94 while (byte != '\"') {
95 /* prevent endless loop */
96 if (cbm_k_readst()) {
97 rv = 3;
98 goto ret_val;
99 }
100 byte = cbm_k_basin();
101 }
102
103 while ((byte = cbm_k_basin()) != '\"') {
104 /* prevent endless loop */
105 if (cbm_k_readst()) {
106 rv = 4;
107 goto ret_val;
108 }
109
110 if (i < sizeof (l_dirent->name) - 1) {
111 l_dirent->name[i] = byte;
112 ++i;
113 }
114 }
115 l_dirent->name[i] = '\0';
116
117 if (is_header) {
118 l_dirent->type = CBM_T_HEADER;
119
120 /* Get the disk-format code. */
121 i = 6;
122 do {
123 l_dirent->access = byte = cbm_k_basin();
124 } while (--i != 0);
125
126 } else {
127 /* Go to the file-type column. */
128 while ((byte = cbm_k_basin()) == ' ') {
129 /* prevent endless loop */
130 if (cbm_k_readst()) {
131 rv = 5;
132 goto ret_val;
133 }
134 }
135
136 l_dirent->access = CBM_A_RW;
137
138 /* "Splat" files shouldn't be read. */
139 if (byte == '*') {
140 l_dirent->access = CBM_A_WO;
141 byte = cbm_k_basin();
142 }
143
144 /* Determine the file type */
145 l_dirent->type = _cbm_filetype (byte);
146
147 /* Notice whether it's a directory or a deleted file. */
148 if (cbm_k_basin() == 'i' && byte == 'd') {
149 l_dirent->type = CBM_T_DIR;
150 }
151 cbm_k_basin();
152
153 /* Locked files shouldn't be written. */
154 if ((byte = cbm_k_basin()) == '<') {
155 l_dirent->access = (l_dirent->access == CBM_A_WO)
156 ? 0 : CBM_A_RO;
157 }
158 }
159
160 /* Read to the end of the line. */
161 while (byte != 0) {
162 /* prevent endless loop */
163 if (cbm_k_readst()) {
164 rv = 6;
165 goto ret_val;
166 }
167 byte = cbm_k_basin();
168 }
169
170 rv = 0;
171 goto ret_val;
172 }
173 }
174
175 ret_val:
176 cbm_k_clrch();
177 return rv;
178 }
179
180
181
cbm_closedir(unsigned char lfn)182 void __fastcall__ cbm_closedir (unsigned char lfn)
183 {
184 cbm_close(lfn);
185 }
186
187
188