На главную
Подписка
Новости










Главная / MS-DOS / MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА / Глава 10 / Использование программы контроля RESCUE Сделать домашней страницей Добавить в избранное Написать писмо

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Использование программы контроля RESCUE

Программа, описанная листингом 11-4, очень проста в использовании. После набора команды RESCUE задается имя стертого файла. Команда RESCUE требует задания только имени файла, то есть, заданные по умолчанию дисковод и каталог, содержащие стертый файл, должны быть установлены командой CHDIR (или сокращенно - CD) до запуска программы RESCUE. Подлежащий стиранию файл может быть файлом любого типа: обычным, скрытым, системным, доступным только по чтению или расположенным в подкаталоге. Если вы восстанавливаете файл, находящийся в подкаталоге, который тоже был стерт, или, если вы хотите проконтролировать все дерево каталога, расположенное ниже стертого подкаталога, вы должны сначала восстановить этот подкаталог по имени, используя команду RESCUE; создать заново подкаталог в заданном по умолчанию каталоге (используя команду CHDIR или CD) и затем вручную восстановить стертый файл (файлы) в подкаталоге, используя программу RESCUE.


Если имя файла найдено в каталоге (корневом каталоге или подкаталоге), будет произведена попытка проведения восстановления файла путем анализа и записи информации в таблицу FAT. Если файл не был найден, или, если было обнаружено, что он не уделен, на экране дисплея появится сообщение об этом. Как пояснялось ранее, путь доступа, проходящий через таблицу FAT для заданного файла, может быть сложным. Если программа RESCUE не сможет найти путь размещения файла (может быть он был сложно переплетен с путем доступа к другому файлу) выполнение программы завершается и никакая информация не записывается на диск. Важным фактором в работе программы является то, что она не будет записывать любую информацию на диск до тех пор, пока все проблемы, связанные с файлом, не будут разрешены. Эта программа решает все свои задачи путем переписывания всех секторов каталога и таблицы FAT в память, где и выполняются все модификации элементов каталога файла и его таблицы FAT. Когда все изменения были проведены, программа RESCUE записывает весь каталог и всю таблицу FAT обратно на диск. Если во время анализа данных и их модифицирования встречаются трудности, выполнение программы RESCUE завершается и диск остается без изменений.


Как было отмечено ранее, программа RESCUE была так разработана, что она может работать с любым форматом диска, который соответствует стандартным соглашениям по форматированию, принятым в операционной системе MS-DOS. Программа RESCUE использует не входящую в документацию по операционной системе MS-DOS функцию 32h (получить блок параметров диска) для получения необходимой ей информации, касающейся формата диска. Эта программа также широко использует функции, содержащиеся в библиотеке поддержки языка Си фирмы "Майкрософт". Если вы будете перестраивать эту программу для работы ее на другом языке или с другим компилятором, вам придется найти или самим написать заменяющие значения для этих функций.


Программа RESCUE намеренно сделана очень простой, и для ее понимания и для того, чтобы она соответствовала уровню этой книги. Существует ряд расширений, которые вы возможно, захотите добавить в программу RESCUE, чтобы сделать ее еще более широко используемой и полезной. Возможно, вы захотите позволить пользователю самому указывать в командной строке по заданию RESCUE дисковод и каталог, где расположен файл или вы можете захотеть разрешить универсальное задание стертых файлов с применением символов "*" и "?". Весьма полезным добавлением может оказаться средство проверки попыток восстановления пользователем файлов, имена которых уже существуют (что может быть сделано при разумном использовании имеющихся стандартных программ).


