Операционная система MS DOS

Таблица файлов MS-DOS


DOS создает таблицу открытых файлов и помещает ее адрес в поле file_tab векторной таблицы связи. В этой таблице для каждого открытого файла хранится такая информация, как количество файловых чисел (file handle), связанных с данным файлом, режим открытия файла (чтение, запись и т.д.), слово информации об устройстве, указатель на заголовок драйвера, обслуживающего данное устройство, элемент дескриптора файла (дата, время, имя файла, номер начального кластера, распределенного файлу), номер последнего прочитанного кластера и т.д.

Эта информация может пригодиться при организации защиты программы от копирования путем ее привязки к номерам занимаемых программой кластеров. Заметьте, что получить информацию о начальном кластере файла довольно трудно - стандартные средства DOS не предоставляют такой возможности. Приходится работать с диском на уровне секторов, отслеживать FAT, читать напрямую каталог и т.д. Таблица файлов содержит этот номер в явном виде.

Строка файла CONFIG.SYS может содержать оператор FILES=xx. Этот оператор в конечном счете определяет размер таблицы файлов DOS (DFT). Каждая таблица DFT содержит указатель на следущую таблицу и количество управляющих блоков файлов DOS (DFCB). Сами блоки DFCB (по одному для каждого файла) расположены в конце таблицы DFT.

Формат этого блока различается для DOS 3.х и 4.х. Информация по некоторым полям отсутствует. И хотя эти поля отмечены как резервные, на самом деле они используются, но неизвестно как.

Приведем сначала формат таблицы файлов для DOS 3.х:



(0) 4 next указатель на следующую таблицу файлов
(+4) 2 file_count количество файлов в этой таблице
  --- Дальше идут блоки DFCB в количестве file_count штук ----
(0) 2 handl_num количество файловых чисел, связанных с данным файлом (file handle)
(+2) 1 access_mode режим доступа к файлу, заданный при открытии файла
(+3) 2 reserv1 зарезервировано
(+5) 2 dev_info информация IOCTL, полученная для устройства, на котором расположен этот файл (подробно формат и назначение этого поля будут рассмотрены в главе, посвященной драйверам)
(+7) 4 driver указатель на драйвер, обслуживающий устройство, содержащее файл
(+11) 2 first_clu номер первого кластера, распределенного файлу
(+13) 2 time время последнего изменения файла в упакованном формате
(+15) 2 date дата последнего изменения файла в упакованном формате
(+17) 4 fl_size размер файла в байтах
(+21) 4 offset текущее смещение внутри файла в байтах
(+25) 2 reserv2 зарезервировано
(+27) 2 last_clu номер только что прочитанного кластера
(+29) 3 reserv3 зарезервировано
(+32) 11 filename имя файла в формате FCB (имя выровнено на левую границу поля, дополнено пробелами до 8 символов, справа к нему прилегает 3 символа расширения без точки)
(+43) 2 reserv4 зарезервировано
(+45) 2 ownr_psp PSP программы, открывшей файл
(+47) 2 reserv5 зарезервировано
<
Операционная система MS-DOS версии 4. х отличается расположением поля last_clu, кроме того изменилась длина DFCB:

(0) 4 next указатель на следующую таблицу файлов
(+4) 2 file_count количество файлов в этой таблице
    --- Дальше идут блоки DFCB в количестве file_count штук ----
(0) 2 handl_num количество файловых чисел, связанных с данным файлом (file handle)
(+2) 1 access_mode режим доступа к файлу, заданный при открытии файла
(+3) 2 reserv1 зарезервировано
(+5) 2 dev_info информация IOCTL, полученная для устройства, на котором расположен этот файл (подробно формат и назначение этого поля будут расмотрены в главе, посвященной драйверам)
(+7) 4 driver указатель на драйвер, обслуживающий устройство, содержащее файл
(+11) 2 first_clu номер первого кластера, распределенного файлу
(+13) 2 time время последнего изменения файла в упакованном формате
(+15) 2 date дата последнего изменения файла в упакованном формате
(+17) 4 fl_size размер файла в байтах
(+21) 4 offset текущее смещение внутри файла в байтах
(+25) 2 reserv2 зарезервировано
(+27) 2 reserv7 зарезервировано
(+29) 3 reserv3 зарезервировано
(+32) 1 reserv4 зарезервировано
(+33) 11 filename имя файла в формате FCB (имя выравнено на левую границу поля, дополнено пробелами до 8 символов, справа к нему прилегает 3 символа расширения без точки)
(+44) 2 reserv5 зарезервировано
(+46) 2 ownr_psp PSP программы, открывшей файл
(+48) 2 reserv6 зарезервировано
(+50) 2 last_clu номер только что прочитанного кластера
(+52) 4 reserv8 зарезервировано

Для версии 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".

Содержание раздела