]> git.sur5r.net Git - cc65/blob - libsrc/cbm/cbm_dir.c
Improved cbm_dir routines by Thomas Giesel.
[cc65] / libsrc / cbm / cbm_dir.c
1 /* This is very simplified version of POSIX opendir(), readdir() and closedir() */
2 /* for Commodore computers.                                                     */
3 /* Created by Josef Soucek, 2003    E-mail:josef.soucek@ct.cz                   */
4
5 /* Version 0.1 - 21.1.2003 */
6 /* Tested with floppy drive and IDE64 devices                                   */
7 /* Not tested with messed (buggy) directory listing                             */
8 /* Limits filenames to 16 chars (VICE supports more in directory listing)       */
9
10
11
12 #include <cbm.h>
13
14
15
16 unsigned char __fastcall__ cbm_opendir (unsigned char lfn, unsigned char device)
17 {
18     unsigned char status;
19     if ((status = cbm_open (lfn, device, CBM_READ, "$")) == 0) {
20         if (cbm_k_chkin (lfn) == 0) {
21             if (cbm_k_basin () == 0x01) {         /* Start address */
22                 if (cbm_k_basin () == 0x04) {
23                     cbm_k_clrch ();
24                     return 0;
25                 }
26             } else {
27                 cbm_close (lfn);
28                 cbm_k_clrch ();
29                 return 2;
30             }
31         }
32     }
33     return status;
34 }
35
36
37
38 unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_dirent* l_dirent)
39 {
40     unsigned char byte, i;
41     unsigned char rv;
42     unsigned char is_header;
43     static const unsigned char types[] = { 
44         CBM_T_OTHER, CBM_T_OTHER, CBM_T_CBM,   CBM_T_DIR,   /* a b c d */
45         CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, /* e f g h */
46         CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, /* i j k l */
47         CBM_T_OTHER, CBM_T_OTHER, CBM_T_OTHER, CBM_T_PRG,   /* m n o p */
48         CBM_T_OTHER, CBM_T_REL,   CBM_T_SEQ,   CBM_T_OTHER, /* q r s t */
49         CBM_T_USR,   CBM_T_VRP                              /* u v     */
50     };
51
52     rv = 1;
53     is_header = 0;
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 */
62             l_dirent->size = cbm_k_basin() | ((cbm_k_basin()) << 8);
63
64             byte = cbm_k_basin();
65
66             /* "B" BLOCKS FREE. */
67             if (byte == 'b') {
68                 /* Read until end, careless callers may call us again */
69                 while (!cbm_k_readst()) {
70                     cbm_k_basin();
71                 }
72                 rv = 2; /* EOF */
73                 goto ret_val;
74             }
75
76             /* reverse text shows that this is the directory header */
77             if (byte == 0x12) { /* RVS_ON */
78                 is_header = 1;
79             }
80
81             while (byte != '\"') {
82                 byte = cbm_k_basin();
83                 /* prevent endless loop */
84                 if (cbm_k_readst()) {
85                     rv = 3;
86                     goto ret_val;
87                 }
88             }
89
90             i = 0;
91             while ((byte = cbm_k_basin()) != '\"') {
92                 /* prevent endless loop */
93                 if (cbm_k_readst()) {
94                     rv = 4;
95                     goto ret_val;
96                 }
97
98                 if (i < sizeof (l_dirent->name) - 1) {
99                     l_dirent->name[i] = byte;
100                     ++i;
101                 }
102             }
103             l_dirent->name[i] = '\0';
104
105             while ((byte = cbm_k_basin()) == ' ') {
106                 /* prevent endless loop */
107                 if (cbm_k_readst()) {
108                     rv = 5;
109                     goto ret_val;
110                 }
111             }
112
113             if (is_header) {
114                 l_dirent->type = CBM_T_HEADER;
115             } else {
116                 if (byte >= 'a' && byte < 'a' + sizeof(types)) {
117                     l_dirent->type = types[byte - 'a'];
118                 } else {
119                     l_dirent->type = CBM_T_OTHER;
120                 }
121
122                 cbm_k_basin();
123                 cbm_k_basin();
124
125                 byte = cbm_k_basin();
126
127                 l_dirent->access = (byte == 0x3C)? CBM_A_RO : CBM_A_RW;
128             }
129
130             /* read to end of line */
131             while (byte != 0) {
132                 byte = cbm_k_basin();
133                 /* prevent endless loop */
134                 if (cbm_k_readst()) {
135                     rv = 6;
136                     goto ret_val;
137                 }
138             }
139
140             rv = 0;
141             goto ret_val;
142         }
143     }
144
145 ret_val:
146     cbm_k_clrch();
147     return rv;
148 }
149
150
151 void __fastcall__ cbm_closedir( unsigned char lfn)
152 {
153     cbm_close(lfn);
154 }
155
156