Другая модификация, которую вы можете захотеть произвести, заключается в разрешении программе RESCUE работать с жесткими дисками, которые имеют части, превышающие 32 Мегабайта, что возможно в работе под управлением операционной системы MS-DOS версии 4.0. Разбиения расширенного размера используют 32-битовые номера секторов вместо 16-битовых номеров секторов, использовавшихся в разбиениях по 32 Мегабайта и меньше. Для того, чтобы избежать работы с 32-битовыми элементами таблицы FAT, отношение сектор/кластер увеличивается в разбиениях расширенного размера так, что 16-битовые элементы таблицы FAT тоже могут по-прежнему использоваться. Однако, максимальный размер таблицы FAT (одной ее копии) был увеличен с 64 Кбайт (для операционной системы MS-DOS версии 3.3) до 128 Кбайт (для операционной системы MS-DOS версии 4.0). Прикладные программы операционной системы MS-DOS экранируются от кластера разбиения повышенного размера и от схемы отображения секторов, при условии, что используются только стандартные файловые функции операционной системы MS-DOS или абсолютные ссылки на кластеры. Но использование абсолютными ссылками на кластеры прерываний 25h и 26h требует разных соглашений по обращениям между частями в 32 Мегабайта или меньше и частями, большими 32 Мегабайт. В представленных ниже листингах продемонстрированы два соглашения в операционной системе MS-DOS версии 4.0 для прерывания 25h (Абсолютное чтение диска) и прерывания 26h (Абсолютная запись на диск).


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


    Листинг 11-2. Условия вызова операций  абсолютного  чте-
  ния/записи  на  диск  (по  прерываниям "int 25h/int 26h") для
  разделений диска в 32 Мегабайта или меньше (Все версии опера-
   ционной системы MS-DOS)
----------------------------------------------------------------
Вход :    AL = Hомер дисковода (0=А, 1=В и т.д.)
 CX = Количество секторов для чтения (прерывание
      "int 25h") или для  записи  (прерывание
      "int 26h")
 DX =  Hачальный логический номер сектора
 DS:BX = Aдрес передачи
Bозврат:  Признак переноса = 0 (успешная передача) или
= 1 (не успешная передача)
 AL = Kод ошибки
 AH = Tип ошибки
Примечание: B  регистре AX возвращается значение 0207h, если
   была сделана попытка чтения или записи части раз-
   мером больше 32 Мегабайт

  Листинг 11-3.  Условия вызова операций абсолютного чтения/за-
        писи на диск (по прерываниям "int  25h/int  26h")  для  разделений
        диска,  больших  32  Мегабайт  (только для версии 4.0 операционной
       системы MS-DOS)
        -----------------------------------------------------------------
Вход :    AL = Hомер дисковода (0=А, 1=В и т.д.)
 BX = Указатель на список параметров
 CX = -1 (указывает на расширенный
(> 32 Мегабайт) формат)
Bозврат:  Признак переноса = 0 (успешная передача) или
= 1 (не успешная передача)
 AL = Kод ошибки
 AH = Tип ошибки
Примечание: POP AX (код ошибки) при выходе. Коды ошибок
   такие же как указанные выше.

    Cтруктура списка параметров:

    rba     dd   ?  ; первый сектор (32-битовый с
  ; началом в 0) для чтения-записи
    count   dw   ?  ; количество секторов для
  ; чтения-записи
    buffer  dd   ?  ; буфер данных

        Листинг 11-4. Программа контроля RESCUE
_________________________________________________________

