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

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

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

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

4.1. Получение различной информации

С помощью подфункции 00h можно получить информацию об открытом файле или устройстве по файловому индексу.

Для удобства работы с этой подфункцией мы подготовили следующую программу:

/**
*.Name      get_devi
*
*.Title     Получить информацию об устройстве
*
*.Descr     Функция получает информацию о файле
*           или об устройстве по его файловому индексу.
*
*
*.Params    int get_devi(int handle, int *info);
*
*           handle      - файловый индекс для
*                         которого необходимо получить
*                         информацию
*
*           info        - указатель на слово, в которое
*                         должна быть записана информация
*
*.Return    0          - если нет ошибок;
*           Код ошибки - если произошла ошибка.
**/

#include <stdio.h>
#include <dos.h>
#include "sysp.h"

int get_devi(int handle, int *info) {

         union REGS reg;

// Заполняем регистровые структуры для вызова
// прерывания DOS INT 21h. Код используемой
// подфункции - 00h.

         reg.x.ax = 0x4400;
         reg.x.bx = handle;

// Вызываем прерывание

         intdos(&reg, &reg);

// Проверяем флаг переноса

         if(reg.x.cflag == 0) {

// Если флаг переноса сброшен в 0, ошибок нет.
// Записываем информацию по адресу *info

          *info = reg.x.dx;
          return(0);

         }

// Если флаг переноса установлен в 1, возвращаем
// код ошибки

         else return(reg.x.ax);
}

Приведенная выше функция принимает в качестве первого параметра файловый индекс открытого файла или устройства и адрес слова, в который она запишет информацию об устройстве или файле, связанном с этим файловым индексом.

Вы можете использовать эту функцию так, как это сделано в следующем примере:

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

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

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

         int handle;
         int info;
         int rc;

// Открываем файл или устройство с заданным именем

         handle = open(argv[1], O_RDONLY);

// Если открыть невозможно, выводим сообщение
// и завершаем работу программы

         if(handle == -1) {
                printf("Не могу открыть файл!\n");
                exit(-1);
         }

// Получаем информацию для файлового индекса handle

         rc = get_devi(handle, &info);

         if(rc != 0) {
                printf("Ошибка с кодом %d\n", rc);
                exit(-1);
         }

         printf("\nСлово информации об устройстве: %04X",info);

         close(handle);
}

В качестве параметра при запуске этой программы попробуйте задавать имена файлов или имена устройств, например - CON, AUX, и т.д.

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

Для устройства:

Бит Значение
0 Это устройство является стандартным устройством ввода.
1 Стандартное устройство вывода.
2 NUL-устройство.
3 Часы.
4 Специальное устройство.
5 1 - двоичный режим работы;
0 - режим ASCII
6 0 - при чтении достигнут конец файла.
7 1 - это слово информации относится к устройству (данный handle относится к устройству);
0 - слово информации относится к файлу.
8-10 Зарезервировано.
11 1 - Устройство поддерживает команды открытия/закрытия.
12 Сетевое устройство (только для DOS версии 3.0 и более поздних версий).
13 Устройство поддерживает вывод до состояния занятости.
14 Устройство может обрабатывать управляющие строки IOCTL, посылаемые подфункциями 2, 3, 4, 5 функции 44h. Этот бит может быть только прочитан, его установка подфункцией 1 функции 44h не производится.
15 Зарезервировано.

Для файла:

Бит Значение
0-5 Номер дисковода (0-А:, 1-В: и т.д.).
6 0 - Была запись в выходной файл.
7 1 - это слово информации относится к устройству (данный handle относится к устройству);
0 - слово информации относится к файлу.
8-11 Зарезервировано.
12 Сетевое устройство (только для DOS версии 3.0 и более поздних версий).
13-14 Зарезервировано.
15 1 - Данный файл является удаленным при работе в сети (только для DOS версии 3.0 и более поздних версий).

Подфункция 06h функции 44h прерывания INT 21h поможет вам определить момент достижения конца файла или готовность устройства посимвольной обработки.

Для проверки условия "Конец файла" или готовности устройства можно использовать следующую функцию:

/**
*.Name      heof
*
*.Title     Проверить условие "Конец файла"
*
*.Descr     Функция позволяет проверить факт достижения
*           конца файла или готовность устройства
*
*.Params    int heof(int handle);
*
*           handle      - файловый индекс для
*                         которого необходимо получить
*                         информацию о состоянии
*
*.Return    0           - конец файла не достигнут (для файла),
*                         устройство готово (для устройства);
*
*           1           - достигнут конец файла (для файла),
*                         устройство не готово (для устройства);
*
*          -1           - произошла ошибка.
**/

