Improvements to directory checking

This commit is contained in:
Bobbi Webber-Manners 2020-02-08 23:16:39 -05:00
parent d98fbac22b
commit c2f198e843

View File

@ -119,25 +119,17 @@ static uchar dowrite = 0;
static uchar doverbose = 0; static uchar doverbose = 0;
static char sortopts[5] = "n"; static char sortopts[5] = "n";
static uint stack; // DEBUG
//#define STACK(msg) asm {tsc; sta stack }; fputs(msg, stdout); fputs(" ", stdout); pr_int(stack); putchar('\n');
/* Prototypes */ /* Prototypes */
void prerr(char *s); void prerr(char *s);
void reverse(char *s);
void itoa(int n, char s[]);
void uitoa(uint n, char s[]);
void pr_int(int a);
void pr_uint(uint a);
void print_uint(uint i);
int readdiskblock(uchar device, uint blocknum, char *buf); int readdiskblock(uchar device, uint blocknum, char *buf);
int writediskblock(uchar device, uint blocknum, char *buf); int writediskblock(uchar device, uint blocknum, char *buf);
void fixcase(char *in, char *out, uchar minvers, uchar vers); void fixcase(char *in, char *out, uchar minvers, uchar vers, uchar len);
int readfreelist(uchar device); int readfreelist(uchar device);
int isfree(uint blk); int isfree(uint blk);
int saplingblocks(uchar device, uint keyblk, uint *blkcnt); int saplingblocks(uchar device, uint keyblk, uint *blkcnt);
int treeblocks(uchar device, uint keyblk, uint *blkcnt); int treeblocks(uchar device, uint keyblk, uint *blkcnt);
int subdirblocks(uchar device, uint keyblk, struct pd_dirent *ent,
uint blocknum, uint blkentries, uint *blkcnt);
int readdir(uint device, uint blocknum); int readdir(uint device, uint blocknum);
int cmp_name_asc(const void *a, const void *b); int cmp_name_asc(const void *a, const void *b);
int cmp_name_desc(const void *a, const void *b); int cmp_name_desc(const void *a, const void *b);
@ -159,75 +151,18 @@ void prerr(char *s) {
fputs("\n", stderr); fputs("\n", stderr);
} }
/* Reverse the characters of the string s */
void reverse(char *s) {
char buf[10];
int l = strlen(s);
for (int i=0; i<l; ++i)
buf[i] = s[i];
for (int i=0; i<l; ++i)
s[i] = buf[l-i-1];
}
/* Stolen from K&R 2nd Ed. pp 64 */
void itoa(int n, char s[]) {
int i, sign;
if ((sign = n) < 0)
n = -1;
i = 0;
do {
s[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
/* Unsigned verson of itoa() */
void uitoa(uint n, char s[]) {
int i;
i = 0;
do {
s[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
s[i] = '\0';
reverse(s);
}
/* Print an integer */
void pr_int(int a) {
char buf[10];
itoa(a, buf);
fputs(buf, stdout);
}
/* Print an unsigned integer */
void pr_uint(unsigned int a) {
char buf[10];
uitoa(a, buf);
fputs(buf, stdout);
}
/* /*
* Read block from disk using ProDOS call * Read block from disk using ProDOS call
* buf must point to buffer with at least 512 bytes * buf must point to buffer with at least 512 bytes
*/ */
int readdiskblock(uchar device, uint blocknum, char *buf) { int readdiskblock(uchar device, uint blocknum, char *buf) {
#ifdef DEBUG #ifdef DEBUG
fputs("Reading dev ", stdout); printf("Reading dev %2u block %5u\n", device, blocknum);
pr_int(device);
fputs(" block ", stdout);
pr_uint(blocknum);
putchar('\n');
#endif #endif
#ifdef CHECK #ifdef CHECK
if (flloaded) if (flloaded)
if (isfree(blocknum)) if (isfree(blocknum))
printf(" 1)Block %u is marked free!\n", printf(" Block %u is marked free!\n", blocknum);
blocknum);
#endif #endif
BlockRec br; BlockRec br;
br.blockDevNum = device; br.blockDevNum = device;
@ -248,11 +183,7 @@ int readdiskblock(uchar device, uint blocknum, char *buf) {
*/ */
int writediskblock(uchar device, uint blocknum, char *buf) { int writediskblock(uchar device, uint blocknum, char *buf) {
#ifdef DEBUG #ifdef DEBUG
fputs("Writing dev ", stdout); printf("Writing dev %2u block %5u\n", device, blocknum);
pr_int(device);
fputs(" block ", stdout);
pr_uint(blocknum);
putchar('\n');
#endif #endif
DIORecGS dr; DIORecGS dr;
dr.pCount = 6; dr.pCount = 6;
@ -272,11 +203,12 @@ int writediskblock(uchar device, uint blocknum, char *buf) {
* as a bitmap representing which characters are upper and which are * as a bitmap representing which characters are upper and which are
* lowercase * lowercase
*/ */
void fixcase(char *in, char *out, uchar minvers, uchar vers) { void fixcase(char *in, char *out, uchar minvers, uchar vers, uchar len) {
uchar idx = 0; uchar idx = 0;
if (!(vers&0x80)) { if (!(vers & 0x80)) {
for (idx=0; idx<NMLEN; ++idx) for (idx=0; idx<NMLEN; ++idx)
out[idx] = in[idx]; out[idx] = in[idx];
out[len] = '\0';
return; return;
} }
vers <<= 1; vers <<= 1;
@ -288,6 +220,7 @@ void fixcase(char *in, char *out, uchar minvers, uchar vers) {
out[idx++] = ((minvers&0x80) ? tolower(in[idx]) : in[idx]); out[idx++] = ((minvers&0x80) ? tolower(in[idx]) : in[idx]);
minvers <<= 1; minvers <<= 1;
} }
out[len] = '\0';
} }
/* /*
@ -420,7 +353,7 @@ int saplingblocks(uchar device, uint keyblk, uint *blkcnt) {
uint p = (uchar)buf[i] + 256U * (uchar)buf[i+256]; uint p = (uchar)buf[i] + 256U * (uchar)buf[i+256];
if (p) { if (p) {
if (isfree(p)) if (isfree(p))
printf(" 2)Block %u is marked free!\n", p); printf(" Data block %u is marked free!\n", p);
++(*blkcnt); ++(*blkcnt);
} }
} }
@ -440,7 +373,7 @@ int treeblocks(uchar device, uint keyblk, uint *blkcnt) {
uint p = (uchar)buf2[i] + 256U * (uchar)buf2[i+256]; uint p = (uchar)buf2[i] + 256U * (uchar)buf2[i+256];
if (p) { if (p) {
if (isfree(p)) if (isfree(p))
printf(" 4)Block %u is marked free!\n", p); printf(" Idx block %u is marked free!\n", p);
uint b; uint b;
if (saplingblocks(device, p, &b) == 0) if (saplingblocks(device, p, &b) == 0)
*blkcnt += b; *blkcnt += b;
@ -451,6 +384,48 @@ int treeblocks(uchar device, uint keyblk, uint *blkcnt) {
return 0; return 0;
} }
/*
* Count the blocks in a subdirectory
*/
int subdirblocks(uchar device, uint keyblk, struct pd_dirent *ent,
uint blocknum, uint blkentries, uint *blkcnt) {
if (readdiskblock(device, keyblk, buf) == -1) {
printf(" Error reading keyblock %u\n", keyblk);
return -1;
}
*blkcnt = 1;
struct pd_dirhdr *hdr = (struct pd_dirhdr*)(buf + PTRSZ);
uchar parentry = hdr->parentry;
uchar parentlen = hdr->parentlen;
uint parblk = hdr->parptr[0] + 256U * hdr->parptr[1];
if (parblk != blocknum) {
printf(" Bad parent block %u", parblk);
printf(", should be %u\n", blocknum);
}
if (parentry != blkentries) {
printf(" Bad parent block entry %u", parentry);
printf(", should be %u\n", blkentries);
}
if (parentlen != 0x27)
puts(" Bad parent entry length");
char *dirname = buf + 0x05;
if (strncmp(dirname, ent->name, NMLEN))
puts(" Subdirectory name mismatch");
blocknum = buf[0x02] + 256U * buf[0x03];
while (blocknum) {
if (readdiskblock(device, blocknum, buf) == -1) {
printf(" Error reading dir block %u\n", blocknum);
return -1;
}
++(*blkcnt);
blocknum = buf[0x02] + 256U * buf[0x03];
}
return 0;
}
/* /*
* Read a directory, store the raw directory blocks in a linked list * Read a directory, store the raw directory blocks in a linked list
* and build filelist[] in preparation for sorting. * and build filelist[] in preparation for sorting.
@ -481,23 +456,19 @@ int readdir(uint device, uint blocknum) {
entperblk = hdr->entperblk; entperblk = hdr->entperblk;
uint filecount = hdr->filecnt[0] + 256U * hdr->filecnt[1]; uint filecount = hdr->filecnt[0] + 256U * hdr->filecnt[1];
static char namebuf[NMLEN+1];
fixcase(hdr->name, namebuf,
hdr->vers, hdr->minvers, hdr->typ_len & 0x0f);
puts("---------------------------------------------------------");
printf("Directory %s (%d entries)\n", namebuf, filecount);
puts("---------------------------------------------------------");
/* Copy pointers and header to sorteddata[], zero the rest */ /* Copy pointers and header to sorteddata[], zero the rest */
bzero(curblk->sorteddata, BLKSZ); bzero(curblk->sorteddata, BLKSZ);
memcpy(curblk->sorteddata, curblk->data, PTRSZ + entsz); memcpy(curblk->sorteddata, curblk->data, PTRSZ + entsz);
#ifdef DEBUG
fputs("entsz=", stdout);
pr_uint(entsz);
putchar('\n');
fputs("entperblk=", stdout);
pr_uint(entperblk);
putchar('\n');
fputs("filecount=", stdout);
pr_uint(filecount);
putchar('\n');
#endif
#ifdef CHECK #ifdef CHECK
if (entsz != 0x27) { if (entsz != 0x27) {
puts("Error - bad entry size"); puts("Error - bad entry size");
@ -512,14 +483,36 @@ int readdir(uint device, uint blocknum) {
uchar blkentries = 2; uchar blkentries = 2;
uchar entries = 0; uchar entries = 0;
static char namebuf[NMLEN];
while (1) { while (1) {
struct pd_dirent *ent = (struct pd_dirent*)(curblk->data + idx); struct pd_dirent *ent = (struct pd_dirent*)(curblk->data + idx);
if (ent->typ_len != 0) { if (ent->typ_len != 0) {
fixcase(ent->name, namebuf, ent->vers, ent->minvers); fixcase(ent->name, namebuf,
ent->vers, ent->minvers, ent->typ_len & 0x0f);
#ifdef CHECK #ifdef CHECK
printf("File: %s\n", namebuf); switch (ent->typ_len & 0xf0) {
case 0x10:
fputs("Seed ", stdout);
break;
case 0x20:
fputs("Sapl ", stdout);
break;
case 0x30:
fputs("Tree ", stdout);
break;
case 0x40:
fputs("Pasc ", stdout);
break;
case 0x50:
fputs("Fork ", stdout);
break;
case 0xd0:
fputs("Dir ", stdout);
break;
default:
fputs("???? ", stdout);
break;
}
puts(namebuf);
#endif #endif
for (uchar i=0; i<NMLEN+1; ++i) for (uchar i=0; i<NMLEN+1; ++i)
filelist[numfiles].name[i] = '\0'; filelist[numfiles].name[i] = '\0';
@ -543,36 +536,8 @@ int readdir(uint device, uint blocknum) {
switch (ent->typ_len & 0xf0) { switch (ent->typ_len & 0xf0) {
case 0xd0: case 0xd0:
/* Subdirectory */ /* Subdirectory */
if (readdiskblock(device, keyblk, buf) == -1) { subdirblocks(device, keyblk, ent,
printf(" Error reading keyblock %u\n", blocknum, blkentries, &count);
keyblk);
return 1;
}
hdr = (struct pd_dirhdr*)(buf + PTRSZ);
uchar parentry = hdr->parentry;
uchar parentlen = hdr->parentlen;
uint parblk =
hdr->parptr[0] + 256U * hdr->parptr[1];
if (parblk != blocknum) {
printf(" Bad parent block %u", parblk);
printf(", should be %u\n", blocknum);
}
if (parentry != blkentries) {
printf(" Bad parent block entry %u",
parentry);
printf(", should be %u\n", blkentries);
}
if (parentlen != 0x27)
puts(" Bad parent entry length");
char *dirname = buf + 0x05;
if (strncmp(dirname, ent->name, NMLEN))
puts(" Subdirectory name mismatch");
//
// TODO: COUNT DIRECTORY BLOCKS
//
count = 0;
break; break;
case 0x10: case 0x10:
/* Seedling */ /* Seedling */
@ -592,34 +557,33 @@ int readdir(uint device, uint blocknum) {
count = 0; count = 0;
break; break;
default: default:
printf( "%s: unexpected storage type 0x%x\n", printf(" %s: unexpected storage type 0x%x\n",
namebuf, ent->typ_len & 0xf0); namebuf, ent->typ_len & 0xf0);
count = 0; count = 0;
} }
if (blks != count) { if (blks != count) {
if (count != 0) { if (count != 0) {
printf(" Size %u is incorrect", blks); printf(" Size %u is incorrect", blks);
printf(", should be %u\n", blkcnt); printf(", should be %u\n", count);
} }
} }
#endif #endif
++numfiles; ++numfiles;
if (numfiles == MAXFILES) { if (numfiles == MAXFILES) {
puts("Too many files!"); puts("** Too many files! **");
return 1; return 1;
} }
++entries; ++entries;
} }
if (blkentries == entperblk) { if (blkentries == entperblk) {
blocknum = blocknum = curblk->data[0x02] + 256U*curblk->data[0x03];
curblk->data[0x02] + 256U*curblk->data[0x03];
if (blocknum == 0) { if (blocknum == 0) {
break; break;
} }
curblk->next = curblk->next =
(struct block*)malloc(sizeof(struct block)); (struct block*)malloc(sizeof(struct block));
if (!curblk->next) { if (!curblk->next) {
puts("Unable to allocate memory"); puts("** Unable to allocate memory **");
return 1; return 1;
} }
curblk = curblk->next; curblk = curblk->next;
@ -628,7 +592,7 @@ int readdir(uint device, uint blocknum) {
++blkcnt; ++blkcnt;
if ( if (
readdiskblock(device, blocknum, curblk->data) == -1) { readdiskblock(device, blocknum, curblk->data) == -1) {
printf("Error reading dir block %d\n", blkcnt); printf(" Error reading dir block %d\n", blkcnt);
return 1; return 1;
} }
/* Copy ptrs to sorteddata[], zero the rest */ /* Copy ptrs to sorteddata[], zero the rest */
@ -754,7 +718,7 @@ void sortlist(char s) {
* Print the file info stored in filelist[] * Print the file info stored in filelist[]
*/ */
void printlist(void) { void printlist(void) {
puts("----------------------------------------------------"); puts("---------------------------------------------------------");
printf("numfiles=%u\n", numfiles); printf("numfiles=%u\n", numfiles);
puts("Dirblk Entry Type : Name"); puts("Dirblk Entry Type : Name");
for(uint i=0; i<numfiles; ++i) for(uint i=0; i<numfiles; ++i)
@ -763,7 +727,7 @@ void printlist(void) {
filelist[i].entrynum, filelist[i].entrynum,
filelist[i].type, filelist[i].type,
filelist[i].name); filelist[i].name);
puts("----------------------------------------------------"); puts("---------------------------------------------------------");
} }
/* /*
@ -773,16 +737,8 @@ void printlist(void) {
void copyent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device) { void copyent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device) {
if (doverbose) { if (doverbose) {
fputs(" from blk ", stdout); printf(" from dirblk %03u entry %02u\n", srcblk, srcent);
pr_uint(srcblk); printf(" to dirblk %03u entry %02u\n", dstblk, dstent);
fputs(" entry ", stdout);
pr_uint(srcent);
putchar('\n');
fputs(" to blk ", stdout);
pr_uint(dstblk);
fputs(" entry ", stdout);
pr_uint(dstent);
putchar('\n');
} }
struct block *source = blocks; struct block *source = blocks;