Получение различной информации
С помощью подфункции 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(®, ®);
// Проверяем флаг переноса
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 и более поздних версий). |
поможет вам определить момент достижения конца файла или готовность устройства посимвольной обработки.
Для проверки условия "Конец файла" или готовности устройства можно использовать следующую функцию:
/** *.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(®, ®);
// Проверяем флаг переноса
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.
Эта подфункция не предназначена для работы с сетевыми устройствами.