/********************************************************
    FILE:   RESCUE2.C   Rescue File Utility Version 2.00

Расширения:  Контроль  файла  в подкаталогах
    Контроль стертого подкаталога
    Управление  любым  типом  дискового носителя
    операционной системы MS-DOS (гибкие диски,
    жесткие диски, сменные кассеты)

Компилирование компилятором "Си" "фирмы "Майкрософт":
   cl /c /Zp1 /AS /GO /Ze /Ot rescue2.c

Редактирование редактором фирмы "Майкрософт":
   Link /Dosseg/MA/LI/CPAR:1/STACK:4096 rescue2,rescue2.exe,
        rescue2.map,slibce;
   *********************************************************

   /*  В К Л Ю Ч Е Н Н Ы Е    Ф А Й Л Ы  */

   #include     /*для функции printf() и еще многих*/
   #include     /*для getch() */
   #include       /*для intdos(),int86(), и так  далее*/
   #include    /*для _fmalloc ()& malloc */
   #include    /*для memory "mem...()" и  str..."*/
   #iclude      /*для topper() and "есть...()" */
   #include    /*для getcwd() */

   /*  О П Р Е Д Е Л Е Н И Е    К О Н С Т А Н Т  */

   #define FALSE     0   /* эти определения предназначены*/
   #define TRUE      1   /* для того, чтобы сделать програм-*/
   #define AND       &&  /* му более читаемой и  понятной*/
   #define OR        ‹‹
   #define EQ        ==
   #define NE        !=
   #define LE        <=
   #define ABS_READ       0x25 /* прерывание чтения диска */
   #define ABS_WRITE      0x26 /* прерывание записи на диск */
  /* Функции прерываний  "int 21h"  операционной системы DOS:*/
   #define DFUNC_RESETDSK 0x0D /* сброс  дисковода */
   #define DFUNC_GETDISK  0x19 /* получить текущий дисковод */
   #define DFUNC_GETDPB   0x32 /* получить блок дисковых */
    /* параметров */
   #define DFUNC_GETCD    0x47 /* получить текущий дисковод */
     /* Биты атрибутов файла операционной системы DOS: */
   #define FATR_NONE      0x00 /* соответствует ANY */
   #define FATR_READ      0x01 /* только для чтения */
   #define FATR_HIDDEN    0x02 /* скрытый */
   #define FATR_SYSTEM    0x04 /* файл системы */
   #define FATR_VOLUME    0x08 /* метка тома */
   #define FATR_SUBDIR    0x10 /* подкаталог */
   #define FATR_ARCHIV    0x20 /* архивированный файл */

   #define CL_OFF      2    /* первым номером кластера */
 /* является число 2*/
   #define TENMB       20740L /* максимальное количество */
 /* секторов, поддерживаемых */
 /* 12-битовой таблице FAT */

   #define CHAIN_END   1    /* используется  функцией */
 /* "get_cluster ()" для */
 /*  обозначения конца файла*/
   #define FILE_END    0xfff8   /* элемент таблицы FAT для */
     /* конца файла */
     /* стандартная программа match() для совпадающих типов*/
   #define NO_MATCH    0   /* не совпадают*/
   #define IS_MATCH    1   /* совпадают */
   #define IS_ERASED   2   /* со стертыми файлами */
   #define IS_UNIQUE   4   /* со нестертыми файлами */

   #define DNAME_SIZE  80  /* максимальный размер имени в */
