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

MS-DOS для программиста

© Александр Фролов, Григорий Фролов
Том 18, М.: Диалог-МИФИ, 1995, 254 стр.

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

2.6. Системная таблица файлов SFT

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

Эта информация может пригодиться, например, при организации защиты программы от копирования путем ее привязки к номерам занимаемых файлом программы кластеров.

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

Строка файла config.sys может содержать оператор files=xx. Этот оператор, в конечном счете, определяет размер таблицы SFT .

Формат таблицы SFT

Каждая таблица SFT содержит указатель на следующую таблицу, а также количество управляющих блоков файлов DFCB .

Приведем формат таблицы SFT :

Смещение, байт Размер, байт Имя поля Описание
0 4 next Указатель на следующую таблицу файлов SFT
4 2 file_count Количество файлов, описанных в этой таблице с помощью блоков DFCB

Блоки DFCB (по одному для каждого файла) расположены в конце таблицы SFT и имеют следующий формат:

Смещение, байт Размер, байт Имя поля Описание
0 2 handl_num Количество идентификаторов, связанных с данным файлом
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 Зарезервировано

Приведем соответствующие типы данных:

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

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