Страница Ивана Рощина > Статьи >

© Иван Рощин, Москва

ZXNet: 500:95/462.53
E-mail: bestview@mtu-net.ru
WWW: http://www.ivr.da.ru

Тайна ненайденного файла

Радиомир. Ваш компьютер» 2/2003)
Дата последнего редактирования: 27.07.2003.

Хочу рассказать об одной истории — возможно, мой опыт вам поможет.

Запускаю demo «Dive» с компакт-диска. Всё работает. После этого копирую на винчестер и запускаю оттуда. Не работает — при запуске выдаёт сообщение «Can not find data file» («Не могу найти файл данных»). Хотя все файлы я скопировал!

В чём же дело? Может быть, в директории D:\SCENE&~1\DIVE, откуда я копировал файлы, был какой-то файл с атрибутом «hidden» («скрытый»), не отображающийся в панели Dos Navigator’а и поэтому не скопированный? Чтобы проверить это, включил опцию «показывать скрытые файлы» — но никаких скрытых файлов не обнаружилось.

Версию о том, что причина неработоспособности — сработавшая защита от копирования, я отбросил практически сразу: защищена может быть какая-нибудь коммерческая программа, но никак не demo.

Может быть, программа жёстко привязана к директории D:\SCENE&~1\DIVE и только там ищет свои файлы? Чтобы проверить это, я отключил драйвер CD-ROM, создал директорию C:\BAK\SCENE&~1\DIVE, скопировал в неё файлы программы и командой subst сопоставил директорию C:\BAK логическому диску D. Но и это не помогло…

Тогда я попробовал зайти с другой стороны. Сообщение «Не могу найти файл…», очевидно, появляется после того, как программа пытается открыть какой-то файл, и эта операция завершается неудачно. Для открытия файла служит функция 3Dh прерывания 21h. При её вызове в DS:DX помещается адрес ASCIIZ-строки с именем открываемого файла, а в AL — код доступа: 0 — открыть файл только для чтения, 1 — только для записи, 2 — для чтения и записи. После вызова, если всё нормально, флаг C сброшен, а в регистре AX — номер открытого файла. Если же открыть файл не удалось, флаг C установлен, а в AX — код ошибки.

Я написал резидентную программу, которая перехватывает прерывание 21h и, если вызвана функция открытия файла, печатает значения регистров и строку, на которую указывает DS:DX, до и после вызова функции. При запуске demo эта резидентная программа напечатала следующее:

FLAGS=7046 AX=3D02 BX=A372 CX=0000 DX=A3B0 name=DIVE.PRJ
FLAGS=7047 AX=0005 BX=A372 CX=0000 DX=A3B0 name=DIVE.PRJ

То есть программа открывает файл DIVE.PRJ (который, как я сразу же проверил, присутствует на диске) для чтения и записи (AL=2). Функция завершается с ошибкой (нечётное значение регистра флагов — 7047h — соответствует установленному флагу C, так как этот флаг размещается в самом младшем бите регистра флагов). Код ошибки — 5, что значит «нет доступа» (а вовсе не «файл не найден», чему соответствует код 2). Очевидно, программа не анализирует код ошибки и при любой ошибке выдаёт «Can not find data file».

Почему же нельзя получить доступ к файлу DIVE.PRJ для чтения и записи? Может быть, у этого файла установлен атрибут «read only» («только чтение»)?

Проверил — так оно и оказалось. И после того, как этот атрибут был снят, всё заработало!

Но, позвольте, а как же тогда всё работало при запуске demo с компакт-диска? Ведь и там у файла DIVE.PRJ был установлен атрибут «read only»!

При запуске demo с компакт-диска резидентная программа напечатала следующее:

FLAGS=7046 AX=3D02 BX=A372 CX=0000 DX=A3B0 name=DIVE.PRJ
FLAGS=7046 AX=0005 BX=A372 CX=0000 DX=A3B0 name=DIVE.PRJ

Как видите, тот же самый вызов функции открытия файла почему-то завершается успешно (значение регистра флагов чётно — значит, флаг C сброшен). То есть файл, находящийся на компакт-диске, почему-то можно открыть для чтения и записи, несмотря на установленный атрибут «read only»…

Кстати говоря, в рассматриваемом случае, очевидно, достаточно было открыть файл DIVE.PRJ только для чтения: если бы программе и впрямь было бы необходимо что-то записывать в этот файл, она не запустилась бы нормально с компакт-диска…

Итак, тайна ненайденного файла была раскрыта. После этого я вспомнил, что ранее уже сталкивался с похожей ситуацией. При запуске с винчестера (или с дискеты) ещё одного demo на экране можно было увидеть следующее:

C:\WORK\UNSORTED>verses.exe
Fatal error: VERSES.EXE not found!

Если верить этому сообщению, программа не может отыскать… собственный exe-файл! :–)

Проверив атрибуты этого файла, я обнаружил, что атрибут «read only» также установлен. После его снятия и это demo нормально запустилось. Причина неработоспособности, как и в первом случае, была не в том, что программа не могла найти нужный файл, а в том, что она не могла открыть этот файл для чтения и записи.

Так что, если вы столкнётесь с аналогичной ситуацией, советую проверить атрибуты файла (файлов) программы. В Dos Navigator’е это можно сделать, нажав комбинацию Alt+F. Также в Dos Navigator’е удобно включить автоматическое снятие атрибута «read only» при копировании с CD-ROM (Настройки > Конфигурация > Системные установки). (Когда я вначале копировал файлы, эта опция была выключена.)

Ну а при написании своих программ желательно предусмотреть, чтобы выводимые сообщения об ошибках не вводили пользователя в заблуждение…

Литература

  1. П.Абель. «Ассемблер и программирование для IBM PC».
Страница Ивана Рощина > Статьи >