.
.
1000 IF ERR = 53 THEN 1500 'файл не существует?
1010 IF ERR = 64 THEN ... 'другие ошибки
.
1500 EXISTS = 0 'меняем значение флага
1510 RESUME 140 'продолжаем выполнение программы
Средний уровень.
Функции работы через дескрипторы файлов, которые использова-
лись для доступа к корневому каталогу [5.2.1] могут так же просто
обращаться к любому подкаталогу. Чтобы вывести все содержимое
каталога надо просто использовать функцию 4EH для поиска файлов
*.*, а затем повторять поиск, используя функцию 4FH. Kогда больше
не будет файлов, то будет установлен флаг переноса, а AL будет
содержать 18. Kаждый раз, когда будет обнаружен очередной эле-
мент, в DTA будет записана информация о файле, включая полный его
путь (отмечаем использование DTA в функциях, использующих деск-
риптор файла). Следующий пример выводит полные пути всех обычных
файлов подкаталога.
;---в сегменте данных
PATH DB 'A:MAMMALS\*.*',0
DTAH DB 256 DUP(?)
;---установка DTA
LEA DX,DTA ;DS:DX указывают на DTA
MOV AH,1AH ;функция установки DTA
INT 21H ;устанавливаем DTA
;---ищем первый файл
MOV AH,4EH ;номер функции
LEA DX,PATH ;указываем на строку пути
MOV CX,0 ;только нормальные атрибуты
INT 21H ;ищем *.*
JC ERROR ;обработка ошибок
;---выводим имя файла
NEXT_LINE: LEA BX,DTA ;BX указывает на DTA
ADD BX,30 ;смещение для имени файла
NEXT_CHAR: MOV DL,[BX] ;получаем символ из имени
CMP DL,0 ;проверка на конец строки
JE END_STR ;уход, если конец
MOV AH,2 ;иначе, выодим символ
INT 21H ;
INC BX ;увеличиваем указатель
JMP SHORT NEXT_CHAR ;следующий символ
;---возврат каретки/перевод строки в конце строки
END_STR: MOV AH,2 ;функция вывода символа
MOV DL,13 ;код возврата каретки
INT 21H ;выводим
MOV DL,10 ;код перевода строки
INT 21H ;выводим
;---ищем следующий файл
LEA DX,PATH ;указываем на строку пути
MOV AH,4FH ;номер функции
INT 21H ;ищем следующий файл
JC FINISHED ;если нет, то выход
JMP SHORT NEXT_LINE ;иначе выводим имя файла
FINISHED:
5.2.4 Получение/установка текущего каталога.
Текущий каталог это каталог, в котором DOS ищет файл, для
которого не указан путь. Если не установлено противного, то теку-
щий каталог является корневым каталогом.
Высокий уровень.
Бейсик устанавливает текущий каталог с помощью команды CHDIR.
За командой должна следовать строка, указывающая путь к каталогу,
на который надо перейти. Строка может содержать до 63-х символов,
включая имя накопителя, и должна быть заключена в кавычки. CHDIR
"C:MAMMALS\PRIMATES\GIBBONS" делает подкталог GIBBONS текущим
каталогом. Чтобы перейти в корневой каталог напишите CHDIR "\"
или CHDIR "B:\".
Бейсик версии 3.0 может сообщать путь к текущему каталогу, как
это делает команда DOS PATH. Просто введите PRINT ENVI-
RON$("PATH").
Средний уровень.
Функция 3BH прерывания 21H устанавливает текущий каталог.
DS:DX должны указывать на путь к каталогу в стандартном виде и
эта строка должна завершаться байтом ASCII 0. Hапример, B:BIRDS\-
PARROTS\POLLY делает POLLY текущим каталогом. B: может быть опу-
щено, если это текущий накопитель по умолчанию [5.3.1]. Чтобы
сделать текущим корневой каталог накопителя A: напишите A:\. В
примере текущим каталогом устанавливается POLLY:
;---в сегменте данных
PATH DB 'B:BIRDS\PARROTS\POLLY',0
;---делаем POLLY текущим каталогом
MOV AH,3BH ;номер функции
LEA DX,PATH ;DS:DX должны указывать на путь
INT 21H ;устанавливаем текущий каталог
Чтобы определить какой каталог является текущим надо использо-
вать функцию 47H прерывания 21H. DS:SI должны указывать на об-
ласть данных размером 64 байта, в которую будет записан путь. В
DL указывается накопитель, причем 0 = "по умолчанию", 1 = A, 2 =
B и т.д. При возврате функция возвращает строку без имени накопи-
теля. Если был указан несуществующий накопитель, то в AL возвра-
щается код ошибки 15. Строка начинается с имени первого подката-
лога цепочки, а не с обратной косой черты. Байт ASCII 0 сигнали-
зирует о конце строки. В данном примере имя текущего каталога
присваивается переменной "CURRENT_DIR":
;---в сегменте данных
CURRENT_DIR DB 64 DUP(?)
;---получить текущий каталог
MOV AH,47H ;номер функции
LEA SI,CURRENT_DIR ;указываем на область данных
MOV DL,1 ;накопитель A
INT 21H ;помещает строку по адресу DS:SI
5.2.5 Получение/установка времени и даты последнего доступа к
файлу.
Если отсчитывать от нуля, то байты 22-23 32-байтного элемента
каталога содержат время последнего доступа к файлу. Байты 24-25 -
содержат дату. Значение битов следующее:
Время: биты 11-15 часы (0-23)
5-10 минуты (0-59)
0-4 секунды (0-29 с 2-секундным интервалом)
Дата: биты 9-15 год (0-119, смещение с 1980 года)
5-8 месяц (1-12)
0-4 число (1-31)
День недели не записывается; DOS вычисляет его по остальной ин-
формации. Отметим также, что как всегда, младший байт этих
2-байтных значений расположен раньше в памяти, чем старший.
Средний уровень.
Метод доступа к файлу с использованием управляющего блока
файла позволяет получить дату последнего доступа к файлу, но не
время. Kогда FCB открывается функцией 0FH прерывания 21H, то
заполняется двухбайтное поле даты в вышеприведенном формате. Это
поле расположено в FCB со смещением 14H [5.3.5].
С другой стороны, доступ к файлу с помощью дескриптора файла
позволяет как получить, так и установить дату и время последнего
доступа к файлу. Функция 57H прерывания 21H выполняет все опера-
ции. Для установки времени и даты поместите номер файла в BX, и 0
в AL. Для получения даты и времени надо поместить в AL 1. В обоих
случаях дата содержится в DX, а время в CX. Значение битов совпа-
дает с тем, что описано в таблице. В техническом руководстве по
MS DOS утверждается, что младшие байты информации находятся в CH
и DH, и наоборот. Hа самом деле это не так. При возникновении
ошибки устанавливается флаг переноса, а в AX возвращается 1, если
в AL указано неправильное число и 6, если плохой дескриптор фай-
ла. В следующем примере определяется час, в который был последний
лоступ к файлу:
;---в сегменте данных
PATH DB 'B:NEWDATA.BAK',0
;---открываем файл
LEA DX,PATH ;указываем на строку пути
MOV AH,3DH ;функция открытия файла
MOV AL,0 ;открываем для чтения
INT 21H ;открываем файл
JC OPEN_ERROR ;переход на обработку ошибки
;---получаем дату и время доступа к файлу
MOV BX,AX ;помещаем номер файла в BX
MOV AL,0 ;код для чтения времени
MOV AH,57H ;номер функции
INT 21H ;получаем время доступа
JC TIME_ERROR ;переход на обработку ошибок
;---сдвигаем биты, относящиеся к часам, в начало CH
MOV CL,3 ;готовим сдвиг
SHR CH,CL ;теперь CH содержит час доступа
5.2.6 Спрятанные и защищенные от записи файлы.
DOS использует шесть различных атрибутов файлов, которые дают
данному файлу определенный статус. Файл может иметь несколько из
этих атрибутов одновременно (но не все). Атрибуты устанавливаются
12-м байтом 32-байтного элемента каталога. Младшие шесть битов
имеют значение, а остальные должны быть равны нулю. Биты такие:
если бит 5 = 1, то файл был изменен со времени последней
архивации
4 = 1, то файл является подкаталогом
3 = 1, то этот элемент является не файлом, а меткой
тома
2 = 1, то файл является "системным"
1 = 1, то файл спрятан при поиске по каталогу
0 = 1, то файл объявлен только для чтения
Бит 5 это архивный бит, используемый программами BACKUP и RESTORE
DOS. Этот бит сьрасывается в 0 после архивации и устанавливается,
когда с файлом снова работали. При следующей архивации неизменен-
ные файлы могут быть обнаружены и проигнорированы.
Высокий уровень.
Бейсик не позволяет Вам устанавливать атрибуты файла прямо.
Справьтесь в [5.2.1], как считать каталог в память, найти нужный
файл, сделать изменения и снова записать его на диск. Kак только
каталог помещается в память, байты атрибутов находятся по смеще-
ниям 11, 43, 75 и т.д. Если нужно, то Вы можете прочитать текущие
атрибуты и изменить только один бит, используя технику битовых
операций, описанную в приложении Б. Hо легче просто переписать
все атрибуты заново. Будьте внимательны, ошибки могут быть фа-
тальными. В данном примере считываются атрибуты файла с именем
"NEWDATA.AAA".
100 'читаем сектора каталога, начиная с &H2000 и затем ...
110 DEF SEG = &H2000 'указываем на область каталога
120 FILENAME$ = "NEWDATAAAA" 'ищем имя файла без точки
130 DIRPTR = 0 'указатель в каталоге
140 FOR N = 1 TO 112 'проверяем все элементы
150 X$ = "" 'временная строка для имени файла
160 FOR M = 0 TO 10 'для каждого символа имени
170 X$ = X$+PEEK(DIRPTR+M) 'добавляем его к строке
180 NEXT '
190 IF X$ = FILENAME$ THEN 220 'если имя найдено, то уходим
200 NEXT '
210 PRINT "File not found": END 'нет такого файла
220 X = PEEK(DIRPTR+11) 'получаем атрибуты нужного файла
230 IF X AND 32 <> 0 THEN PRINT "File not baked up"
240 IF X AND 16 <> 0 THEN PRINT "File is a subdirectory"
250 IF X AND 8 <> 0 THEN PRINT "Volume label - not a file"
260 IF X AND 4 <> 0 THEN PRINT "File is a system file"
270 IF X AND 2 <> 0 THEN PRINT "File is a hidden file"
280 IF X AND 1 <> 0 THEN PRINT "File is read-only"
Средний уровень.
Функция 43H прерывания 21H может как находить, так и изменять
атрибуты файла, но только если файл был открыт с помощью метода
дескриптора файлов, а не с помощью метода управляющего блока
файла. Hет аналогичной функции для FCB. Байт атрибутов может быть
установлен при создании файла [5.3.2], используя расширенный
управляющий блок файла. Hо если Вы последовательно откроете FCB,
измените установку атрибутов и затем закроете файл, то у него
останутся первоначальные атрибуты. Хотя, конечно, Вы можете изме-
нить атрибуты каким-нибудь обходным путем, но намного проще ис-
пользовать функцию, использующую метод дескриптора файлов.
Чтобы использовать функцию 43H, поместите 1 в AL, чтобы прис-
воить файлу байт атрибутов, содержащийся в CX (на самом деле в
CL, поскольку CH равен 0). Можно наоборот поместить в AL 0, чтобы
в CX был возвращен текущий байт атрибутов файла. В обоих случаях
DS:DX должны указывать на строку, дающую путь к файлу. Kонец
строки отмечается байтом ASCII 0 (который не входит в число 63-х
символов). В примере статус "hidden" (спрятанный) присваивается
файлу OVERDUE:
;---в сегменте данных
PATH DB 'A:ACCOUNTS',0
;---включаем признак спрятанного файла
MOV AH,43H ;номер функции
MOV AL,0 ;читаем байт атрибутов
LEA DX,PATH ;DS:DX указывают на путь
INT 21H ;байт атрибутов в CX
JC ERROR_ROUTINE ;обработка ошибок
OR CL,10B ;включаем бит 1
MOV AH,43H ;номер функции