/* каталоге */
   /*  ОПРЕДЕЛЕНИЕ  СТРУКТУР  И  ТИПОВ  */

   typedef unsigned int BOOL;
   typedef unsigned char BYTE;
   typedef unsigned int WORD;
   typedef unsigned long DWORD;
   typedef union {
  BYTE far * ptr;
  struct {
      WORD off ;
      WORD seg ;
      } a;
  } LONGPTR ;
   typedef struct dpbbuf {   /* буфер блока дисковых пара- */
  /* метров */
       BYTE PhysDrive;       /* номер дисковода */
       Byte DriverUnit ;     /* номер узла в пределах дис- */
  /* ковода */
       WORD BytesSector ;    /* количество байтов в секторе */
       BYTE SectorsCluster ; /* количество секторов в кластере
  /* минус 1 */
       BYTE ClusterShift;    /* сдвиг кластера */
       WORD  Reserve;        /* количество зарезервированных
  /* секторов */
       BYTE NumberOfFATs;    /* копии таблицы FAT */
       WORD DirEntries;      /* количество  элементов корне- */
  /* вого каталога */
       WORD DataSect;        /* первый сектор данных */
       WORD TotClust;        /* общее количество кластеров */
  /* плюс 1 */
       BYTE nFATsec;/* количество секторов  таблицы */
  /* FAT  (1 таблица FAT) */
       WORD DirSect;/* номер сектора каталога */
       DWORD DevHeaderAddr;  /* адрес головки дисковода */
       BYTE MediaByte;       /* байт описателя носителя */
       BYTE DiskAccFlag;     /* признак доступа к диску */
       DWORD NextBlockAddr;  /* адрес следующего блока диска */
       } DPB;
   typedef struct dirbuf {   /* элемент каталога диска */
       char  name [8];       /* имя */
       char  ext  [3];       /* расширение */
       BYTE  attrib ;        /* атрибут */
       BYTE reserved [10];
       WORD time  ; /* время: часы минуты- */
  /* -минуты секунды */
       WORD date ;  /* дата: год месяц-месяц день */
       WORD cluster ;        /* начальный кластер */
       DWORD fsize ;/* общий размер в байтах */
       } DENTRY;

   /*  Г Л О Б А Л Ь Н Ы Е   П Е Р Е М Е Н Н Ы Е   * /

   DPB    far * DPBPtr ;       /* указатель блок параметров */
    /* диска (DPB) */
   WORD   ClUnit ;    /* количество секторов в */
    /* кластере (а также размер */
    /* буфера  каталога) */
   WORD   ByteClust ; /* количество байтов в */
    /* кластере */
   DWORD  TotSect ;   /* общее количество секторов */
    /* на  диске */
   WORD   FATSize ;   /* количество байтов в таб- */
    /* лице FAT */
   WORD   far * FatAnchor ;    /* адрес буфера таблицы FAT */
   DENTRY near * DirAnchor ;   /* адрес буфера  каталога */
   DENTRY near * AltAnchor ;   /* адрес  буфера другого ка- */
    /* талога */
   char   defalt_sname [] ={"*.*"};  /* имя поиска по умол- */
    /* чанию */

   /*  ОПРЕДЕЛЕНИЕ ПСЕВДО-СТAHДАРТНЫХ ПОДПРОГРАММ  */

#define diskread(d,s,c,b)   diskaccess(ABS_READ,d,s,c,b)
#define diskwrite(d,s,c,b)   diskaccess(ABS_WRITE,d,s,c,b)

#define sector_of(cl)   (DPBPtr->DataSect+(cl-CL_OFF)*ClUnit)
#define cluster_of(sec) (CL_OFF+(sec-DPBPtr->DataSect)/ClUnit)
   /*  ПРЕДВАРИТЕЛЬНЫЕ ОБЪЯВЛЕНИЯ СТAHДАРТНОЙ ПОДПРОГРАММЕ  */

   WORD   get_cluster ();      /* получить значение элемента */
    /* кластера */
   void   put_cluster ();      /* сохранить значение в клас- */
    /* тере */
   BOOL   savefile ();/* восстановить файл(ы) */
   DENTRY near * findt ();     /* просмотр буфера каталога */
   DPB    far * getdpb () ;    /* получить адрес блока пара- */
    /* метров диска */
   void   diskaccess () ;      /* абсолютное чтение/запись */
    /* диска */
   BOOL   match () ;  /* соответствие определенного */
    /* имени  с файлом */

   /* *******************************************************
   /*
   /*  Главная   точка   входа
   /*
   /* *******************************************************

   main (argc,argv,envp)
   int argc ;
   char   * argv [] ;
   char   * envp [] ;
      }
      char   near * sspec ;       /* характеристика поиска */
      char   dname [DNAME_SIZE];  /* буфер имени каталога */
      char   * pptr ;    /* указатель на каталоговое
       /* имя */
      WORD   dnum ;      /* номер дисковода (исход- */
       /* ное значение 0) */
      WORD   snum ;      /* номер сектора каталога */
      WORD   savenum ;   /* используется для хра- */
       /* нения */
       /* значения snum */
      DENTRY near * dptr ;/* элемент текущего каталога */
      print ("\nRESCUE, Version 2.OO\n\n");

      if (argc<2) {      /* если  параметров  нет */
    print ("*** Имя файла не указано ***\n");
    exit (1) ;
    };
      sspec =argv [1];  /* файл для восстановления */
      getcwd (dname, DNAME_SIZE) ;  /* получить дисковод по */