#include <stdio.h>
#include <dos.h>
#include "sysp.h"

int heof(int handle) {

         union REGS reg;

// Заполняем регистровые структуры для вызова
// прерывания DOS INT 21h. Код используемой
// подфункции - 06h.

         reg.x.ax = 0x4406;
         reg.x.bx = handle;

// Вызываем прерывание

         intdos(&reg, &reg);

// Проверяем флаг переноса

         if(reg.x.cflag == 0) {

// Если флаг переноса сброшен в 0, ошибок нет.

          if(reg.h.al == 0) return(1);
          else return(0);

         }

// Если флаг переноса установлен в 1, возвращаем
// признак ошибки

         else return(-1);
}

Вы можете использовать эту функцию аналогично функции eof(). В приведенном ниже примере программы, копирующей файлы, мы так и поступили:

#include <stdio.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <malloc.h>
#include <errno.h>

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

         int source, target, i;
         char *buffer;
         unsigned count;

         if(argc == 3) {

// Открываем исходный копируемый файл

                 if((source = open(argv[1], O_BINARY | O_RDONLY)) == - 1) {

                          printf("\nОшибка при открытии исходного файла: %d",
                          errno);
                          exit(-1);

                 }

// Открываем выходной файл. При необходимости создаем
// новый. Если файл уже существует, выводим на экран
// запрос на перезапись содержимого существующего файла

                target = open(argv[2], O_BINARY | O_WRONLY | O_CREAT | O_EXCL,
                                                                         S_IREAD | S_IWRITE);
                if(errno == EEXIST) {

                        printf("\nФайл существует. Перезаписать? (Y,N)\n");

// Ожидаем ответ оператора и анализируем его

                        i = getch();
                        if((i == 'y') || (i == 'Y'))
                                target = open(argv[2], O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
                                                 S_IREAD | S_IWRITE);

                }

// Если выходной файл открыть невозможно, выводим
// сообщение об ошибке и завершаем работу программы

                if(target == -1){
                          printf("\nОшибка при открытии выходного файла: %d",
                          errno);
                          exit(-1);
                }

// Будем читать и писать за один раз 10000 байтов

                count = 10000;

// Заказываем буфер для передачи данных

                if((buffer = (char *)malloc(count)) == NULL) {
                          printf("\nНедостаточно оперативной памяти");
                          exit(-1);
                }


// Копируем исходный файл

                while(!heof(source)) {

// Читаем count байтов в буфер buffer

                        if((count = read(source, buffer, count)) == -1) {
                          printf("\nОшибка при чтении: %d",
                          errno);
                          exit(-1);
                        }

// Выполняем запись count байтов из буфера в выходной файл

                        if((count = write(target, buffer, count)) == - 1) {
                          printf("\nОшибка при записи: %d",
                          errno);
                          exit(-1);
                        }
                }

// Закрываем входной и выходной файлы

                close(source);
                close(target);

// Освобождаем память, заказанную под буфер

                free(buffer);
         }

// Если при запуске программы не были указаны
// пути для входного или выходного файла,
// выводим сообщение об ошибке

         else
                  printf("\n"
                        "Задайте пути для исходного"
                        " и результирующего файлов!\n");
}

Подфункция 0Ah функции 44h прерывания INT 21h поможет программе, работающей в сети, определить расположение открытого файла или устройства - на рабочей станции или на сервере.

Перед вызовом запишите в регистр BX файловый индекс проверяемого файла или устройства.

После возврата из подфункции регистр DX содержит слово атрибутов для файла или устройства. Если самый старший бит в этом слове равен 0, то файл или устройство является локальным и расположено на рабочей станции. Если же этот бит равен 1, то файл или устройство удаленное и находится на сервере (подключено к серверу, если проверяется устройство).

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

Аналогично для проверки расположения дисковода можно использовать подфункцию 09h.

Перед вызовом запишите в регистр BL код дисковода (0-текущий дисковод, 1 - А:, 2 - В:, и т.д.). Двенадцатый бит регистра DX после вызова этой функции покажет вам расположение дисковода: 0 - локальное, 1 - удаленное.

Для проверки возможности замены носителя данных в дисководе вы можете воспользоваться подфункцией 08h. Используя эту подфункцию, вы сможете отличить НГМД от НМД. Это может вам понадобиться, например, для операции форматирования, так как форматирование НГМД и НМД выполняется по-разному.

Перед вызовом подфункции 08h запишите код устройства в регистр BL (0 -текущий дисковод, 1 - А:, 2 - В:, и т.д.). Если носитель данных сменный, то после выполнения подфункции регистр AL будет содержать 0, в противном случае - 1.

Эта подфункция не предназначена для работы с сетевыми устройствами.

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