/*
Aus J:\USER\HENNI\NEU
Aufbau der TREEINFO.NCD
- 5 Bytes ASCIIZ "PNCI", wird NICHT geprüft!
- 2 Bytes Anzahl (n) der Verzeichnisse (INTEL-Notation)
- 2 Bytes simple Prüfsumme über diese 7 Header-Bytes, 1. Prüfsumme
- n 16-Byte-Verzeichnisblöcke, beginnend mit "\", mit je folgendem Aufbau:
- 13 Byte ASCIIZ Verzeichnisname (mit Punkt; Slack undefiniert, jedoch
ist das 13. Byte stets Null)
- 1 Byte Tiefe des Verzeichnisses, Root=0
- 1 Byte Flag (0 oder 1): Vorhergehender Eintrag 1 Level höher
- 1 Byte Flag (0 oder 1): Weitere Einträge desselben Levels folgen
(Diese Blöcke sind selbstverständlich tree-gerecht geordnet, d.h. beim
Erstellen eines tief unten liegenden Vrz's wird ggf. mitten in der Datei
Platz gemacht, um dort den Block einzufügen)
- 2 Bytes simple Prüfsumme (*nur*) über die n Verzeichnisblöcke, 2. Prüfsumme
*/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <io.h>
#include <ctype.h>
#include <string.h>
/* Compilerunterschiede mit Makros erschlagen */
#ifdef __TURBOC__
#include <dir.h>
#define FF_STRUCT struct ffblk
#define FF_NAME(ff) ff.ff_name
#define FF_ATTRIB(ff) ff.ff_attrib
#else /* Zortech C */
#define FF_STRUCT struct FIND
#define FF_NAME(ff) ff.name
#define FF_ATTRIB(ff) ff.attribute
#endif
/* Grafische Verbindungselemente für Codepage 437 */
#define HSTRICH 0xC4 /* - */
#define VSTRICH 0xB3 /* | */
#define WINKEL 0xC0 /* \ */
#define VERBINDUNG 0xC3 /* + */
/* Makro zum Test auf Unterverzeichnisse */
#define ISDIR(ff) ((FF_ATTRIB(ff) & FA_DIREC) && (FF_NAME(ff)[0] != '.'))
unsigned NumDirs; /* Anzahl Verzeichnisse */
char TreeInfo[] = { " :\\TREEINFO.NCD" };
/* Laufwerk wird im Hauptprogramm eingetragen */
unsigned CheckSum; /* Prüfsumme */
/* Kopfinformation von TREEINFO.NCD */
struct HEADER
{ char ident[5]; /* "PNCI\x0" */
unsigned numdir; /* Anzahl 'DIRINFO' Einträge */
unsigned checksum; /* Checksumme über 'ident' und 'numdir' */
} header;
#if sizeof(header) != 9
#error Byteweise Ausrichtung benutzen
#endif
/* Verzeichnisinformation von TREEINFO.NCD */
struct DIRINFO
{ char name[13],
deep,
isfirst,
isnotlast;
} dirinfo;
/* Struktur zum Aufbau eines Verzeichnisbaumes im Hauptspeicher */
struct DIRTREE
{ char *name;
int deep;
struct DIRTREE *next, /* Zeiger auf Verzeichnisnamen im selben Verzeichnis */
*sub, /* Zeiger auf Unterverzeichnis dieses Verzeichnisses */
*father; /* Zeiger auf übergeordnetes Verzeichnis -
wurde eingeführt, um von einer beliebigen Stelle aus
den kompletten Verzeichnisnamen einfach bilden zu
können, z.B. für Verzeichniswechseln */
} root;
/* Funktion zum Testen auf eine gültige TREEINFO.NCD */
FILE *validate(void)
{ FILE *fp;
unsigned i, checksum;
unsigned char *p;
if ((fp = fopen(TreeInfo, "rb")) != NULL)
if (fread(&header, 1, sizeof(header), fp) == sizeof(header))
if (strcmp(header.ident, "PNCI") == 0)
if (filelength(fileno(fp)) >> 4 == header.numdir)
{
p = (void*)&header;
for (i=checksum=0; i<7; i++, p++) checksum += *p;
if (checksum == header.checksum)
{ NumDirs = header.numdir;
return fp;
}
}
if (fp) fclose(fp);
return NULL;
}
void readsubdir(FILE *fp, struct DIRTREE *pFather, int deep)
{ struct DIRTREE *pCurrent, *pNext;
deep++;
pCurrent = malloc(sizeof(struct DIRTREE));
pFather->sub = pCurrent;
while (pCurrent && (dirinfo.deep == deep))
{ pCurrent->name = strdup(dirinfo.name);
pCurrent->deep = dirinfo.deep;
pCurrent->next = pCurrent->sub = NULL;
pCurrent->father = pFather;
if (fread(&dirinfo, 1, sizeof(dirinfo), fp) == sizeof(dirinfo))
{ if (dirinfo.deep > deep) readsubdir(fp, pCurrent, deep);
if (dirinfo.deep == deep)
{ pNext = malloc(sizeof(struct DIRTREE));
pCurrent->next = pNext;
pCurrent = pNext;
}
}
else dirinfo.deep = -1;
}
}
int readinfo(FILE *fp)
{ int deep;
/* Wurzelverzeichnis einlesen */
if (fread(&dirinfo, 1, sizeof(dirinfo), fp) != sizeof(dirinfo)) return 1;
root.next = root.father = root.sub = NULL;
root.name = strdup(dirinfo.name);
root.deep = dirinfo.deep;
if (fread(&dirinfo, 1, sizeof(dirinfo), fp) == sizeof(dirinfo))
readsubdir(fp, &root, 0);
fclose(fp);
return 0;
}
void writesubs(FILE *fp, struct DIRTREE *pDT)
{ int i;
unsigned char *p;
while (pDT)
{
strcpy(dirinfo.name, pDT->name);
for (i=strlen(pDT->name); i < 13; i++) dirinfo.name[i] = 0;
dirinfo.deep = pDT->deep;
dirinfo.isnotlast = pDT->next != NULL;
dirinfo.isfirst = pDT->father ? pDT->father->sub == pDT: 0;
if (fwrite(&dirinfo, 1, 16, fp) != 16)
{ fprintf(stderr, "error writing %s (disk full ?)\n", TreeInfo);
return;
}
p = (void*)&dirinfo;
for (i=0; i < 16; i++, p++) CheckSum += *p;
if (pDT->sub) writesubs(fp, pDT->sub);
pDT = pDT->next;
}
}
void writeinfo(void)
{ unsigned i;
unsigned char *p;
FILE *fp;
strcpy(header.ident, "PNCI");
header.numdir = NumDirs;
p = (void*)&header;
for (i = header.checksum = 0; i<7; i++, p++) header.checksum += *p;
fp = fopen(TreeInfo, "wb");
if (!fp)
{ fprintf(stderr, "error opening %s\n", TreeInfo);
return;
}
if (fwrite(&header, 1, sizeof(header), fp) != sizeof(header))
{ fprintf(stderr, "error writing %s (disk full ?)\n", TreeInfo);
return;
}
CheckSum = 0;
writesubs(fp, &root);
fwrite(&CheckSum, 1, sizeof(unsigned), fp);
fclose(fp);
}
void deleteEntry(struct DIRTREE *pDT)
{ struct DIRTREE *tmp;
while (pDT)
{
pDT->father = NULL;
if (pDT->name)
{ free(pDT->name);
pDT->name = NULL;
}
if (pDT->sub)
{ deleteEntry(pDT->sub);
free(pDT->sub);
pDT->sub = NULL;
}
tmp = pDT;
pDT = pDT->next;
free(tmp);
}
}
void subdir(char *path, struct DIRTREE *dir, int deep)
{ char *pp;
int done;
FF_STRUCT ff;
struct DIRTREE *dp;
pp = path + strlen(path); /* auf die abschließende 0 */
if (*(pp-1) != '\\')
{ *pp = '\\';
*(++pp) = 0;
}
deep++ ;
strcpy(pp, "*.*");
done = findfirst(path, &ff, 0x3F);
while (!done && !ISDIR(ff))
{ done = findnext(&ff);
}
if (done) dir->sub = NULL;
else
{ dir->sub = dp = malloc(sizeof(struct DIRTREE));
while (!done && dp)
{
dp->name = strdup(FF_NAME(ff));
NumDirs++;
dp->father = dir;
dp->deep = deep;
strcpy(pp, FF_NAME(ff));
subdir(path, dp, deep);
done = findnext(&ff);
while (!done && !ISDIR(ff))
{ done = findnext(&ff);
}
if (done) dp->next = NULL;
else
{ dp->next = malloc(sizeof(struct DIRTREE));
dp = dp->next;
}
}
}
}
void scandirs(void)
{ char path[129];
deleteEntry(root.sub);
if (root.name) free(root.name);
root.name = strdup("\\");
strcpy(path, root.name);
root.father = root.next = NULL;
root.deep = 0;
NumDirs = 1;
subdir(path, &root, 0);
}
void printdir(struct DIRTREE *pDT, long lines)
{ int i;
while (pDT)
{ for (i=1; i<pDT->deep; i++)
{ if (lines & (1L << i)) putchar(VSTRICH);
else putchar(' ');
putchar(' ');
}
if (pDT->deep)
{
if (pDT->next == NULL) putchar(WINKEL);
else putchar(VERBINDUNG);
putchar(HSTRICH);
}
puts(pDT->name);
printdir(pDT->sub, pDT->next ? lines | (1L << pDT->deep): lines);
pDT = pDT->next;
}
}
main(int argc, char **argv)
{ FILE *fp;
char Read, Show, Drive;
int i;
Read = Show = Drive = 0;
if (argc > 1) for (i=1; i<argc; i++)
{ if ((argv[i][0] == '/') || (argv[i][0] == '-'))
{ switch (toupper(argv[i][1]))
{ case 'R': Read = 1; break;
case 'S': Show = 1; break;
case 'H':
case '?':
printf( "TREEINFO [/r] [/s] [<drive>:]\n"
" /r - reread,\n"
" /s - show the directory tree"
" of specified drive\n");
return 0;
default:
printf("using: TREEINFO [/r] [/s] [<drive>:]\n");
return 0;
}
}
else if (argv[i][1] == ':') Drive = toupper(argv[i][0]) - '@';
}
else
{
printf("using: TREEINFO [/r] [/s] [<drive>:]\n");
return 0;
}
if (Drive == 0) Drive = bdos(0x19,0,0) + 1;
TreeInfo[0] = Drive + '@';
if (!Read)
{ fp = validate();
Read = fp ? readinfo(fp): 1;
}
if (Read)
{ scandirs();
writeinfo();
}
if (Show) printdir(&root, 0);
return 0;
}
Vorgefundene Kodierung: ANSI (CP1252) | 4
|
|