/* умолчанию и каталог */
      if (*(char *)((WORD)dname + strlen(dname) - 1) NE '\\')
  strcat (dname, "\\");  /* имя пути доступа за- */
      /* канчивается знаком "\"*/
      pptr = dname+3;   /* указатель  начального */
      /* имени пути доступа*/
      dnum = *dname - 'A' ;      /* извлечь номер дисковода */

/*  Определить разные глобальные значения из блока парамет- */
/*  ров диска (DPB), включая размер таблицы FAT, количество */
/*  байтов в кластере, общее количество секторов и т.д.     */

DPBPtr = getdpb (dnum) ;  /* получить блок параметров диска */

 if(dnum NE DPBPtr->PhysDrive) {
    printf ("Дисковод %c: является замененным\n",(dnum+ 'A'));
    printf("Программа RESCUE будет работать только
   на физических дисководах\n");
    exit (1);
    } ;
   FATSize = DPBPtr->BytesSector * DPBPtr->nFATsec:
   CLUnit  = DPBPtr->SectorsCluster + 1;

TotSect = (DWORD) DPBPtr->TotClust * (DWORD) ClUnit
    + (DWORD) DPBPtr->DataSect;
   BytCLust= DPBPtr->BytesSector * CLUnit;
  /* Pаспределить память для буферов каталога и таблиц FAT */

     If (((DirAnchor=(Dentry near *) malloc(BytClust)) EQ
   NULL) OR
((AltAnchor=(DENTRY near *) malloc(BytCLust)) EQ
   NULL) OR
((FATAnchor=(WORD far *)_fmalloc(FATSize)) EQ
    NULL)) {
printf ("*** Can't Allocate Working Memory ***\n");
exit (1);
} ;

   /* Cчитать в исходную таблицу FAT */

   discread (dnum,DPBPtr->Reserve,DPBPtr->nFATsec,FATAnchor);

   /* Двигаться по цепи элементов каталога в поисках  */
   /* соответствующего  имени пути доступа */

      snum = DPBPtr->Dirsect;    /* первый сектор каталога */
      while (*pptr NE '\0')      /* до тех пор, пока путь */
/* доступа к каталогу ненулевой */
if ((dptr = findf (dnum, &snum, pptr, DirAnchor,
  NULL,FATR_SUBDIR,IS_INIQUE)) NE NULL) {
     snum = sector_of (dptr->cluster);
     while ((*pptr NE '\0') AND (*pptr NE '\\'))
pptr++;
     if (*pptr EQ '\\') pptr++;
  } else {
    printf ("*** Can't Find  Directory  %s  ***\n",
pptr);
    exit (1);   };
     /* Ненормальное завершение, если файл, подлежащий  */
     /* восстановлению, не стерт. */

  savenum = snum;    /* сохранить сектор каталога */
 if (findf (dnum, &dnum, sspec, DirAnchor,
    NULL,FATR_NONE,IS_UNIQUE) NE NULL) {
printf ("***%s%s не стерто ***\n",dname,sspec);
exit (1) ;
 };
    /* Eсли файл стерт, подкаталог или файл затем */
    /* восстанавливает его */
snum = savenum;   /* восстановить сектор каталога */
if ((dptr = findf (dnum,&snum,sspec, DirAnchor,
   NULL,FATR_NONE,IS_ERASED)) NE NULL){
if(get_cluster (dptr->cluster) NE 0)
   printf ("Hестертый файл%s%s не может быть
        восстановлен\n",
     dname, sspec);
   else {
 if (savefile (dnum,dptr, snum,toupper(*sspec))) {
    if (dptr->attrib & FATR_SUBDIR)
        print ("Подкаталог %s%s восстановлен\n,
  dname,sspec);
        else
 printf ("Файл %s%s восстановлен\n",
    dname,sspec);
     } else {
       printf (Неудачное восстановление %s%s\n",
dname,sspec);
       diskread (dnum,DPBPtr->Reserve,
DPBPtr->nFARsec,FatAnchor);
     };
   };
        } else {
 printf ("Не могу найти нестертый файл %s%s\n",
   dname,sspec);
 };
        };
