From 33368c8e24021e549a28e044f5b15729b5dbb3ae Mon Sep 17 00:00:00 2001 From: Bobbi Webber-Manners Date: Mon, 1 Jun 2020 19:49:25 -0400 Subject: [PATCH] Create sorted blocks on-the-fly, without storing them all in aux mem. --- sortdir.c | 157 ++++++++++++++++++++++++++--------------------------- sortdir.po | Bin 143360 -> 143360 bytes 2 files changed, 76 insertions(+), 81 deletions(-) diff --git a/sortdir.c b/sortdir.c index 5b8f1a5..c12400b 100644 --- a/sortdir.c +++ b/sortdir.c @@ -3,10 +3,6 @@ * * Bobbi January-June 2020 * - * TODO: IDEA you only need one sorteddata block at a time. Do not allocate - * until writeout time and use one block buffer. Iterate through - * filelist[] collecting all entries for block 1, 2, 3 in turn. - * Huge aux memory savings!! * TODO: Get working on drives >2 (S7D3, S7D4 etc.) * TODO: Enable free list functionality on ProDOS-8 * TODO: Get both ProDOS-8 and GNO versions to build from this source @@ -29,6 +25,7 @@ * v0.63 Made code work properly with #undef CHECK. * v0.64 Fixed overflow in file count (entries). Added check to auxalloc(). * v0.65 Fixed length passed to AUXMOVE in copyaux(). + * v0.66 Modified to build sorted blocks on the fly rather than in aux memory. */ //#pragma debug 9 @@ -119,16 +116,13 @@ struct pd_dirent { /* * Linked list of directory blocks read from disk - * Original directory block is stored in data[] - * Directory block for sorted directory is stored in sorteddata[] + * Directory block is stored in data[] */ struct block { #ifdef AUXMEM char *data; /* Original contents of block */ - char *sorteddata; /* Content block for sorted dir */ #else char data[BLKSZ]; /* Original contents of block */ - char sorteddata[BLKSZ]; /* Content block for sorted dir */ #endif uint blocknum; /* Block number on disk */ struct block *next; @@ -202,7 +196,9 @@ static uchar dowrite = 0; /* -w write option */ static uchar doverbose = 0; /* -v verbose option */ static uchar dodebug = 0; /* -V very verbose option */ static uchar do_ctime = 0; /* -k ctime option */ +#ifdef FREELIST static uchar dozero = 0; /* -z zero free blocks option */ +#endif static char sortopts[NLEVELS+1] = ""; /* -s:abc list of sort options */ static char caseopts[2] = ""; /* -c:x case conversion option */ static char fixopts[2] = ""; /* -f:x fix mode option */ @@ -274,15 +270,18 @@ void sortlist(char s); #endif void printlist(void); uint blockidxtoblocknum(uint idx); -void copyent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device); -void sortblocks(uint device); +void copydirblkptrs(uint blkidx); +void copydirent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device); +void sortblock(uint device, uint dstblk); int writedir(uchar device); void freeblocks(void); void interactive(void); void processdir(uint device, uint blocknum); +#ifdef FREELIST void checkfreeandused(uchar device); void zeroblock(uchar device, uint blocknum); void zerofreeblocks(uchar device, uint freeblks); +#endif #ifdef CMDLINE void usage(void); void parseargs(void); @@ -517,7 +516,7 @@ void lowercase(char *p, uchar len, uchar *minvers, uchar *vers) { * Convert filename pointed to by p into upper case (which is recorded * as a bitmap in the vers and minvers fields. */ -void uppercase(char *p, uchar len, uchar *minvers, uchar *vers) { +void uppercase(char*, uchar, uchar *minvers, uchar *vers) { *vers = 0x00; *minvers = 0x00; } @@ -827,9 +826,11 @@ void checkblock(uint blk, char *msg) { /* * Count the blocks in a seedling file */ -int seedlingblocks(uchar device, uint keyblk, uint *blkcnt) { #ifdef FREELIST +int seedlingblocks(uchar, uint keyblk, uint *blkcnt) { checkblock(keyblk, "Data"); +#else +int seedlingblocks(uchar, uint, uint *blkcnt) { #endif *blkcnt = 1; return 0; @@ -1076,7 +1077,6 @@ int readdir(uint device, uint blocknum) { static char namebuf[NMLEN+1]; struct pd_dirhdr *hdr; struct block *curblk; - struct datetime dt; ulong eof; uint filecount, idx, subdirs, blks, keyblk, hdrblk, count, entries; uchar blkentries, pd25, i; @@ -1095,7 +1095,6 @@ int readdir(uint device, uint blocknum) { #ifdef AUXMEM curblk->data = auxalloc(BLKSZ); - curblk->sorteddata = auxalloc(BLKSZ); #endif #ifdef FREELIST @@ -1308,14 +1307,8 @@ int readdir(uint device, uint blocknum) { blocknum = dirblkbuf[0x02] + 256U * dirblkbuf[0x03]; #ifdef AUXMEM copyaux(dirblkbuf, curblk->data, BLKSZ, TOAUX); - bzero(buf, BLKSZ); - memcpy(buf, dirblkbuf, PTRSZ); - copyaux(buf, curblk->sorteddata, BLKSZ, TOAUX); #else memcpy(curblk->data, dirblkbuf, BLKSZ); - bzero(buf, BLKSZ); - memcpy(buf, dirblkbuf, PTRSZ); - memcpy(curblk->sorteddata, buf, BLKSZ); #endif if (blocknum == 0) { break; @@ -1330,7 +1323,6 @@ int readdir(uint device, uint blocknum) { #ifdef AUXMEM curblk->data = auxalloc(BLKSZ); - curblk->sorteddata = auxalloc(BLKSZ); #endif #ifdef FREELIST @@ -1359,14 +1351,8 @@ int readdir(uint device, uint blocknum) { } #ifdef AUXMEM copyaux(dirblkbuf, curblk->data, BLKSZ, TOAUX); - bzero(buf, BLKSZ); - memcpy(buf, dirblkbuf, PTRSZ); - copyaux(buf, curblk->sorteddata, BLKSZ, TOAUX); #else memcpy(curblk->data, dirblkbuf, BLKSZ); - bzero(buf, BLKSZ); - memcpy(buf, dirblkbuf, PTRSZ); - memcpy(curblk->sorteddata, buf, BLKSZ); #endif return errcount - errsbefore; @@ -1730,21 +1716,36 @@ uint blockidxtoblocknum(uint idx) { uint i; struct block *p = blocks; for (i = 1; i < idx; ++i) - if (p) - p = p->next; - else - err(FATAL, "Int error"); - if (!p) - err(FATAL, "Int error"); + p = p->next; return p->blocknum; } +/* + * Copy the 4 bytes of pointers from the directory block with index idx + * to the start of dirblkbuf[]; zeroes the rest of dirblkbuf[]. + */ +void copydirblkptrs(uint idx) { + uint i; + struct block *p = blocks; + for (i = 1; i < idx; ++i) + p = p->next; + //while (--blkidx > 0) + // b = b->next; + bzero(dirblkbuf, BLKSZ); +#ifdef AUXMEM + copyaux(p->data, dirblkbuf, PTRSZ, FROMAUX); +#else + memcpy(dirblkbuf, p->data, PTRSZ); +#endif +} + /* * Copy a file entry from one srcblk, srcent to dstblk, dstent * All indices are 1-based. + * dstblk is written to dirblkbuf[] */ -void copyent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device) { - struct block *source = blocks, *dest = blocks; +void copydirent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device) { + struct block *source = blocks; struct pd_dirent *ent; struct pd_dirhdr *hdr; char *srcptr, *dstptr; @@ -1755,32 +1756,26 @@ void copyent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device) { printf(" to dirblk %03u entry %02u\n", dstblk, dstent); } - parentblk = blockidxtoblocknum(dstblk); - while (--srcblk > 0) source = source->next; - while (--dstblk > 0) - dest = dest->next; + srcptr = source->data + PTRSZ + (srcent-1) * entsz; - dstptr = dest->sorteddata + PTRSZ + (dstent-1) * entsz; + dstptr = dirblkbuf + PTRSZ + (dstent-1) * entsz; + #ifdef AUXMEM - copyaux(srcptr, buf2, entsz, FROMAUX); - copyaux(buf2, dstptr, entsz, TOAUX); + copyaux(srcptr, dstptr, entsz, FROMAUX); #else memcpy(dstptr, srcptr, entsz); #endif /* For directories, update the parent dir entry number */ -#ifdef AUXMEM - ent = (struct pd_dirent*)buf2; -#else ent = (struct pd_dirent*)dstptr; -#endif if ((ent->typ_len & 0xf0) == 0xd0) { uint block = ent->keyptr[0] + 256U * ent->keyptr[1]; if (readdiskblock(device, block, buf) == -1) err(FATAL, "Can't read subdir"); hdr = (struct pd_dirhdr*)(buf + PTRSZ); + parentblk = blockidxtoblocknum(dstblk); hdr->parptr[0] = parentblk & 0xff; hdr->parptr[1] = (parentblk >> 8) & 0xff; hdr->parentry = dstent; @@ -1792,39 +1787,40 @@ void copyent(uint srcblk, uint srcent, uint dstblk, uint dstent, uint device) { } /* - * Use the sorted list in filelist[] to create a sorted set of directory - * blocks. Note that the block and entry numbers are 1-based indices. + * 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. */ -void sortblocks(uint device) { - uint i; - uchar destblk = 1; - uchar destentry = 2; /* Skip header on first block */ - copyent(1, 1, 1, 1, device); /* Copy directory header */ - for(i = 0; i < numfiles; ++i) { - if (dodebug) - puts(filelist[i].name); - copyent(filelist[i].blockidx, filelist[i].entrynum, - destblk, destentry, device); - if (destentry++ == entperblk) { - ++destblk; - destentry = 1; - } +void sortblock(uint device, uint dstblk) { + uint i, firstlistent, lastlistent; + uchar destentry; + copydirblkptrs(dstblk); + if (dstblk == 1) { + copydirent(1, 1, 1, 1, device); /* Copy directory header */ + destentry = 2; /* Skip header on first block */ + firstlistent = 0; + lastlistent = entperblk - 2; + } else { + destentry = 1; + firstlistent = (dstblk - 1) * entperblk - 1; + lastlistent = firstlistent + entperblk - 1; + } + for (i = firstlistent; i <= lastlistent; ++i) { + copydirent(filelist[i].blockidx, filelist[i].entrynum, + dstblk, destentry++, device); } } /* - * Write out the sorted directory + * Build each sorted directory block in turn, then write them + * out to disk. */ int writedir(uchar device) { + uint dstblk = 1; struct block *b = blocks; while (b) { -#ifdef AUXMEM - copyaux(b->sorteddata, dirblkbuf, BLKSZ, FROMAUX); + sortblock(device, dstblk++); if (writediskblock(device, b->blocknum, dirblkbuf) == -1) { -#else - if (writediskblock(device, b->blocknum, b->sorteddata) == -1) { -#endif - err(NONFATAL, "Can't write block %u", b->blocknum); + err(NONFATAL, "Can't write blk %u", b->blocknum); return 1; } b = b->next; @@ -1846,12 +1842,15 @@ void freeblocks(void) { } void interactive(void) { - char w, l, d, f, z, wrt; + char w, l, d, f, wrt; +#ifdef FREELIST + char z; +#endif uchar level; doverbose = 1; - puts("S O R T D I R v0.65 alpha Use ^ to return to previous question"); + puts("S O R T D I R v0.66 alpha Use ^ to return to previous question"); q1: fputs("\nEnter path (e.g.: /H1) of starting directory> ", stdout); @@ -1983,13 +1982,9 @@ void processdir(uint device, uint blocknum) { printf("[%c] ", sortopts[i]); buildsorttable(sortopts[i], i); sortlist(sortopts[i]); - sortblocks(device); } if (doverbose) putchar('\n'); - //if (doverbose) { - // printlist(); - //} if (dowrite) { puts("Writing dir ..."); errs = writedir(device); @@ -2004,13 +1999,14 @@ done: #endif } +#ifdef FREELIST + /* * Iterate through freelist[] and usedlist[] and see if all is well. * If we have visited all files and directories on the volume, every * block should either be marked free or marked used. */ void checkfreeandused(uchar device) { -#ifdef FREELIST uint i, freeblks = 0; printf("Total blks\t%u\n", totblks); for (i = 0; i < totblks; ++i) @@ -2041,13 +2037,11 @@ void checkfreeandused(uchar device) { } if (dozero) zerofreeblocks(device, freeblks); -#endif } /* * Zero block blocknum */ -#ifdef FREELIST void zeroblock(uchar device, uint blocknum) { bzero(buf, BLKSZ); // DIORecGS dr; @@ -2061,12 +2055,10 @@ void zeroblock(uchar device, uint blocknum) { // if (dr.transferCount != BLKSZ) // err(FATAL, "Block write failed"); } -#endif /* * Zero all free blocks on the volume */ -#ifdef FREELIST void zerofreeblocks(uchar device, uint freeblks) { uint i, step = freeblks / 60, ctr = 0; puts("Zeroing free blocks ..."); @@ -2082,6 +2074,7 @@ void zerofreeblocks(uchar device, uint freeblks) { } puts("\nDone zeroing!"); } + #endif #ifdef CMDLINE @@ -2173,7 +2166,9 @@ void parseargs() { //int main(int argc, char *argv[]) { int main() { +#ifdef CMDLINE int opt; +#endif uchar dev; uint blk; @@ -2292,10 +2287,10 @@ int main() { processdir(dev, blk); } } +#ifdef FREELIST if (dowholedisk) checkfreeandused(dev); -#ifdef FREELIST free(freelist); free(usedlist); #endif diff --git a/sortdir.po b/sortdir.po index d6341fdcc606e9bd9dd1815182486769da2c45c6..6ee86c25510dba287375fddf4259be0800cfc029 100644 GIT binary patch delta 23541 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%0A`i7 z_~0K5ka&>+I)8P&R-OlQWwpj^o1z0*He`KqXxWFYG139~cym%9x$moC^ak+*AFyIt z%VAmW*$=h7e~m_oR*uw`9G(8!nrd5eP>)0Ky6Ue))i?O-?njB()ncpb_H5`L?78x0zkwxo~QE14-!s+GY-&Cs1c@*Wf~e` zwD}(^Pz=@TXg-iR5v6BWKy;q;;&r;yPW~hqkA!og=)UGNWBv=#*{@B|44qvCKNoxo zr5sq|I09n=Vo|<#xU3l=E&1`nK{^Rei-L*+9Ut)FWGAAMo#`K`w?SC# zl$_voXs9vPz=l6<g?($52t5x}D%OAss!-k) uSN!bb2P(veeD?8&eE{hY_pP~r3R+Fd2bH~fuBW=DJeIKW+s1Db#{XZdX`wm*