#define CHAIN_END 1 /* используется функцией */
/* "get_cluster ()" для */
/* обозначения конца файла*/
#define FILE_END 0xfff8 /* элемент таблицы FAT для */
/* конца файла */
/* стандартная программа match() для совпадающих типов*/
#define NO_MATCH 0 /* не совпадают*/
#define IS_MATCH 1 /* совпадают */
#define IS_ERASED 2 /* со стертыми файлами */
#define IS_UNIQUE 4 /* со нестертыми файлами */
#define DNAME_SIZE 80 /* максимальный размер имени в */
/* каталоге */
/* ОПРЕДЕЛЕНИЕ СТРУКТУР И ТИПОВ */
typedef unsigned int BOOL;
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
typedef union {
BYTE far * ptr;
struct {
WORD off ;
WORD seg ;
} a;
} LONGPTR ;
typedef struct dpbbuf { /* буфер блока дисковых пара- */
/* метров */
BYTE PhysDrive; /* номер дисковода */
Byte DriverUnit ; /* номер узла в пределах дис- */
/* ковода */
WORD BytesSector ; /* количество байтов в секторе */
BYTE SectorsCluster ; /* количество секторов в кластере
/* минус 1 */
BYTE ClusterShift; /* сдвиг кластера */
WORD Reserve; /* количество зарезервированных
/* секторов */
BYTE NumberOfFATs; /* копии таблицы FAT */
WORD DirEntries; /* количество элементов корне- */
/* вого каталога */
WORD DataSect; /* первый сектор данных */
- 11-60 -
WORD TotClust; /* общее количество кластеров */
/* плюс 1 */
BYTE nFATsec; /* количество секторов таблицы */
/* FAT (1 таблица FAT) */
WORD DirSect; /* номер сектора каталога */
DWORD DevHeaderAddr; /* адрес головки дисковода */
BYTE MediaByte; /* байт описателя носителя */
BYTE DiskAccFlag; /* признак доступа к диску */
DWORD NextBlockAddr; /* адрес следующего блока диска */
} DPB;
typedef struct dirbuf { /* элемент каталога диска */
char name [8]; /* имя */
char ext [3]; /* расширение */
BYTE attrib ; /* атрибут */
BYTE reserved [10];
WORD time ; /* время: часы минуты- */
/* -минуты секунды */
WORD date ; /* дата: год месяц-месяц день */
WORD cluster ; /* начальный кластер */
DWORD fsize ; /* общий размер в байтах */
} DENTRY;
/* Г Л О Б А Л Ь Н Ы Е П Е Р Е М Е Н Н Ы Е * /
DPB far * DPBPtr ; /* указатель блок параметров */
/* диска (DPB) */
WORD ClUnit ; /* количество секторов в */
/* кластере (а также размер */
/* буфера каталога) */
WORD ByteClust ; /* количество байтов в */
/* кластере */
DWORD TotSect ; /* общее количество секторов */
/* на диске */
WORD FATSize ; /* количество байтов в таб- */
/* лице FAT */
WORD far * FatAnchor ; /* адрес буфера таблицы FAT */
DENTRY near * DirAnchor ; /* адрес буфера каталога */
DENTRY near * AltAnchor ; /* адрес буфера другого ка- */
/* талога */
char defalt_sname [] ={"*.*"}; /* имя поиска по умол- */
/* чанию */
/* ОПРЕДЕЛЕНИЕ ПСЕВДО-СТAHДАРТНЫХ ПОДПРОГРАММ */
#define diskread(d,s,c,b) diskaccess(ABS_READ,d,s,c,b)
#define diskwrite(d,s,c,b) diskaccess(ABS_WRITE,d,s,c,b)
#define sector_of(cl) (DPBPtr->DataSect+(cl-CL_OFF)*ClUnit)
#define cluster_of(sec) (CL_OFF+(sec-DPBPtr->DataSect)/ClUnit)
/* ПРЕДВАРИТЕЛЬНЫЕ ОБЪЯВЛЕНИЯ СТAHДАРТНОЙ ПОДПРОГРАММЕ */
WORD get_cluster (); /* получить значение элемента */
/* кластера */
void put_cluster (); /* сохранить значение в клас- */
/* тере */
BOOL savefile (); /* восстановить файл(ы) */
DENTRY near * findt (); /* просмотр буфера каталога */
- 11-61 -
DPB far * getdpb () ; /* получить адрес блока пара- */
/* метров диска */
void diskaccess () ; /* абсолютное чтение/запись */
/* диска */
BOOL match () ; /* соответствие определенного */
/* имени с файлом */
/* *******************************************************
/*
/* Главная точка входа
/*
/* *******************************************************
main (argc,argv,envp)
int argc ;
char * argv [] ;
char * envp [] ;
}
char near * sspec ; /* характеристика поиска */
char dname [DNAME_SIZE]; /* буфер имени каталога */
char * pptr ; /* указатель на каталоговое
/* имя */
WORD dnum ; /* номер дисковода (исход- */
/* ное значение 0) */
WORD snum ; /* номер сектора каталога */
WORD savenum ; /* используется для хра- */
/* нения */
/* значения snum */
DENTRY near * dptr ; /* элемент текущего каталога */
print ("\nRESCUE, Version 2.OO\n\n");
if (argc<2) { /* если параметров нет */
print ("*** Имя файла не указано ***\n");
exit (1) ;
};
sspec =argv [1]; /* файл для восстановления */
getcwd (dname, DNAME_SIZE) ; /* получить дисковод по */
/* умолчанию и каталог */
if (*(char *)((WORD)dname + strlen(dname) - 1) NE '\\')
strcat (dname, "\\"); /* имя пути доступа за- */
/* канчивается знаком "\"*/
pptr = dname+3; /* указатель начального */
/* имени пути доступа*/
dnum = *dname - 'A' ; /* извлечь номер дисковода */
/* Определить разные глобальные значения из блока парамет- */
/* ров диска (DPB), включая размер таблицы FAT, количество */
/* байтов в кластере, общее количество секторов и т.д. */
DPBPtr = getdpb (dnum) ; /* получить блок параметров диска */
if(dnum NE DPBPtr->PhysDrive) {
printf ("Дисковод %c: является замененным\n",(dnum+ 'A'));
printf("Программа RESCUE будет работать только
на физических дисководах\n");
exit (1);
} ;
- 11-62 -
FATSize = DPBPtr->BytesSector * DPBPtr->nFATsec:
CLUnit = DPBPtr->SectorsCluster + 1;
TotSect = (DWORD) DPBPtr->TotClust * (DWORD) ClUnit
+ (DWORD) DPBPtr->DataSect;
BytCLust= DPBPtr->BytesSector * CLUnit;
/* Pаспределить память для буферов каталога и таблиц FAT */
If (((DirAnchor=(Dentry near *) malloc(BytClust)) EQ
NULL) OR
((AltAnchor=(DENTRY near *) malloc(BytCLust)) EQ
NULL) OR
((FATAnchor=(WORD far *)_fmalloc(FATSize)) EQ
NULL)) {
printf ("*** Can't Allocate Working Memory ***\n");
exit (1);
} ;
/* Cчитать в исходную таблицу FAT */
discread (dnum,DPBPtr->Reserve,DPBPtr->nFATsec,FATAnchor);
/* Двигаться по цепи элементов каталога в поисках */
/* соответствующего имени пути доступа */
snum = DPBPtr->Dirsect; /* первый сектор каталога */
while (*pptr NE '\0') /* до тех пор, пока путь */
/* доступа к каталогу ненулевой */
if ((dptr = findf (dnum, &snum, pptr, DirAnchor,
NULL,FATR_SUBDIR,IS_INIQUE)) NE NULL) {
snum = sector_of (dptr->cluster);
while ((*pptr NE '\0') AND (*pptr NE '\\'))
pptr++;
if (*pptr EQ '\\') pptr++;
} else {
printf ("*** Can't Find Directory %s ***\n",
pptr);
exit (1); };
/* Ненормальное завершение, если файл, подлежащий */
/* восстановлению, не стерт. */
savenum = snum; /* сохранить сектор каталога */
if (findf (dnum, &dnum, sspec, DirAnchor,
NULL,FATR_NONE,IS_UNIQUE) NE NULL) {
printf ("***%s%s не стерто ***\n",dname,sspec);
exit (1) ;
};
/* Eсли файл стерт, подкаталог или файл затем */
/* восстанавливает его */
snum = savenum; /* восстановить сектор каталога */
if ((dptr = findf (dnum,&snum,sspec, DirAnchor,
NULL,FATR_NONE,IS_ERASED)) NE NULL){
if(get_cluster (dptr->cluster) NE 0)
printf ("Hестертый файл%s%s не может быть
восстановлен\n",
- 11-63 -
dname, sspec);
else {
if (savefile (dnum,dptr, snum,toupper(*sspec))) {
if (dptr->attrib & FATR_SUBDIR)
print ("Подкаталог %s%s восстановлен\n,
dname,sspec);
else
printf ("Файл %s%s восстановлен\n",
dname,sspec);
} else {
printf (Неудачное восстановление %s%s\n",
dname,sspec);
diskread (dnum,DPBPtr->Reserve,