/* **** Найти следующий кластер в цепи ********************

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

     Если диск имеет емкость 10 Мегабайт или меньше,  то использу-
ются 12-битовые элементы таблицы FAT (кластеры). Если диск больше,
то используются 16-битовые элементы таблицы FAT.

Значения кластера: (0)000 ................ свободный кластер
 (0)001 ................ неопределен
 (0)002 -(F)FEF......... следующий кластер
 (F)FF0 -(F)FF6......... зарезервирован
 (F)FF7 ................ испорченный кластер
 (F)FF8 -(F)FFF......... конец цепи
*/

   WORD   get_cluster (clust)   /* номер кластера */
       WORD clust;
       {
       union { WORD FAR }* w;  /* указатель на таблицу FAT */
  BYTE far * b;
  }fatptr;
       WORD   value;   /* содержимое кластера */

  if (TotSect > TENMB){
  fatptr.b=(BYTE far *)
    ((DWORD) FatAnchor + (DWORD)(clust * 2));
  value = *fatptr.w;
       } else {
       fatptr.b= (BYTE far *)
       ((DWORD) FatAnchor + (DWORD)(clust * 3/2));
       value = *fatptr.w;
/*  Кластеры с нечетными номерами сдвигаются влево */
/*  на 4 бита в слове */
  if (clust & 0x01) value >>= 4;
  value &= 0x0fff;
  } ;
   if ((value & 0x0ff0) EQ 0xff0) return (CHAIN_END);
  else return (value);
  } ;

/* ****  Сохранить значение кластера *************************
        Эта стандартная  программа  помещает  значение  в  элемент
   кластера  в  таблице  FAT,  если диск имеет емкость 10 Мегабайт
   пользуются 12-битовые элементы  таблицы  FAT  (кластеры).  Если
   диск больше, то используются 16-битовые элементы таблицы FAT.

*/
   void put_cluster (clust,value)
       WORD clust;     /* номер кластера */
       WORD value;     /* значение нового кластера */
       {

   union { WORD FAR }* w;       /* указатель на таблицу FAT */
       BYTE far * b;
       }fatptr ;
   WORD   cur_val; /* значение текущего кластера */

   if (TotSect > TENMB) {
       fatptr.b=(BYTE far *)
       ((DWORD) FatAnchor + (DWORD) (clust * 2));
       *fatptr.w=value;
       } else {
       fatptr.b= (BYTE far *)
       ((DWORD)FatAnchor + (DWORD)(clust * 3/2));
       cur_val = *fatptr.w;
/*  Кластеры с нечетными номерами сдвигаются влево */
/*  на 4 бита в слове */
   if (clust & 0x01)
       *fatptr.w = (cur_val & 0x000f) ‹ (значение << 4);
   else
       *fatptr.w = (cur_val & 0xf000) ‹ (значение & 0x0fff);
       } ;
   };

/* *** Найти  кластер файла и сохранить каталог и
  таблицу FAT файла ***

      Эта программа восстанавливает стертый  файл,  если  это
   можно.  Она вычисляет количество кластеров, которые должен
   занимать файл, и ищет эти кластеры в таблице FAT.

       Эта стандартная программа предполагает, что номер  на-
   чального  кластера  файла, подлежащего восстановлению, был
   проверен, и его значение равно нулю.
*/
   BOOL savefile (dnum,dptr,sect,ch)
       WORD    dnum ;       /* рабочий дисковод */
       DENTRY  near * dptr ;     /* элемент  каталога, */
      /*  подлежащий сохранению */
       WORD    sect ;   /* дать оглавление секторов */
      /* кластера */
       BYTE    ch ; /* первый  символ  в имени файла */
       {
       DENTRY  far * writeptr ; /*указатель на буфер каталога*/
       WORD    filecls ;        /* размер файла (в кластерах) */
       WORD    last ;  /* номер последнего  кластера */
       WORD    current ;        /* номер текущего кластера */
       WORD    next ;  /* следующий кластер в цепи */
       WORD    fatsect ;        /* номер сектора таблицы FAT */
       union { WORD FAR }* w ;  /* указатель на таблицу FAT */
  BYTE far * b ;
  } fatptr ;

   if (dptr->attrib & FATR_SUBDIR)  /* если файл находится в */
