DPBPtr->nFARsec,FatAnchor);
};
};
} else {
printf ("Не могу найти нестертый файл %s%s\n",
dname,sspec);
};
};
/* **** Найти следующий кластер в цепи ********************
Эта стандартная программа находит значение элемента FAT.
Это эквивалентно соединению кластеров FAT в цепь. Эта стан-
дартная программа возвращает либо значение кластера (следую-
щий кластер в цепи файлов операционной системы DOS) либо ну-
левое значение NULL, если в цепи больше нет кластеров.
Если диск имеет емкость 10 Мегабайт или меньше, то использу-
ются 12-битовые элементы таблицы FAT (кластеры). Если диск больше,
то используются 16-битовые элементы таблицы FAT.
Значения кластера: (0)000 ................ свободный кластер
(0)001 ................ неопределен
(0)002 -(F)FEF......... следующий кластер
(F)FF0 -(F)FF6......... зарезервирован
(F)FF7 ................ испорченный кластер
(F)FF8 -(F)FFF......... конец цепи
*/
WORD get_cluster (clust) /* номер кластера */
WORD clust;
{
union { WORD FAR }* w; /* указатель на таблицу FAT */
BYTE far * b;
}fatptr;
WORD value; /* содержимое кластера */
if (TotSect > TENMB){
fatptr.b=(BYTE far *)
((DWORD) FatAnchor + (DWORD)(clust * 2));
value = *fatptr.w;
} else {
fatptr.b= (BYTE far *)
((DWORD) FatAnchor + (DWORD)(clust * 3/2));
value = *fatptr.w;
- 11-64 -
/* Кластеры с нечетными номерами сдвигаются влево */
/* на 4 бита в слове */
if (clust & 0x01) value >>= 4;
value &= 0x0fff;
} ;
if ((value & 0x0ff0) EQ 0xff0) return (CHAIN_END);
else return (value);
} ;
/* **** Сохранить значение кластера *************************
Эта стандартная программа помещает значение в элемент
кластера в таблице FAT, если диск имеет емкость 10 Мегабайт
пользуются 12-битовые элементы таблицы FAT (кластеры). Если
диск больше, то используются 16-битовые элементы таблицы FAT.
*/
void put_cluster (clust,value)
WORD clust; /* номер кластера */
WORD value; /* значение нового кластера */
{
union { WORD FAR }* w; /* указатель на таблицу FAT */
BYTE far * b;
}fatptr ;
WORD cur_val; /* значение текущего кластера */
if (TotSect > TENMB) {
fatptr.b=(BYTE far *)
((DWORD) FatAnchor + (DWORD) (clust * 2));
*fatptr.w=value;
} else {
fatptr.b= (BYTE far *)
((DWORD)FatAnchor + (DWORD)(clust * 3/2));
cur_val = *fatptr.w;
/* Кластеры с нечетными номерами сдвигаются влево */
/* на 4 бита в слове */
if (clust & 0x01)
*fatptr.w = (cur_val & 0x000f) ¦ (значение << 4);
else
*fatptr.w = (cur_val & 0xf000) ¦ (значение & 0x0fff);
} ;
};
/* *** Найти кластер файла и сохранить каталог и
таблицу FAT файла ***
Эта программа восстанавливает стертый файл, если это
можно. Она вычисляет количество кластеров, которые должен
занимать файл, и ищет эти кластеры в таблице FAT.
Эта стандартная программа предполагает, что номер на-
чального кластера файла, подлежащего восстановлению, был
проверен, и его значение равно нулю.
*/
- 11-65 -
BOOL savefile (dnum,dptr,sect,ch)
WORD dnum ; /* рабочий дисковод */
DENTRY near * dptr ; /* элемент каталога, */
/* подлежащий сохранению */
WORD sect ; /* дать оглавление секторов */
/* кластера */
BYTE ch ; /* первый символ в имени файла */
{
DENTRY far * writeptr ; /*указатель на буфер каталога*/
WORD filecls ; /* размер файла (в кластерах) */
WORD last ; /* номер последнего кластера */
WORD current ; /* номер текущего кластера */
WORD next ; /* следующий кластер в цепи */
WORD fatsect ; /* номер сектора таблицы FAT */
union { WORD FAR }* w ; /* указатель на таблицу FAT */
BYTE far * b ;
} fatptr ;
if (dptr->attrib & FATR_SUBDIR) /* если файл находится в */
/* подкаталоге */
filecls = 0 ; /* дополнений не нужно */
else
filecls = (WORD) ((dptr->fsize + (DWORD)BytClust-1L)/
(DWORD) BytClust) -1 ;
current = last =dptr->cluster ; /* первый кластер */
/* Исправление таблицы FAT */
while (filecls) {
if (++current > DPBPtr->TotClust) {
print ("\n*** Нельзя восстановить файл ***/n");
return (FALSE) ;
} ;
if (get_cluster(current) EQ 0) { /* пустой кластер */
put_cluster (last,current) ; /* часть цепи */
last = current ;
filecls-- ;
} ;
} ;
put_cluster (last, FILE_END) ; /* конец цепи */
*(dptr->name) = ch ; /* сохранить первый символ */
/* Подготовка завершена - писать сектора таблицы FAT */
/* и каталога */
writeptr = DirFnchor ;
fatsect = DPBPtr->Reserve ;
disckwrite (dnum,fatsect,DPBPtr->nFATsec,FatAnchor) ;
fatsect += DPBPtr->FATsec ;
disckwrite (dnum,fatsect,DPBPtr->nFATsec,FatAnchor) ;
disckwrite (dnum,sect,ClUnit,writeptr) ;
dbos (DFUNC_RESETDSK,NULL,NULL);
return(TRUE)) ;
} ;
/* **** Найти определенный элемент в этом каталоге **** */
- 11-66 -
DENTRY near * findf (dnum,sect,pptr,dbuf,bptr,sattr,mtype)
WORD dnum ; /* рабочий дисковод */
WORD * sect ; /* сектор текущего каталога*/
char near * pptr ; /* указатель имени пути доступа*/
DENTRY near * dbuf ; /* буфер каталога */
DENTRY near * bptr ; /* указатель другого буфера */
BYTE sattr ; /* атрибут поиска */
int mtipe ; /* требуемый тип совпадения */
{
int i ; /* счетчик циклов */
WORD cluster ; /* используется для сцепления */
DENTRY near * dirptr ; /* указатель буфера каталога*/
DENTRY far * readptr ; /*указатель буфера каталога*/
DENTRY near * dirend ; /* адрес конца буфера */
readptr = dbuf ;
dirend = (DENTRY near *) ((WORD) dbuf + BitClust - 1) ;
while (TRUE) {
if (bptr NE NULL) { /* продолжить с ... */
dirptr =++bptr ; /* того места, где */
/* остановились */
bptr = NULL ;
} else { /* иначе, начать с начала */
diskread (dnum,*sect,ClUnit,readptr) ;
dirptr = dbuf ;
} ;
/* Eсть ли совпадающие файлы ? */
while (dirptr < dirend) {
if (((dirptr->attrib & sattr) EQ sattr) AND
(match (pptr,dirptr->name,mtype)))
return (dirptr) ;
dirptr++ ;
} ;
/* Bсе элементы в этом кластере приведены, перейти к */
/* другому */
if (*sect >=DPBPtr->DataSect) { /* подкаталог */
cluster = cluster_of (*sect) ; /* следующий кластер*/
if ((cluster = get_cluster (cluster)) LE CHAIN_END)
return (NULL) ;
else *sect = (sector_of (cluster)) ;
} else /* корневой каталог */
if (*sect >= DPBPtr->DIRSect) {
*sect += ClUnit ; /* следующие сектора */
if (*sect >=DPBPtr->DATASect) return (NULL) ;
} else return (NULL) ;
} ;
} ;
/* **** Получить блок параметров системы BIOS ****** */
/* **** для заданного дисковода ********* */
DPB far *getdpb (dnum) /* возврат указателя на блок DPB */
Word dnum ; /* номер рабочего дисковода */
- 11-67 -
{
union REGS inregs, outregs ;
struct SREGS segregs ;
LONGPTR farptr ;
inregs.h.ah = DFUNC_GETDPB ;
inregs.h.dl = dnum + 1 ;
intdosx (&inregs, &outregs, &segregs) ; /*получить блок DPB*/
if (outregs.x.cflag) {
if (outregs.h.al EQ 0xff)
print ("*** Дисковод %c неисправен ***\n",(dnum + 'A')) ;
else
printf ("*** Не могу считать параметры дисковода %c ***\n",
(dnum + 'A')) ;
exit (1) ;
} ;
farptr.a.off = outregs.x.bx ;
farptr.a.seg = segregs.ds ;
return ((DPB far *) farptr.ptr ;
} ;
/* **** Чтение/запись на диск прямого доступа *********** */
void diskaccess ((function, dnum, sector, count, buffer)
BYTE function ; /* функция прерывания */
BYTE dnum ; /* номер физического дисковода */
WORD sector ; /* номер сектора */
WORD count ; /* счет секторов */
BYTE far * buffer ; /* буфер */
{
union REGS inregs, outregs ;
struct SREGS segregs ;
LONGPTR farptr ;
farptr.ptr = buffer ;
inregs.h.al = dnum ;
inregs.x.dx = sector ;
inregs.x.cx = count ;
inregs.x.bx = farptr.a.off ;
segregs.ds = farptr.a.seg ;
int86x (function,&inregs,&outregs,&segregs) ;
if (outregs.x.cflag) {
if (function EQ ABC_READ)
printf ("*** Ошибка во время считывания диска ***\n") ;
else