mirror of
https://github.com/bobbimanners/ProDOS-Utils.git
synced 2024-06-27 12:29:28 +00:00
Trimming of directory blocks is working now
This commit is contained in:
parent
fdc7f30b82
commit
7a4fabd990
169
sortdir.c
169
sortdir.c
|
@ -3,10 +3,11 @@
|
||||||
*
|
*
|
||||||
* Bobbi January-June 2020
|
* Bobbi January-June 2020
|
||||||
*
|
*
|
||||||
* TODO: Maybe no-op sort is useful after all?
|
|
||||||
* TODO: Need code to write out modified freelist if there are fixes
|
|
||||||
* TODO: Get both ProDOS-8 and GNO versions to build from this source
|
|
||||||
* TODO: Trimming unused directory blocks
|
* TODO: Trimming unused directory blocks
|
||||||
|
* TODO: Don't trim volume directory to <4 blocks
|
||||||
|
* TODO: *** When trimming dirs fix EOF in directory header ***
|
||||||
|
* TODO: no-op sort is useful after all - reinstate it
|
||||||
|
* TODO: Get both ProDOS-8 and GNO versions to build from this source
|
||||||
*
|
*
|
||||||
* Revision History
|
* Revision History
|
||||||
* v0.50 Initial alpha release on GitHub. Ported from GNO/ME version.
|
* v0.50 Initial alpha release on GitHub. Ported from GNO/ME version.
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
* v0.76 Fix bug - checkfreeandused() not traversing all freelist.
|
* v0.76 Fix bug - checkfreeandused() not traversing all freelist.
|
||||||
* v0.77 Implemented zeroblock() for ProDOS-8.
|
* v0.77 Implemented zeroblock() for ProDOS-8.
|
||||||
* v0.78 Improved error handling when too many files to sort.
|
* v0.78 Improved error handling when too many files to sort.
|
||||||
|
* v0.79 Trim unused directory blocks after sorting. Write freelist to disk.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#pragma debug 9
|
//#pragma debug 9
|
||||||
|
@ -133,9 +135,9 @@ struct pd_dirent {
|
||||||
*/
|
*/
|
||||||
struct block {
|
struct block {
|
||||||
#ifdef AUXMEM
|
#ifdef AUXMEM
|
||||||
char *data; /* Original contents of block */
|
char *data; /* Contents of block (pointer to auxmem) */
|
||||||
#else
|
#else
|
||||||
char data[BLKSZ]; /* Original contents of block */
|
char data[BLKSZ]; /* Contents of block */
|
||||||
#endif
|
#endif
|
||||||
uint blocknum; /* Block number on disk */
|
uint blocknum; /* Block number on disk */
|
||||||
struct block *next;
|
struct block *next;
|
||||||
|
@ -198,6 +200,7 @@ static uchar *freelist; /* Free-list bitmap */
|
||||||
static uchar *usedlist; /* Bit map of used blocks */
|
static uchar *usedlist; /* Bit map of used blocks */
|
||||||
static uchar flloaded = 0; /* 1 if free-list has been loaded */
|
static uchar flloaded = 0; /* 1 if free-list has been loaded */
|
||||||
static uint flsize; /* Size of free-list in blocks */
|
static uint flsize; /* Size of free-list in blocks */
|
||||||
|
static uint flblk; /* Block num for start of freelist */
|
||||||
#endif
|
#endif
|
||||||
static char currdir[NMLEN+1]; /* Name of current directory */
|
static char currdir[NMLEN+1]; /* Name of current directory */
|
||||||
static struct block *blocks = NULL; /* List of directory disk blocks */
|
static struct block *blocks = NULL; /* List of directory disk blocks */
|
||||||
|
@ -291,9 +294,8 @@ uint askfix(void);
|
||||||
int readfreelist(uchar device);
|
int readfreelist(uchar device);
|
||||||
int isfree(uint blk);
|
int isfree(uint blk);
|
||||||
int isused(uint blk);
|
int isused(uint blk);
|
||||||
void markfree(uint blk);
|
|
||||||
void marknotfree(uint blk);
|
|
||||||
void markused(uint blk);
|
void markused(uint blk);
|
||||||
|
void marknotused(uint blk);
|
||||||
void checkblock(uint blk, char *msg);
|
void checkblock(uint blk, char *msg);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CHECK
|
#ifdef CHECK
|
||||||
|
@ -328,8 +330,9 @@ void printlist(void);
|
||||||
uint blockidxtoblocknum(uint idx);
|
uint blockidxtoblocknum(uint idx);
|
||||||
void copydirblkptrs(uint blkidx);
|
void copydirblkptrs(uint blkidx);
|
||||||
void copydirent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device);
|
void copydirent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device);
|
||||||
void sortblock(uint device, uint dstblk);
|
uchar sortblock(uint device, uint dstblk);
|
||||||
int writedir(uchar device);
|
uchar writedir(uchar device);
|
||||||
|
uchar writefreelist(uchar device);
|
||||||
void freeblocks(void);
|
void freeblocks(void);
|
||||||
void subtitle(char *s);
|
void subtitle(char *s);
|
||||||
void interactive(void);
|
void interactive(void);
|
||||||
|
@ -782,15 +785,17 @@ void writedatetime(uchar pd25, struct datetime *dt, uchar time[4]) {
|
||||||
uint askfix(void) {
|
uint askfix(void) {
|
||||||
if (strlen(fixopts) == 0)
|
if (strlen(fixopts) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
fputs(": Fix (y/n)? ", stdout);
|
||||||
switch (fixopts[0]) {
|
switch (fixopts[0]) {
|
||||||
case '?':
|
case '?':
|
||||||
fputs("Fix (y/n)? ", stdout);
|
|
||||||
if (tolower(getchar()) == 'y')
|
if (tolower(getchar()) == 'y')
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
case 'y':
|
case 'a':
|
||||||
|
fputs("y", stdout);
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
|
fputs("n", stdout);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -801,7 +806,7 @@ uint askfix(void) {
|
||||||
* Read the free list
|
* Read the free list
|
||||||
*/
|
*/
|
||||||
int readfreelist(uchar device) {
|
int readfreelist(uchar device) {
|
||||||
uint i, flblk;
|
uint i, f;
|
||||||
char *p;
|
char *p;
|
||||||
#ifdef AUXMEM
|
#ifdef AUXMEM
|
||||||
bzero(buf, BLKSZ);
|
bzero(buf, BLKSZ);
|
||||||
|
@ -819,7 +824,7 @@ int readfreelist(uchar device) {
|
||||||
err(NONFATAL, err_rdblk1, 2);
|
err(NONFATAL, err_rdblk1, 2);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
flblk = buf[0x27] + 256U * buf[0x28];
|
flblk = f = buf[0x27] + 256U * buf[0x28];
|
||||||
totblks = buf[0x29] + 256U * buf[0x2a];
|
totblks = buf[0x29] + 256U * buf[0x2a];
|
||||||
if (doverbose)
|
if (doverbose)
|
||||||
printf("Volume has %u blocks\n", totblks);
|
printf("Volume has %u blocks\n", totblks);
|
||||||
|
@ -828,11 +833,11 @@ int readfreelist(uchar device) {
|
||||||
++flsize;
|
++flsize;
|
||||||
p = (char*)freelist;
|
p = (char*)freelist;
|
||||||
for (i = 0; i < flsize; ++i) {
|
for (i = 0; i < flsize; ++i) {
|
||||||
markused(flblk);
|
markused(f);
|
||||||
#ifdef AUXMEM
|
#ifdef AUXMEM
|
||||||
if (readdiskblock(device, flblk++, buf) == -1) {
|
if (readdiskblock(device, f++, buf) == -1) {
|
||||||
#else
|
#else
|
||||||
if (readdiskblock(device, flblk++, p) == -1) {
|
if (readdiskblock(device, f++, p) == -1) {
|
||||||
#endif
|
#endif
|
||||||
err(NONFATAL, err_rdfl);
|
err(NONFATAL, err_rdfl);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -876,38 +881,6 @@ int isused(uint blk) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Mark a block as free
|
|
||||||
*/
|
|
||||||
void markfree(uint blk) {
|
|
||||||
uchar temp;
|
|
||||||
uint idx = blk / 8;
|
|
||||||
uint bit = blk % 8;
|
|
||||||
#ifdef AUXMEM
|
|
||||||
copyaux(freelist + idx, &temp, 1, FROMAUX);
|
|
||||||
temp |= (0x80 >> bit);
|
|
||||||
copyaux(&temp, freelist + idx, 1, TOAUX);
|
|
||||||
#else
|
|
||||||
freelist[idx] |= (0x80 >> bit);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Mark a block as not free
|
|
||||||
*/
|
|
||||||
void marknotfree(uint blk) {
|
|
||||||
uchar temp;
|
|
||||||
uint idx = blk / 8;
|
|
||||||
uint bit = blk % 8;
|
|
||||||
#ifdef AUXMEM
|
|
||||||
copyaux(freelist + idx, &temp, 1, FROMAUX);
|
|
||||||
temp &= ~(0x80 >> bit);
|
|
||||||
copyaux(&temp, freelist + idx, 1, TOAUX);
|
|
||||||
#else
|
|
||||||
freelist[idx] &= ~(0x80 >> bit);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark a block as used
|
* Mark a block as used
|
||||||
*/
|
*/
|
||||||
|
@ -924,6 +897,22 @@ void markused(uint blk) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark a block as not used
|
||||||
|
*/
|
||||||
|
void marknotused(uint blk) {
|
||||||
|
uchar temp;
|
||||||
|
uint idx = blk / 8;
|
||||||
|
uint bit = blk % 8;
|
||||||
|
#ifdef AUXMEM
|
||||||
|
copyaux(usedlist + idx, &temp, 1, FROMAUX);
|
||||||
|
temp &= ~(0x80 >> bit);
|
||||||
|
copyaux(&temp, usedlist + idx, 1, TOAUX);
|
||||||
|
#else
|
||||||
|
usedlist[idx] |= (0x80 >> bit);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform all the operations to check a block which is used by
|
* Perform all the operations to check a block which is used by
|
||||||
* a directory or file. Complains if the block is on the free-list
|
* a directory or file. Complains if the block is on the free-list
|
||||||
|
@ -1860,10 +1849,11 @@ void copydirent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device)
|
||||||
/*
|
/*
|
||||||
* Build sorted directory block dstblk (1,2,3...) using the sorted list in
|
* Build sorted directory block dstblk (1,2,3...) using the sorted list in
|
||||||
* filelist[]. Note that the block and entry numbers are 1-based indices.
|
* filelist[]. Note that the block and entry numbers are 1-based indices.
|
||||||
|
* Returns 1 if last block of directory, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
void sortblock(uint device, uint dstblk) {
|
uchar sortblock(uint device, uint dstblk) {
|
||||||
uint i, firstlistent, lastlistent;
|
uint i, firstlistent, lastlistent;
|
||||||
uchar destentry;
|
uchar destentry, rc = 0;
|
||||||
copydirblkptrs(dstblk);
|
copydirblkptrs(dstblk);
|
||||||
if (dstblk == 1) {
|
if (dstblk == 1) {
|
||||||
copydirent(1, 1, 1, 1, device); /* Copy directory header */
|
copydirent(1, 1, 1, 1, device); /* Copy directory header */
|
||||||
|
@ -1875,32 +1865,71 @@ void sortblock(uint device, uint dstblk) {
|
||||||
firstlistent = (dstblk - 1) * entperblk - 1;
|
firstlistent = (dstblk - 1) * entperblk - 1;
|
||||||
lastlistent = firstlistent + entperblk - 1;
|
lastlistent = firstlistent + entperblk - 1;
|
||||||
}
|
}
|
||||||
if (lastlistent > numfiles - 1)
|
|
||||||
|
if (lastlistent > numfiles - 1) {
|
||||||
|
|
||||||
lastlistent = numfiles - 1;
|
lastlistent = numfiles - 1;
|
||||||
|
// TODO: Fix EOF for directory
|
||||||
|
#ifdef AUXMEM
|
||||||
|
dirblkbuf[2] = dirblkbuf[3] = 0; /* Set next ptr to NULL */
|
||||||
|
#else
|
||||||
|
p->data[2] = p->data[3] = 0; /* Set next ptr to NULL */
|
||||||
|
#endif
|
||||||
|
rc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = firstlistent; i <= lastlistent; ++i) {
|
for (i = firstlistent; i <= lastlistent; ++i) {
|
||||||
copydirent(filelist[i].blockidx, filelist[i].entrynum,
|
copydirent(filelist[i].blockidx, filelist[i].entrynum,
|
||||||
dstblk, destentry++, device);
|
dstblk, destentry++, device);
|
||||||
}
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build each sorted directory block in turn, then write them
|
* Build each sorted directory block in turn, then write them
|
||||||
* out to disk.
|
* out to disk.
|
||||||
*/
|
*/
|
||||||
int writedir(uchar device) {
|
uchar writedir(uchar device) {
|
||||||
uint dstblk = 1;
|
uint dstblk = 1;
|
||||||
|
uchar finished = 0;
|
||||||
struct block *b = blocks;
|
struct block *b = blocks;
|
||||||
while (b) {
|
while (b) {
|
||||||
sortblock(device, dstblk++);
|
if (!finished) {
|
||||||
|
finished = sortblock(device, dstblk++);
|
||||||
if (writediskblock(device, b->blocknum, dirblkbuf) == -1) {
|
if (writediskblock(device, b->blocknum, dirblkbuf) == -1) {
|
||||||
err(NONFATAL, err_wtblk1, b->blocknum);
|
err(NONFATAL, err_wtblk1, b->blocknum);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
puts("Trimming dir blk");
|
||||||
|
marknotused(b->blocknum);
|
||||||
|
}
|
||||||
b = b->next;
|
b = b->next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the freelist back to disk.
|
||||||
|
*/
|
||||||
|
uchar writefreelist(uchar device) {
|
||||||
|
uchar b;
|
||||||
|
puts("Writing freelist ...");
|
||||||
|
for (b = 0; b < flsize; ++b) {
|
||||||
|
#ifdef AUXMEM
|
||||||
|
copyaux(freelist + b * BLKSZ, dirblkbuf, BLKSZ, FROMAUX);
|
||||||
|
#else
|
||||||
|
memcpy(dirblkbuf, freelist + b * BLKSZ, BLKSZ);
|
||||||
|
#endif
|
||||||
|
if (writediskblock(device, flblk, dirblkbuf) == -1) {
|
||||||
|
err(NONFATAL, err_wtblk1, flblk);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
++flblk;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Walk through the linked list freeing memory
|
* Walk through the linked list freeing memory
|
||||||
*/
|
*/
|
||||||
|
@ -1937,7 +1966,7 @@ void interactive(void) {
|
||||||
|
|
||||||
revers(1);
|
revers(1);
|
||||||
hlinechar(' ');
|
hlinechar(' ');
|
||||||
fputs("S O R T D I R v0.78 alpha Use ^ to return to previous question", stdout);
|
fputs("S O R T D I R v0.79 alpha Use ^ to return to previous question", stdout);
|
||||||
hlinechar(' ');
|
hlinechar(' ');
|
||||||
revers(0);
|
revers(0);
|
||||||
|
|
||||||
|
@ -2104,7 +2133,7 @@ done:
|
||||||
*/
|
*/
|
||||||
void checkfreeandused(uchar device) {
|
void checkfreeandused(uchar device) {
|
||||||
uchar fl, ul, bit;
|
uchar fl, ul, bit;
|
||||||
uint byte, blk = 1, blkcnt = 0;
|
uint byte, blk = 0, blkcnt = 0;
|
||||||
printf("Total blks %u", totblks);
|
printf("Total blks %u", totblks);
|
||||||
for (byte = 0; byte < flsize * BLKSZ; ++byte) {
|
for (byte = 0; byte < flsize * BLKSZ; ++byte) {
|
||||||
#ifdef AUXMEM
|
#ifdef AUXMEM
|
||||||
|
@ -2115,15 +2144,22 @@ void checkfreeandused(uchar device) {
|
||||||
ul = usedlist[byte];
|
ul = usedlist[byte];
|
||||||
#endif
|
#endif
|
||||||
for (bit = 0; bit < 8; ++bit) {
|
for (bit = 0; bit < 8; ++bit) {
|
||||||
if ((blk > totblks) || (blk == 0))
|
if (blk >= totblks)
|
||||||
break;
|
break;
|
||||||
if ((fl << bit) & 0x80) {
|
if ((fl << bit) & 0x80) {
|
||||||
/* Free */
|
/* Free */
|
||||||
if ((ul << bit) & 0x80) {
|
if ((ul << bit) & 0x80) {
|
||||||
/* ... and used */
|
/* ... and used */
|
||||||
err(NONFATAL, err_blfree1, blk);
|
err(NONFATAL, err_blfree1, blk);
|
||||||
if (askfix() == 1)
|
if (askfix() == 1) {
|
||||||
marknotfree(blk);
|
++blkcnt;
|
||||||
|
fl &= ~(0x80 >> bit);
|
||||||
|
#ifdef AUXMEM
|
||||||
|
copyaux(&fl, freelist + byte, 1, TOAUX);
|
||||||
|
#else
|
||||||
|
freelist[byte] = fl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Not free */
|
/* Not free */
|
||||||
|
@ -2131,8 +2167,15 @@ void checkfreeandused(uchar device) {
|
||||||
if (!((ul << bit) & 0x80)) {
|
if (!((ul << bit) & 0x80)) {
|
||||||
/* ... and not used */
|
/* ... and not used */
|
||||||
err(NONFATAL, err_blused1, blk);
|
err(NONFATAL, err_blused1, blk);
|
||||||
if (askfix() == 1)
|
if (askfix() == 1) {
|
||||||
markfree(blk);
|
--blkcnt;
|
||||||
|
fl |= (0x80 >> bit);
|
||||||
|
#ifdef AUXMEM
|
||||||
|
copyaux(&fl, freelist + byte, 1, TOAUX);
|
||||||
|
#else
|
||||||
|
freelist[byte] = fl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++blk;
|
++blk;
|
||||||
|
@ -2140,7 +2183,6 @@ void checkfreeandused(uchar device) {
|
||||||
}
|
}
|
||||||
printf("\nFree blks %u\n", totblks - blkcnt);
|
printf("\nFree blks %u\n", totblks - blkcnt);
|
||||||
|
|
||||||
// TODO: NEED SOME CODE TO WRITE OUT MODIFIED FREE LIST!!
|
|
||||||
if (dozero)
|
if (dozero)
|
||||||
zerofreeblocks(device, totblks - blkcnt);
|
zerofreeblocks(device, totblks - blkcnt);
|
||||||
}
|
}
|
||||||
|
@ -2409,8 +2451,11 @@ int main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef FREELIST
|
#ifdef FREELIST
|
||||||
if (dowholedisk)
|
if (dowholedisk) {
|
||||||
checkfreeandused(dev);
|
checkfreeandused(dev);
|
||||||
|
if (dowrite)
|
||||||
|
writefreelist(dev);
|
||||||
|
}
|
||||||
|
|
||||||
free(freelist);
|
free(freelist);
|
||||||
free(usedlist);
|
free(usedlist);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user