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" будет записано содержимое таблицы файлов. |