MS-DOS для программиста© Александр Фролов, Григорий ФроловТом 18, М.: Диалог-МИФИ, 1995, 254 стр. 2.6. Системная таблица файлов SFTMS-DOS создает системную таблицу файлов SFT (System File Table ) и помещает ее адрес в поле file_tab векторной таблицы связи. В этой таблице для каждого открытого файла хранится такая информация, как количество файловых идентификаторов, связанных с данным файлом, режим открытия файла (чтение, запись и т. д.), слово информации об устройстве, указатель на заголовок драйвера, обслуживающего данное устройство, элемент дескриптора файла (дата, время, имя файла, номер начального кластера, распределенного файлу), номер последнего прочитанного кластера и т. д. Эта информация может пригодиться, например, при организации защиты программы от копирования путем ее привязки к номерам занимаемых файлом программы кластеров. Заметьте, что получить информацию о начальном кластере файла довольно трудно - стандартные средства MS-DOS не предоставляют такой возможности. Приходится работать с диском на уровне секторов, отслеживать списки кластеров в таблице размещения файлов FAT , читать каталоги напрямую по секторам диска и т. д. Таблица файлов содержит этот номер в явном виде. Строка файла config.sys может содержать оператор files=xx. Этот оператор, в конечном счете, определяет размер таблицы SFT . Формат таблицы SFTКаждая таблица SFT содержит указатель на следующую таблицу, а также количество управляющих блоков файлов DFCB . Приведем формат таблицы SFT :
Блоки DFCB (по одному для каждого файла) расположены в конце таблицы SFT и имеют следующий формат:
Приведем соответствующие типы данных: typedef struct _DFCB _
{
unsigned handl_num;
unsigned char access_mode;
unsigned reserv1;
unsigned dev_info;
void far *driver;
unsigned first_clu;
unsigned time;
unsigned date;
unsigned long fl_size;
unsigned long offset;
unsigned reserv2;
unsigned reserv7;
unsigned reserv3;
char reserv4;
char filename[11];
char reserv5[6];
unsigned ownr_psp;
unsigned reserv6;
unsigned last_clu;
char reserv8[4];
} DFCB ;
typedef struct _SFT _
{
struct _SFT _ far *next;
unsigned file_count;
DFCB dfcb;
} SFT ;
Программа SFTLISTДля подробной распечатки содержимого таблицы файлов можно использовать программу SFTLIST (листинг 2.5), которая была проверена в MS-DOS версии 6.22. Листинг 2.5. Файл sftlist\sftlist.cpp #include <dos.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct _DFCB _
{
unsigned handl_num;
unsigned char access_mode;
unsigned reserv1;
unsigned dev_info;
void far *driver;
unsigned first_clu;
unsigned time;
unsigned date;
unsigned long fl_size;
unsigned long offset;
unsigned reserv2;
unsigned reserv7;
unsigned reserv3;
char reserv4;
char filename[11];
char reserv5[6];
unsigned ownr_psp;
unsigned reserv6;
unsigned last_clu;
char reserv8[4];
} DFCB ;
typedef DFCB far* LPDFCB;
typedef struct _DFT_
{
struct _DFT_ far *next;
unsigned file_count;
DFCB dfcb;
} SFT ;
typedef SFT far* LPSFT;
typedef struct
{
unsigned mcb_seg;
void far *dev_cb;
void far *file_tab;
void far *clock_dr;
void far *con_dr;
unsigned max_btbl;
void far *disk_buf;
void far *drv_info;
void far *fcb_tabl;
unsigned fcb_size;
unsigned char num_bdev;
unsigned char lastdriv;
} CVT ;
typedef CVT far* LPCVT ;
void main(void);
LPSFT get_fsft(LPCVT cvt);
LPSFT get_nsft(LPSFT sft);
void main(void)
{
union REGS regs;
struct SREGS sregs;
LPCVT lpCVT;
LPSFT lpSFT;
unsigned i,j,k;
LPDFCB lpDFCB;
FILE * list;
printf("Информация об открытых файлах MS-DOS\n"
"(C) Фролов А.В., 1995\n");
// Открываем файл для вывода информации о файлах
list = fopen("!sft.lst","w+");
fprintf(list,"Информация об открытых файлах MS-DOS\n"
"(C) Фролов А.В., 1995\n\n");
// Получаем адрес векторной таблицы связи
regs.h.ah = 0x52;
intdosx (®s, ®s, &sregs);
// Передвигаем указатель на поле msb_seg
lpCVT = (LPCVT )MK_FP (sregs.es, regs.x.bx - 2);
lpSFT = get_fsft(lpCVT);
for(;;)
{
if(lpSFT == NULL) break;
i = lpSFT->file_count;
fprintf(list,"Таблица файлов SFT : %Fp, в ней %d файлов\n"
"===========================================\n",
lpSFT, i);
for(j=0; j<i; j++)
{
lpDFCB = (&(lpSFT->dfcb)) + j; // Адрес DFCB файла
fprintf(list,"\nDFCB файла: %Fp\n\n", lpDFCB);
fprintf(list,"Имя файла: ");
for(k=0; k<11; k++)
fputc(lpDFCB->filename[k], list);
fprintf(list,
"\nКоличество идентификаторов: %d\n"
"Режим доступа: %d\n"
"Поле reserv1: %04X\n"
"Информация об устройстве: %04X\n"
"Адрес драйвера: %Fp\n"
"Начальный кластер: %d\n"
"Время: %04X\n"
"Дата: %04X\n"
"Размер файла в байтах: %ld\n"
"Текущее смещение в файле: %ld\n"
"Поле reserv2: %04X\n"
"Последний прочитанный кластер: %d\n"
"Сегмент PSP владельца файла: %04X\n"
"Поле reserv7: %d\n"
"-------------------------------\n\n",
lpDFCB->handl_num, lpDFCB->access_mode,
lpDFCB->reserv1, lpDFCB->dev_info,
lpDFCB->driver, lpDFCB->first_clu,
lpDFCB->time, lpDFCB->date,
lpDFCB->fl_size, lpDFCB->offset,
lpDFCB->reserv2, lpDFCB->last_clu,
lpDFCB->ownr_psp, lpDFCB->reserv7);
}
lpSFT = get_nsft(lpSFT);
}
fclose(list);
}
LPSFT get_nsft(LPSFT sft)
{
LPSFT sft_next;
sft_next = sft->next;
if(FP_OFF (sft_next) == 0xffff)
return((LPSFT)NULL);
return(sft_next);
}
LPSFT get_fsft(LPCVT cvt)
{
LPSFT sft;
sft = (LPSFT)cvt->file_tab;
return(sft);
}
После запуска этой программы в файл с именем "!dfcb.lst" будет записано содержимое таблицы файлов. |

