Операционная система 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".  | 

