]> git.sur5r.net Git - cc65/blob - libsrc/cbm/cbm_dir.c
Remove trailings spaces from CBM-related asm files
[cc65] / libsrc / cbm / cbm_dir.c
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 */
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 */
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
182 void __fastcall__ cbm_closedir (unsigned char lfn)
183 {
184     cbm_close(lfn);
185 }
186
187