/* подкаталоге */
       filecls = 0 ;       /* дополнений не нужно */
   else
       filecls = (WORD) ((dptr->fsize + (DWORD)BytClust-1L)/
       (DWORD) BytClust) -1 ;
   current = last =dptr->cluster ;   /* первый кластер */

   /* Исправление таблицы FAT */

   while (filecls) {
       if (++current > DPBPtr->TotClust) {
 print ("\n*** Нельзя восстановить файл ***/n");
 return (FALSE) ;
 } ;
       if (get_cluster(current) EQ 0) {  /* пустой  кластер */
 put_cluster (last,current) ;   /* часть цепи */
 last = current ;
 filecls-- ;
 } ;
       } ;
       put_cluster (last, FILE_END) ;/* конец цепи */
       *(dptr->name) = ch ;     /* сохранить первый символ */

   /* Подготовка завершена - писать сектора таблицы FAT */
   /* и каталога */

       writeptr = DirFnchor ;
       fatsect = DPBPtr->Reserve ;
       disckwrite (dnum,fatsect,DPBPtr->nFATsec,FatAnchor) ;
       fatsect += DPBPtr->FATsec ;
       disckwrite (dnum,fatsect,DPBPtr->nFATsec,FatAnchor) ;
       disckwrite (dnum,sect,ClUnit,writeptr) ;
       dbos (DFUNC_RESETDSK,NULL,NULL);
       return(TRUE)) ;
       } ;

   /* **** Найти определенный  элемент в этом каталоге **** */
   DENTRY near * findf (dnum,sect,pptr,dbuf,bptr,sattr,mtype)
       WORD    dnum ;/* рабочий дисковод */
       WORD    * sect ;       /* сектор текущего каталога*/
       char    near * pptr ;  /* указатель имени пути доступа*/
       DENTRY  near * dbuf ;  /* буфер каталога */
       DENTRY  near * bptr ;  /* указатель другого буфера */
       BYTE    sattr ;        /* атрибут поиска */
       int     mtipe ;        /* требуемый тип совпадения */
       {
       int     i ;   /* счетчик циклов */
       WORD    cluster ;      /* используется для сцепления */
       DENTRY  near * dirptr ; /* указатель  буфера каталога*/
       DENTRY  far  * readptr ; /*указатель  буфера каталога*/
       DENTRY  near * dirend ;  /* адрес конца буфера */

       readptr = dbuf ;
       dirend = (DENTRY near *) ((WORD) dbuf + BitClust - 1) ;

       while (TRUE) {
 if (bptr NE NULL) {    /* продолжить с ... */
     dirptr =++bptr ;   /* того места, где */
      /* остановились */
     bptr = NULL ;
   } else {    /* иначе, начать с начала */
     diskread (dnum,*sect,ClUnit,readptr) ;
     dirptr = dbuf ;
     } ;

   /* Eсть ли совпадающие файлы ? */
       while (dirptr < dirend) {
 if (((dirptr->attrib & sattr) EQ sattr) AND
     (match (pptr,dirptr->name,mtype)))
     return (dirptr) ;
 dirptr++ ;
 } ;

   /* Bсе элементы в этом кластере приведены, перейти к */
   /* другому */

   if (*sect >=DPBPtr->DataSect) {      /* подкаталог */
cluster = cluster_of (*sect) ; /* следующий кластер*/
if ((cluster = get_cluster (cluster)) LE CHAIN_END)
      return (NULL) ;
    else *sect = (sector_of (cluster)) ;
 } else     /* корневой каталог */
 if (*sect >= DPBPtr->DIRSect) {
     *sect += ClUnit ;        /* следующие сектора */
 if (*sect >=DPBPtr->DATASect) return (NULL) ;
 } else return (NULL) ;
 } ;
        } ;
      /* **** Получить блок параметров системы BIOS  ****** */
      /* **** для заданного дисковода ********* */

