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

Поиск в каталогах


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

Пара функций 4Eh и 4Fh предназначены для сканирования каталогов.

Эти функции используются вместе следующим образом:

  • Вызывается функция 4Eh для поиска в каталоге файла, соответствующего образцу. В образце можно использовать символы ? и *, которые означают, соответственно, один любой символ и любое количество любых символов. Информация о найденном файле располагается в специальной области, назначенной каждой работающей программе - области DTA.
  • Вызывается в цикле функция 4Fh для поиска остальных файлов, удовлетворяющих образцу, заданному при вызове функции 4Eh. Условие завершения цикла - отсутствие в каталоге указанных файлов.

    Приведем формат вызова функций 4Eh и 4Fh.

    Функция 4Eh:



    На входе: AH = 4Eh
    CX = Атрибуты файла, которые будут использованы при поиске. Будут найдены файлы, имеющие заданный в этом регистре атрибут.
    DS:DX = Адрес строки в формате ASCIIZ, содержащей путь каталогаили файла.
    На выходе: AL = Код ошибки, если был установлен в 1

    флаг переноса CF.

    Функция 4Fh:

    На входе: AH = 4Fh
    На выходе: AL = Код ошибки, если был установлен в 1

    флаг переноса CF.

    Обе функции устанавливают флаг переноса в том случае, когда каталог не содержит файлов, удовлетворяющих заданному критерию поиска.

    Для работы с областью DTA MS-DOS имеет две функции. Это функция 2Fh, позволяющая получить адрес области DTA (она возвращает этот адрес в регистрах ES:BX), и функция 1Ah, предназначенная для установки своей области DTA


    (адрес новой области DTA должен быть указан в регистрах DS:DX).

    Напомним, что по умолчанию область DTA

    занимает 128 байтов в префиксе сегмента программы PSP

    со смещением 80h.

    В случае успешного поиска функции 4Eh и 4Fh

    помещают в DTA информацию о найденных файлах в следующем формате:

    (0) 20 Зарезервировано.
    (+21) 1 Атрибуты найденного файла
    (+22) 2 Поле времени последнего обновления фалйла
    (+24) 2 Поле даты последнего обновления фалйла
    (+26) 4 Длина файла
    (+30) 13 Имя файла и расширение в формате ASCIIZ
    Номер начального класетра, распределенного файлу или каталогу, невозможно получить с помощью функций 4Eh и 4Fh.

    Стандартные библиотеки трансляторов Microsoft QC 2.5 и C 6.0 содержат две функции, предназначенные для сканирования каталогов - _dos_findfirst() и _dos_findnext().

    Приведем прототипы этих функций, описанные в файле dos.h:

    int _dos_findfirst(char *pattern, struct find_t *found, unsigned attr); int _dos_findnext(struct find_t *found);

    В этих функциях параметр pattern определяет образец для поиска файлов, параметр attr - атрибуты файла - используется в качестве дополнительного критерия поиска. Параметр found

    представляет собой указатель на структуру, в которую будет записываться информация о найденных файлах. Эта структура определена в файле dos.h:

    struct find_t { char reserved[21]; // Зарезервировано для DOS char attrib; // Атрибуты файла unsigned wr_time; // Время изменения файла unsigned wr_date; // Дата изменения файла long size; // Размер файла в байтах char name[13]; // Имя файла и расширение };

    Приведем текст программы просмотра содержимого каталога. Программа принимает из командной строки параметр - образец для показа файлов. Если вы укажете параметр *.*, будет выведена информация обо всех файлах. Можно задавать полный путь: c:\*.*.

    #include <stdlib.h> #include <stdio.h> #include <dos.h>

    void main(int argc, char *argv[]) ; void print_info(struct find_t *find); char *time_conv(unsigned time, char *char_buf); char *date_conv(unsigned date, char *char_buf);



    void main(int argc, char *argv[]) {

    struct find_t find;

    // Находим первый файл, удовлетворяющий критериям поиска. // В качестве критерия используем образец, полученный // из командной строки. Для поиска используем файлы с любыми // атрибутами.

    if(!_dos_findfirst(argv[1], 0xffff, &find)) {

    printf("\n" "\nИмя файла Аттр. Дата Время Размер" "\n------------ ----- ---------- -------- ------");

    // Выводим информацию о первом найденном файле на экран

    print_info(&find); } else { printf("Задайте образец для поиска файлов !"); exit(-1); }

    // Выводим информацию об остальных найденных файлах

    while(!_dos_findnext(&find)) print_info( &find );

    exit(0); }

    // Функция для вывода информации о найденных файлах

    void print_info(struct find_t *pfind) {

    char timebuf[10], datebuf[12];

    // Преобразуем формат даты и времени последнего изменения файла

    date_conv(pfind->wr_date, datebuf); time_conv(pfind->wr_time, timebuf);

    // Выводим содержимое дескриптора файла

    printf("\n%-12s",pfind->name); printf(" %02X %8s %8s %8ld ", pfind->attrib, datebuf, timebuf, pfind->size); }

    // Функция преобразования формата времени

    char *time_conv(unsigned t, char *buf) {

    int h, m;

    h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f; sprintf(buf, "%2.2d:%02.2d:%02.2d", h % 12, m, (t & 0x1f) * 2); return buf; }

    // Функция преобразования формата даты

    char *date_conv(unsigned d, char *buf) {

    sprintf(buf, "%2.2d.%02.2d.%04.2d", d & 0x1f,(d >> 5) & 0x0f, (d >> 9) + 1980); return buf; }

    При запуске программы с параметром *.com на экран будет выведена информация:

    Имя файла Аттр. Дата Время Размер ------------ ----- ---------- -------- ------ CURDIR.COM 20 24.02.1991 08:40:24 5879 DIRCTL.COM 20 24.02.1991 09:10:30 6273 DISK_CTL.COM 20 13.01.1991 03:26:34 8177 DISKA.COM 20 19.01.1991 10:08:58 27 DISKB.COM 20 04.02.1991 08:57:34 6186 DISKINFO.COM 20 24.02.1991 04:08:42 6075 DISKSHOW.COM 20 31.01.1991 09:48:34 6989 PARTSHOW.COM 20 07.02.1991 06:12:02 7357 DIRM.COM 20 26.02.1991 11:59:50 6346


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