home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <conio.h>
- #include <dos.h>
- #include <ctype.h>
- #include <mem.h>
- #include <alloc.h>
-
- #include "dosstruc.h"
-
- /*--- Function Prototypes ---*/
-
- int SearchFirst (struct ExtFcb * Fcb);
- int AbortProgram (void);
- int isdevice (int handle);
- void ReadRoot (void);
- void ReadSub (void);
- void WriteRoot (void);
- void WriteSub (void);
- long Alu2Sec (struct DpbStruct * Dpb, unsigned Alu);
- char *strrspn (char *s1, char *s2);
- void PutQueue (struct ClusterQueue * Q, unsigned Cluster);
- unsigned NextCl (int Is12Bit, unsigned Cluster, unsigned char *Fat);
- void FreeCluster (int Is12Bit, unsigned Val, unsigned Cluster, unsigned char Fat[]);
-
- /*--- End of Prototypes ---*/
-
-
- /*
- * 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) {
- extern char Disk, Parent[67], Element[13];
- extern char Line[80], Level, RSwt, VerSwt, Packed, TruncateSwt;
- extern int Lim, j, l;
- extern int OutSectors, OutClusters, BytesPerCluster, ECount;
- extern int *CluArray;
- extern unsigned NumSec;
- extern unsigned DirStart;
- extern long MinMem;
- extern struct DpbStruct Dpb;
- extern struct DirEntry *DirBuff;
- extern struct ClusterEntry *p, *t;
- extern struct ExtFcb Fcb;
- extern struct ExtendedEntry Dir;
- extern struct ClusterQueue CluQ;
-
- char *strrspn();
- char **DirVector, *r;
- int strincmp();
- int i, k, DirCount, Root;
- long Mem;
-
- BytesPerCluster = (Dpb.ClusterSize + 1) * Dpb.SectorSize;
- if (strlen(Element) != 0) { /* Sorting a sub-directory */
- Root = 0;
- bdosptr(0x3B, Parent, 0); /* Set Current Directory */
- if ((Parent[strlen(Parent) - 1] != '\\') && (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;
- }
- }
-
- 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");
- if (TruncateSwt) WriteSub();
- 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)) {
- printf(" Sort (Y or N)? ");
- fflush(stdout);
- }
- else {
- fprintf(stderr, " Sort (Y or N)? ");
- fflush(stderr);
- }
- 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;
- }
- }
- }
-
- if (TruncateSwt) {
- for (i = k; i >= 0; --i) {
- if (DirBuff[i].Name[0] != 0x00) break;
- }
- i += 2;
- }
-
- /*
- * 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;
-
- /* 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", DirStart, 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 (void) {
- extern unsigned Cluster;
- extern unsigned LastCluster;
- extern unsigned char *Fat;
- extern struct ExtendedEntry Dir;
- extern struct ClusterQueue CluQ;
- extern int Is12Bit, *CluArray, BytesPerCluster, Lim;
- extern char Disk;
- 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 (void) {
- extern char TruncateSwt;
- extern char FatDirty;
- extern struct ClusterQueue CluQ;
- extern char Disk;
- extern struct DpbStruct Dpb;
- extern int *CluArray, BytesPerCluster;
- extern int OutClusters;
- extern struct DirEntry *DirBuff;
-
- int i;
-
- for (i = 0; i < OutClusters; 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);
- }
- }
- if ( (TruncateSwt) && (i < CluQ.Count) ) {
- FatDirty |= 1;
- FreeCluster(Is12Bit, 0xFFFF, CluArray[i - 1], Fat);
- for (; i < CluQ.Count; ++i) FreeCluster(Is12Bit, 0, CluArray[i], Fat);
- }
- }
-
- void
- ReadRoot (void) {
- extern struct DpbStruct Dpb;
- extern unsigned NumSec;
- extern unsigned DirStart;
- extern struct DirEntry *DirBuff;
- extern int *CluArray, Lim;
- extern char Disk;
-
- 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, DirStart, (char *) DirBuff)) != 0) {
- fprintf(stderr, "Error reading root: %04X.\n", Error);
- exit(1);
- }
- }
-
-
- void
- WriteRoot (void) {
- extern char Disk;
- extern unsigned NumSec;
- extern unsigned DirStart;
- extern struct DpbStruct Dpb;
- extern struct DirEntry *DirBuff;
-
- if (abswrite(Disk - 'A', NumSec, DirStart, (char *) DirBuff)) {
- fprintf(stderr, "Error writing Root.\n");
- exit(1);
- }
- }