mirror of
https://github.com/bobbimanners/GNO-Extras.git
synced 2024-06-12 06:29:28 +00:00
Improvements to directory checking
This commit is contained in:
parent
d98fbac22b
commit
c2f198e843
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user