X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libsrc%2Fcbm%2Fcbm_dir.c;h=8f31c502ad70a6ed0bf18931031161310d328d1a;hb=6a92d8b987ef98b97fced19533573c9e74b208a9;hp=bedbdaf6ace3e59a0caa08fb97e84c984d15af52;hpb=90f47ed0075aa9ee172336e5d0080f2acd423937;p=cc65 diff --git a/libsrc/cbm/cbm_dir.c b/libsrc/cbm/cbm_dir.c index bedbdaf6a..8f31c502a 100644 --- a/libsrc/cbm/cbm_dir.c +++ b/libsrc/cbm/cbm_dir.c @@ -1,77 +1,111 @@ -/* This is very simplified version of POSIX opendir(), readdir() and closedir() */ -/* for Commodore computers. */ -/* Created by Josef Soucek, 2003 E-mail:josef.soucek@ct.cz */ +/* 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 */ -/* Version 0.1 - 21.1.2003 */ -/* Tested with floppy drive and IDE64 devices */ -/* Not tested with messed (buggy) directory listing */ -/* Limits filenames to 16 chars (VICE supports more in directory listing) */ +/* 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 #include +#include -unsigned char __fastcall__ cbm_opendir (unsigned char lfn, unsigned char device) +/* 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, ...) { - unsigned char status; - if ((status = cbm_open (lfn, device, CBM_READ, "$")) == 0) { - if (cbm_k_chkin (lfn) == 0) { - if (cbm_k_basin () == 0x01) { /* Start address */ - if (cbm_k_basin () == 0x04) { - cbm_k_clrch (); - return 0; - } - } else { - cbm_close (lfn); - cbm_k_clrch (); - return 2; + 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 status; + 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; + unsigned char byte, i = 0; + unsigned char is_header = 0; + unsigned char rv = 1; - if (cbm_k_chkin (lfn) == 0) { - if (cbm_k_readst () == 0) { - cbm_k_basin (); /* 0x01, 0x01, next basic line */ - cbm_k_basin (); + if (!cbm_k_chkin(lfn)) { + if (!cbm_k_readst()) { + /* skip 2 bytes, next-BASIC-line pointer */ + cbm_k_basin(); + cbm_k_basin(); - byte = cbm_k_basin(); /* File-size */ - l_dirent->size = byte | ((cbm_k_basin()) << 8); + /* File-size or drive/partition number */ + l_dirent->size = cbm_k_basin() | (cbm_k_basin() << 8); byte = cbm_k_basin(); + switch (byte) { - if (byte == 'b') { /* "B" BLOCKS FREE. */ - while (cbm_k_readst () == 0) { /* Read until end */ - cbm_k_basin (); + /* "B" BLOCKS FREE. */ + case 'b': + /* Read until end; careless callers might call us again. */ + while (!cbm_k_readst()) { + cbm_k_basin(); } - cbm_k_clrch (); - return 2; /* END */ + rv = 2; /* EOF */ + goto ret_val; + + /* Reverse-text shows when this is the directory header. */ + case 0x12: /* RVS_ON */ + is_header = 1; } - if (byte != '\"') { - while (cbm_k_basin() != '\"') { - if (cbm_k_readst () != 0) { /* ### Included to prevent */ - cbm_k_clrch (); /* ### Endless loop */ - return 3; /* ### Should be probably removed */ - } /* ### */ + while (byte != '\"') { + /* prevent endless loop */ + if (cbm_k_readst()) { + rv = 3; + goto ret_val; } + byte = cbm_k_basin(); } - i = 0; - while ((byte = cbm_k_basin ()) != '\"') { - if (cbm_k_readst () != 0) { /* ### Included to prevent */ - cbm_k_clrch (); /* ### Endless loop */ - return 4; /* ### Should be probably removed */ - } /* ### */ + 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; @@ -80,65 +114,72 @@ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_d } l_dirent->name[i] = '\0'; - while ((byte=cbm_k_basin ()) == ' ') { - if (cbm_k_readst ()) { /* ### Included to prevent */ - cbm_k_clrch (); /* ### Endless loop */ - return 5; /* ### Should be probably removed */ - } /* ### */ - } + if (is_header) { + l_dirent->type = CBM_T_HEADER; - switch (byte) { - case 's': - l_dirent->type = CBM_T_SEQ; - break; - case 'p': - l_dirent->type = CBM_T_PRG; - break; - case 'u': - l_dirent->type = CBM_T_USR; - break; - case 'r': - l_dirent->type = CBM_T_REL; - break; - case 'c': - l_dirent->type = CBM_T_CBM; - break; - case 'd': - l_dirent->type = CBM_T_DIR; - break; - case 'v': - l_dirent->type = CBM_T_VRP; - break; - default: - l_dirent->type = CBM_T_OTHER; - } + /* Get the disk-format code. */ + i = 6; + do { + l_dirent->access = byte = cbm_k_basin(); + } while (--i != 0); - cbm_k_basin (); - cbm_k_basin (); + } 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(); + } - byte = cbm_k_basin (); + /* Determine the file type */ + l_dirent->type = _cbm_filetype (byte); - l_dirent->access = (byte == 0x3C)? CBM_A_RO : CBM_A_RW; + /* 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(); - if (byte != 0) { - while (cbm_k_basin() != 0) { - if (cbm_k_readst () != 0) { /* ### Included to prevent */ - cbm_k_clrch (); /* ### Endless loop */ - return 6; /* ### Should be probably removed */ - } /* ### */ + /* Locked files shouldn't be written. */ + if ((byte = cbm_k_basin()) == '<') { + l_dirent->access = (l_dirent->access == CBM_A_WO) + ? 0 : CBM_A_RO; } } - cbm_k_clrch (); - return 0; /* Line read successfuly */ + /* 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; } } - cbm_k_clrch (); - return 1; + +ret_val: + cbm_k_clrch(); + return rv; } -void __fastcall__ cbm_closedir( unsigned char lfn) + +void __fastcall__ cbm_closedir (unsigned char lfn) { cbm_close(lfn); }