DPB far *getdpb (dnum)  /* возврат указателя на блок DPB */

  Word    dnum ;     /* номер рабочего дисковода */
  {
  union REGS inregs, outregs ;
  struct SREGS segregs ;
  LONGPTR farptr ;
  inregs.h.ah = DFUNC_GETDPB ;
  inregs.h.dl = dnum + 1 ;
  intdosx (&inregs, &outregs, &segregs) ; /*получить блок DPB*/
  if (outregs.x.cflag) {
   if (outregs.h.al EQ 0xff)
    print ("*** Дисковод %c неисправен ***\n",(dnum + 'A')) ;
       else
    printf ("*** Не могу считать параметры дисковода %c ***\n",
   (dnum + 'A')) ;
     exit (1) ;
     } ;

   farptr.a.off = outregs.x.bx ;
   farptr.a.seg = segregs.ds ;
   return ((DPB far *) farptr.ptr ;
   } ;

/* **** Чтение/запись на диск прямого доступа *********** */

void diskaccess ((function, dnum, sector, count, buffer)
     BYTE function ;/* функция прерывания */
     BYTE dnum ;    /* номер физического дисковода */
     WORD sector ;  /* номер сектора */
     WORD count ;   /* счет секторов */
     BYTE far * buffer ;     /* буфер */
     {
     union REGS inregs, outregs ;
     struct SREGS segregs ;
     LONGPTR farptr ;

     farptr.ptr = buffer ;
     inregs.h.al = dnum ;
     inregs.x.dx = sector ;
     inregs.x.cx = count ;
     inregs.x.bx = farptr.a.off ;
     segregs.ds = farptr.a.seg ;
     int86x (function,&inregs,&outregs,&segregs) ;
     if (outregs.x.cflag) {
       if (function EQ ABC_READ)
        printf ("*** Ошибка во время считывания диска ***\n") ;
 else
     print ("*** Ошибка во время записи на диск ***\n") ;
   exit (1) ;
   } ;
} ;

/* ************ Проверить имена на совпадение ********** */

/*     Отметим, что обращение к  массивам  имен  ведется
   без знака, поэтому сравнение с ОхE5 будет выполняться
   надлежащим образом.*/

   BOOL match (sname, fname, mtype)
        BYTE   near *sname ;   /* поиск совпадающего имени */
        BYTE   near *fname ;     /* имя файла или каталога */
        int    mtype ;   /* тип требуемого совпадения */
        {
        int    i ;       /* индекс */
        char   near *fext ; /*расширение файла или каталога*/
        fext = fname + 8;      /* расширение  файла */

/*Сверка состояния файла (стерт/восстановлен) с типом поиска*/

        if  (((*fname NE 0xe5) AND (mtype EQ IS_ERASED)) OR
    ((*fname EQ 0xe5) AND (mtype NE IS_ERASED)))
    return (NO_MATCH) ;

        if  (*fname EQ 0xe5) {    /* игнорировать первый */
   fname++ ;    /* символ стертого файла */
   sname++;
   } ;

        while (fname < (fext+3)) {
        if (*fname EQ toupper(*sname)) {
  fname++ ;
  sname++ ;
} else /* если имена различны, */
  switch (*sname++) {    /* выяснить почему */
    case '.':
        if ((*fname EQ ' ') OR (fname EQ fext)) {
 fname = fext ;  /* проверка расширения */
 break ;
 } ;/* иначе */
        return (NO_MATCH) ;
    case '\\':
    case '\0:
        if (*fname EQ ' ')   /* конец имени sname */

      return (IS_MATCH) ;
    default:
        return (NO_MATCH) ;
    } ;
 } ;
 return (IS_MATCH) ;
        } ;

   /* Конец файла RESCUE.C */
----------------------------------------------------------------

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Hosted by uCoz