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