Операционная система MS-DOS© Александр Фролов, Григорий ФроловТом 1, книги 1-2, М.: Диалог-МИФИ, 1991. 2.4. Таблица файлов MS-DOSDOS создает таблицу открытых файлов и помещает ее адрес в поле file_tab векторной таблицы связи. В этой таблице для каждого открытого файла хранится такая информация, как количество файловых чисел (file handle), связанных с данным файлом, режим открытия файла (чтение, запись и т.д.), слово информации об устройстве, указатель на заголовок драйвера, обслуживающего данное устройство, элемент дескриптора файла (дата, время, имя файла, номер начального кластера, распределенного файлу), номер последнего прочитанного кластера и т.д. Эта информация может пригодиться при организации защиты программы от копирования путем ее привязки к номерам занимаемых программой кластеров. Заметьте, что получить информацию о начальном кластере файла довольно трудно - стандартные средства DOS не предоставляют такой возможности. Приходится работать с диском на уровне секторов, отслеживать FAT, читать напрямую каталог и т.д. Таблица файлов содержит этот номер в явном виде. Строка файла CONFIG.SYS может содержать оператор FILES=xx. Этот оператор в конечном счете определяет размер таблицы файлов DOS (DFT). Каждая таблица DFT содержит указатель на следущую таблицу и количество управляющих блоков файлов DOS (DFCB). Сами блоки DFCB (по одному для каждого файла) расположены в конце таблицы DFT. Формат этого блока различается для DOS 3.х и 4.х. Информация по некоторым полям отсутствует. И хотя эти поля отмечены как резервные, на самом деле они используются, но неизвестно как. Приведем сначала формат таблицы файлов для DOS 3.х:
Операционная система MS-DOS версии 4.х отличается расположением поля last_clu, кроме того изменилась длина DFCB:
Для версии MS/DOS 4.01 файл sysp.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 struct _DFT_ {
struct _DFT_ far *next;
unsigned file_count;
DFCB dfcb;
} DFT;
Приведем текст программ, возвращающих указатели на первый и последующий элементы списка таблиц файлов DOS:
/**
*.Name get_fdft
*
*.Title Получить адрес первой DTF
*
*.Descr Функция возвращает адрес первой таблицы файлов DOS
*
*.Params DTF far *get_fdtf(CVT far *cvt)
*
* cvt - адрес векторной таблицы связи
*
*.Return Указатель на первый блок DDCB
**/
#include <stdlib.h>
#include <stdio.h>
#include "sysp.h"
DFT far *get_fdft(CVT far *cvt) {
DFT far * dft;
dft = cvt->file_tab;
return(dft);
}
/**
*.Name get_ndft
*
*.Title Получить адрес следующей DTF
*
*.Descr Функция возвращает адрес следующей
* таблицы файлов DOS или 0, если это последняя таблица
*
*.Params DFT far *get_ndft(DFT far *dft)
*
* dft - адрес предыдущей таблицы DFT
*
*.Return Указатель на следующую DFT или 0, если последняя
**/
#include <dos.h>
#include <stdlib.h>
#include <stdio.h>
#include "sysp.h"
DFT far *get_ndft(DFT far *dft) {
DFT far * dft_next;
dft_next = dft->next;
if(FP_OFF(dft_next) == 0xffff) return((DFT far *)0);
return(dft_next);
}
Для подробной распечатки содержимого таблицы файлов можно использовать следующую программу, которая была проверена в MS-DOS версии 4.01:
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include "sysp.h"
void main(void);
void main(void)
{
CVT far *cvt;
DFT far *dft;
unsigned i,j,k;
DFCB far *dfcb;
FILE *list;
printf("Информация об открытых файлах DOS\n"
"Copyright Frolov A. (C),1990\n");
// Открываем файл для вывода информации о файлах
list=fopen("!dfcb.lst","w+");
fprintf(list,"Информация об открытых файлах DOS\n"
"Copyright Frolov A. (C),1990\n\n");
cvt=get_mcvt(); // Адрес векторной таблицы связи
dft=get_fdft(cvt); // Адрес начала таблицы файлов
for(;;) {
if(dft == (DDCB far *)0) break; // Конец таблицы
i=dft->file_count;
fprintf(list,"Таблица файлов DFT: %Fp, в ней %d
файлов\n"
"===========================================\n",
dft,i);
for(j=0;j<i;j++) { // Цикл по файловым
// управляющим блокам
dfcb=(&(dft->dfcb))+j; // Адрес DFCB файла
fprintf(list,"\nDFCB файла: %Fp\n\n",dfcb);
fprintf(list,"Имя файла: ");
for(k=0;k<11;k++) {
fputc(dfcb->filename[k],list);
}
fprintf(list,"\nКоличество file handles: %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",
dfcb->handl_num,
dfcb->access_mode,
dfcb->reserv1,
dfcb->dev_info,
dfcb->driver,
dfcb->first_clu,
dfcb->time,
dfcb->date,
dfcb->fl_size,
dfcb->offset,
dfcb->reserv2,
dfcb->last_clu,
dfcb->ownr_psp,
dfcb->reserv7);
}
dft=get_ndft(dft);
}
fclose(list);
exit(0);
}
Описание содержимого таблицы файлов будет записано в файл с именем "!dfcb.lst". |

