Category : File Managers
Archive   : CASP421.ZIP
Filename : SORTDIR.C

 
Output of file : SORTDIR.C contained in archive : CASP421.ZIP
#include
#include
#include
#include
#include
#include
#include
#include

#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);
void FreeCluster(int Is12Bit, unsigned Val, unsigned Cluster);

/*--- 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.
*/

extern struct absr32m a32;

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");
r = &Parent[strlen(Parent) - 1];
if (r[-1] == ':') r++;
*r = 0x00;
if (TruncateSwt) {
OutClusters = 1;
WriteSub();
}
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) {
memset(DirBuff[i].Name, '\0', sizeof(DirBuff[i]));
++ECount;
}
}
i = k;
}
if (TruncateSwt) {
for (i = k; i > 0; --i) {
if (DirBuff[i-1].Name[0] != 0x00) break;
}
}

/*
* 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 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);
}
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 Is12Bit, *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]);
for (; i < CluQ.Count; ++i)
FreeCluster(Is12Bit, 0, CluArray[i]);
}
}

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);
}
}


  3 Responses to “Category : File Managers
Archive   : CASP421.ZIP
Filename : SORTDIR.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/