home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 8
/
CDASC08.ISO
/
VRAC
/
CSAP400.ZIP
/
SORTDIR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-09
|
10KB
|
398 lines
#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);
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.
*/
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].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 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);
}
}