Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

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

© Александр Фролов, Григорий Фролов
Том 1, книги 1-2, М.: Диалог-МИФИ, 1991.

[Назад] [Содержание] [Дальше]

2.4. Таблица файлов 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".

[Назад] [Содеожание] [Дальше]