home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include <ctype.h>
- #include <mem.h>
-
- #include "dosstruc.h"
-
- /*
- * SORTDIR is the main routine of CSAP. It is a recursive routine that will
- * walk the directory hierarchy, sorting all directories that it finds. It
- * uses the quick sort or quicker sort algorithm provided by most C runtime
- * libraries to perform the actual sort. It uses DOS Int 25H and 26H,
- * Absolute Disk Read and Absolute Disk Write, to read the directories into
- * memory for sorting and to write out the sorted directories. It depends
- * upon information about the physical characteristics of the disk provided
- * by GETDPB.
- */
-
- void SortDir () {
- void PutQueue(), GetKey(), qsort();
- void ReadSub(), WriteSub(), ReadRoot(), WriteRoot();
- char *strrspn();
- int strincmp(), SearchFirst();
- unsigned al2sec(), NextCl();
-
- extern char Disk, *Fat, Parent[67], Element[13];
- extern char Line[80], Level, RSwt, VerSwt, Packed;
- extern struct DpbStruct Dpb;
- extern struct DirEntry *DirBuff;
- extern unsigned Cluster, Sector, NumSec;
- extern int Lim, j, l;
- extern struct ClusterEntry *p, *t;
- extern int OutSectors, OutClusters, BytesPerCluster, ECount;
- extern struct ExtFcb Fcb;
- extern struct ExtendedEntry Dir;
- extern struct ClusterQueue CluQ;
- extern int Is12Bit, *CluArray;
- extern unsigned MinMem;
-
- char **DirVector, *r, Reply;
- int i, k, DirCount, Root;
- unsigned Mem;
-
-
- BytesPerCluster = (Dpb.ClusterSize + 1) * Dpb.SectorSize;
-
- if (strlen(Element) != 0) { /* Sorting a sub-directory */
- Root = 0;
- bdos(0x3B, (int) Parent, 0); /* Set Current Directory */
- if (Parent[strlen(Parent)-1] != '\\') strcat(Parent, "\\");
- setdta((char *) &Dir);
- parsfnm(Element, (struct fcb *) &Fcb.DriveId, 0);
- Fcb.FcbHdr.Header = 0xFF;
- Fcb.DriveId = Disk - '@';
- Fcb.FcbHdr.Attrib = 0xFF;
- if (SearchFirst(&Fcb) != 0) {
- fprintf(stderr, "Not found: %s%s\n", Parent, Element);
- AbortProgram();
- }
- }
- else Root = 1; /* Sorting the Root directory */
-
- printf("Sorting: %s%s", Parent, Element);
- if (!isdevice(1)) fprintf(stderr, "Sorting: %s%s", Parent, Element);
-
- /* Read directory to be sorted into memory */
-
- if (Root) ReadRoot();
- else ReadSub();
-
- /* Count sub-directories, skipping "current" and "parent" entries */
-
- for (DirCount=0, i=0; i < Lim / sizeof(struct DirEntry); i++) {
- if (DirBuff[i].Name[0] == 0) break;
- if ((DirBuff[i].Attribute & 0x10)
- && (DirBuff[i].Name[0] != '.')
- && (DirBuff[i].Name[0] != 0xE5)) DirCount++;
- }
- k = i;
- if (DirCount != 0) {
- if ((DirVector = malloc(DirCount * sizeof(DirVector))) == NULL) {
- fprintf(stderr, "Insufficient memory (2).\n");
- return;
- }
- }
-
- /*
- * Compute the number of directory sectors to write out - don't write sectors
- * that don't contain active entries.
- */
-
- OutSectors = ((i * 32) + Dpb.SectorSize - 1) / Dpb.SectorSize;
- OutClusters = (OutSectors + Dpb.ClusterSize) >> Dpb.ClusterShift;
-
- j = 0;
- if (Root) {
-
- /* If sorting Root - skip 1st two files if "System" & "Hidden" */
-
- if (i > 1) {
- if (DirBuff[j].Attribute & 0x06) {
- j++; i--;
- if (DirBuff[j].Attribute & 0x06) {
- j++; i--;
- }
- }
- }
- }
- else {
-
- /* If sorting subdirectory - skip 1st two entries, "current" and "parent" */
-
- j += 2; i -= 2;
- }
- if (i == 0) {
- printf(" Empty.\n");
- r = &Parent[strlen(Parent)-1];
- if (r[-1] == ':') r++;
- *r = 0x00;
- return;
- }
-
- /* If VerSwt ON - request operator confirmation BEFORE sorting */
-
- if (VerSwt != 0) {
- if (!isdevice(1)) {
- fprintf(stderr, " Sort (Y or N)? "); fflush(stderr);
- }
- else {
- printf(" Sort (Y or N)? "); fflush(stdout);
- }
- if (toupper(getche()) != 'Y') {
- if (!isdevice(1)) fprintf(stderr, "n");
- printf("\n");
- return;
- }
- }
-
- if (!isdevice(1)) fprintf(stderr, "\n");
- printf("\n");
-
- /* Sort directory */
-
- qsort(&DirBuff[j], i, sizeof(struct DirEntry), strincmp);
-
- ECount = 0;
-
- /*
- * If Packed OFF, remove "erased" entries from directory (mark them "unused)
- */
-
- if (Packed != 0) {
- for (i=k; i >= 0; i--) {
- if ((DirBuff[i].Name[0] != 0xE5) && (DirBuff[i].Name[0] != 0x00)) break;
- if (DirBuff[i].Name[0] == 0xE5) {
- DirBuff[i].Name[0] = 0x00;
- ++ECount;
- }
- }
- }
-
- /* Build list of subdirectories - skipping "current" and "parent" entries */
-
- for (l=0, i=0; DirBuff[i].Name[0]; i++) {
- if ((DirBuff[i].Attribute & 0x10) && (DirBuff[i].Name[0] != '.')) {
- for (k=0, j=0; j<8; ++j) {
- if (DirBuff[i].Name[j] == ' ') break;
- else Line[k++] = DirBuff[i].Name[j];
- }
- if (DirBuff[i].Ext[0] != ' ') {
- Line[k++] = '.';
- for (j=0; j<3; ++j) {
- if (DirBuff[i].Ext[j] == ' ') break;
- else Line[k++] = DirBuff[i].Ext[j];
- }
- }
- Line[k++] = '\0';
- if ((DirVector[l] = malloc(k)) == NULL) {
- fprintf(stderr, "Insufficient memory.\n");
- return;
- }
- strcpy(DirVector[l++], Line);
- }
- }
-
- /* Write out sorted directory */
-
- if (Root) {
- WriteRoot();
- if (RSwt) printf(" Location: %04XH-%04XH\n", Dpb.DirStart, Dpb.DirStart + NumSec - 1);
- }
- else {
- WriteSub();
- if (RSwt) {
- printf(" Location:");
- for (i=0; i<CluQ.Count; ++i) {
- if (i == 0) printf(" %04XH", Alu2Sec(&Dpb, CluArray[i]));
- if ((i > 0) && (CluArray[i] != CluArray[i-1] + 1)) {
- printf("-%04XH %04XH",
- Alu2Sec(&Dpb, CluArray[i-1] + 1) - 1,
- Alu2Sec(&Dpb, CluArray[i])
- );
- }
- }
- printf("-%04XH\n", Alu2Sec(&Dpb, CluArray[i-1] + 1) - 1);
- }
- }
- if (RSwt) printf(" %d Erased entries removed\n", ECount);
-
- Mem = coreleft();
- if (MinMem < Mem) MinMem = Mem;
-
- /* Release dynamically acquired space for this directory */
-
- free(DirBuff);
- for (p = CluQ.Head; p != NULL; p = t) {
- t = p->Next; free(p);
- }
- free(CluArray);
-
- /* If Recursive sort - build Parent and Element for sub directories & sort */
-
- if (!Level) {
- strcat(Parent, Element);
- for (i=0; i < DirCount; i++) {
- strcpy(Element, DirVector[i]);
-
- SortDir();
-
- }
- r = strrspn(Parent, "\\/");
- if (r[-1] == ':') r++;
- *r = 0x00;
- }
- }
-
- void ReadSub() {
-
- extern unsigned Cluster;
- extern unsigned LastCluster;
- extern char *Fat;
- extern struct ExtendedEntry Dir;
- extern struct ClusterQueue CluQ;
- extern int Is12Bit, *CluArray, BytesPerCluster, Lim;
- extern char Disk, *Fat;
- extern struct DirEntry *DirBuff;
- extern struct DpbStruct Dpb;
-
- int i;
- struct ClusterEntry *p;
- void PutQueue();
- unsigned NextCl();
-
- Cluster = Dir.Body.FirstCluster;
- CluQ.Head = CluQ.Current = NULL; CluQ.Count = 0;
- while (Cluster < LastCluster) {
- PutQueue(&CluQ, Cluster);
- Cluster = NextCl(Is12Bit, Cluster, Fat);
- }
- if ((CluArray = malloc(CluQ.Count * sizeof(int))) == NULL) {
- fprintf(stderr, "Insufficient memory (3).\n");
- return;
- }
- for (i=0, p=CluQ.Head; p != NULL; i++, p=p->Next) {
- CluArray[i] = p->Cluster;
- }
- Lim = CluQ.Count * BytesPerCluster;
- if ((DirBuff = malloc(Lim)) == NULL) {
- fprintf(stderr, "Insufficient memory for directory buffer.\n");
- return;
- }
- for (i=0; i < CluQ.Count; i++) {
- if (absread(Disk-'A', Dpb.ClusterSize + 1,
- Alu2Sec(&Dpb, CluArray[i]),
- (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
- fprintf(stderr, "Error reading directory.\n"); exit(1);
- }
- }
- }
-
- void WriteSub () {
-
- extern struct ClusterQueue CluQ;
- extern char Disk, *Fat, Parent[67], Element[13];
- extern struct DpbStruct Dpb;
- extern int Is12Bit, *CluArray, BytesPerCluster;
- extern struct DirEntry *DirBuff;
-
- int i;
-
- for (i=0; i < CluQ.Count; i++) {
- if (abswrite(Disk-'A', Dpb.ClusterSize + 1,
- Alu2Sec(&Dpb, CluArray[i]),
- (char *) &DirBuff[(i * BytesPerCluster) / 32])) {
- fprintf(stderr, "Error writing directory.\n"); exit(1);
- }
- }
- }
-
- void ReadRoot () {
-
- extern struct DpbStruct Dpb;
- extern unsigned NumSec;
- extern struct DirEntry *DirBuff;
- extern int Is12Bit, *CluArray, Lim;
- extern char Disk;
-
- int i;
- int Error;
-
- Lim = Dpb.MaxEntries * 32;
- NumSec = (Lim + Dpb.SectorSize - 1) / Dpb.SectorSize;
- if ((DirBuff = malloc(Lim)) == NULL) {
- fprintf(stderr, "Insufficient memory for cluster buffer.\n");
- return;
- }
- if ((CluArray = malloc(sizeof(int))) == NULL) {
- fprintf(stderr, "Insufficient memory (4).\n");
- return;
- }
- CluArray[0] = 0;
- if ((Error = absread(Disk-'A', NumSec, Dpb.DirStart, (char *) DirBuff)) != 0) {
- fprintf(stderr, "Error reading root: %04X.\n", Error); exit(1);
- }
- }
-
-
- void WriteRoot () {
-
- extern char Disk;
- extern unsigned Cluster, Sector, NumSec;
- extern struct DpbStruct Dpb;
- extern struct DirEntry *DirBuff;
-
- if (abswrite(Disk-'A', NumSec, Dpb.DirStart, (char *) DirBuff)) {
- fprintf(stderr, "Error writing Root.\n"); exit(1);
- }
- }