]> git.sur5r.net Git - cc65/blob - libsrc/cbm/cbm_dir.c
Moved most of the file type detection from cbm_dir.c into a new function
[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 <cbm.h>
17 #include <errno.h>
18
19
20
21 /* Opens directory listing.
22 ** Returns 0 if openning directory was successful;
23 ** otherwise, an error-code corresponding to cbm_open().
24 */
25 unsigned char __fastcall__ cbm_opendir (unsigned char lfn, unsigned char device)
26 {
27     if (cbm_open (lfn, device, CBM_READ, "$") == 0) {
28         if ((_oserror = cbm_k_chkin (lfn)) == 0) {
29             /* Ignore start address */
30             cbm_k_basin();
31             cbm_k_basin();
32             cbm_k_clrch();
33             if (cbm_k_readst()) {
34                 cbm_close(lfn);
35                 _oserror = 4;           /* directory cannot be read */
36             }
37         }
38     }
39     return _oserror;
40 }
41
42
43
44 /* Reads one directory line into cbm_dirent structure.
45 ** Returns 0 if reading directory-line was successful.
46 ** Returns non-zero if reading directory failed, or no more file-names to read.
47 ** Returns 2 on last line.  Then, l_dirent->size = the number of "blocks free."
48 */
49 unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_dirent* l_dirent)
50 {
51     unsigned char byte, i = 0;
52     unsigned char is_header = 0;
53     unsigned char rv = 1;
54
55     if (!cbm_k_chkin(lfn)) {
56         if (!cbm_k_readst()) {
57             /* skip 2 bytes, next-BASIC-line pointer */
58             cbm_k_basin();
59             cbm_k_basin();
60
61             /* File-size or drive/partition number */
62             l_dirent->size = cbm_k_basin() | (cbm_k_basin() << 8);
63
64             byte = cbm_k_basin();
65             switch (byte) {
66
67                 /* "B" BLOCKS FREE. */
68               case 'b':
69                 /* Read until end; careless callers might call us again. */
70                 while (!cbm_k_readst()) {
71                     cbm_k_basin();
72                 }
73                 rv = 2; /* EOF */
74                 goto ret_val;
75
76                 /* Reverse-text shows when this is the directory header. */
77               case 0x12:  /* RVS_ON */
78                 is_header = 1;
79             }
80
81             while (byte != '\"') {
82                 /* prevent endless loop */
83                 if (cbm_k_readst()) {
84                     rv = 3;
85                     goto ret_val;
86                 }
87                 byte = cbm_k_basin();
88             }
89
90             while ((byte = cbm_k_basin()) != '\"') {
91                 /* prevent endless loop */
92                 if (cbm_k_readst()) {
93                     rv = 4;
94                     goto ret_val;
95                 }
96
97                 if (i < sizeof (l_dirent->name) - 1) {
98                     l_dirent->name[i] = byte;
99                     ++i;
100                 }
101             }
102             l_dirent->name[i] = '\0';
103
104             if (is_header) {
105                 l_dirent->type = CBM_T_HEADER;
106
107                 /* Get the disk-format code. */
108                 i = 6;
109                 do {
110                     l_dirent->access = byte = cbm_k_basin();
111                 } while (--i != 0);
112
113             } else {
114                 /* Go to the file-type column. */
115                 while ((byte = cbm_k_basin()) == ' ') {
116                     /* prevent endless loop */
117                     if (cbm_k_readst()) {
118                         rv = 5;
119                         goto ret_val;
120                     }
121                 }
122
123                 l_dirent->access = CBM_A_RW;
124
125                 /* "Splat" files shouldn't be read. */
126                 if (byte == '*') {
127                     l_dirent->access = CBM_A_WO;
128                     byte = cbm_k_basin();
129                 }
130
131                 /* Determine the file type */
132                 l_dirent->type = _cbm_filetype (byte);
133
134                 /* Notice whether it's a directory or a deleted file. */
135                 if (cbm_k_basin() == 'i' && byte == 'd') {
136                     l_dirent->type = CBM_T_DIR;
137                 }
138                 cbm_k_basin();
139
140                 /* Locked files shouldn't be written. */
141                 if ((byte = cbm_k_basin()) == '<') {
142                     l_dirent->access = (l_dirent->access == CBM_A_WO)
143                         ? 0 : CBM_A_RO;
144                 }
145             }
146
147             /* Read to the end of the line. */
148             while (byte != 0) {
149                 /* prevent endless loop */
150                 if (cbm_k_readst()) {
151                     rv = 6;
152                     goto ret_val;
153                 }
154                 byte = cbm_k_basin();
155             }
156
157             rv = 0;
158             goto ret_val;
159         }
160     }
161
162 ret_val:
163     cbm_k_clrch();
164     return rv;
165 }
166
167
168
169 void __fastcall__ cbm_closedir (unsigned char lfn)
170 {
171     cbm_close(lfn);
172 }
173
174