Pull to refresh

Баги из склепа

Reading time5 min
Views21K
Original author: foone

Сегодня 2018, а сообщение об ошибке передаёт нам привет из 1974. Это ограничение, которое встречается в последних версиях Windows 10, уходит корнями в те времена, когда ещё не было снято ни одного эпизода «Звёздных войн». Этот баг такой же старый, как Уотергейт. Когда его написали, ни на одном товаре не было штрих-кода UPC, потому что его только-только изобрели. В те времена существовала только одна Телефонная Компания, которая не была разделена. Тед Банди был на свободе. Рекорд Бейба Рута по хоум-ранам лишь готовился пасть. Ещё не показывали «Колесо Фортуны», и никто не видел «Шоу ужасов Рокки Хоррора». Стивен Спилберг тогда был малоизвестным режиссёром, «Субботним вечером в прямом эфире» не вышла на экраны. «Эдмунд Фицджеральд» пока возил железную руду. Это был год премьеры 2 части «Крёстного отца»!

В те времена в Unix, которому было всего 5 лет отроду, была классная идея, что «всё является файлом». Это значит, что можно делать разные штуки типа записи в сокеты, пайпы, консоль и т. п. с использованием одних и тех же команд и инструкций. Концепция была перенесена Гэри Килдаллом в CP/M в 1974 году. Вы могли копировать данные из последовательного порта в текстовый файл или печатать текстовый файл прямо из командной строки! В Unix это сделано с помощью специальных файлов, расположенных в специальных директориях, например, /dev/tty для консоли или /dev/lp0 для первого принтера. Вы можете получать бескончные нули из /dev/zero, случайные байты из /dev/random и т. д.

Но есть проблемка: CP/M создана для 8-битных компьютеров с очень маленьким объемом памяти и без жёстких дисков. В лучшем случае на них были 8" дискеты. А каталоги? Они вам не нужны. Вместо директорий вы просто использовали разные диски. Но без директорий вы не могли сложить все свои специальные файлы в /dev/. Поэтому фактически они были «везде». То есть, если у вас был FOO.TXT и вам нужно было напечатать его, вы могли сделать PIP LST:=FOO.TXT, чтобы скопировать FOO.TXT в файл LST, который является принтером. И это просто работало в любом месте, потому что директорий не существовало.

А что с расширениями? Тоже всё непросто: программы предпочитают добавлять к своим файлам правильные расширения. То есть, если вы запустили программу, и она говорит «Введите имя файла для сохранения списка», вы можете ввести LST, чтобы распечатать его или PTP, чтобы записать его на ленту (потому что вы в 1974, помните?). Но программа может попытаться добавить .TXT в конце файла! А LST.TXT ведь уже не принтер, верно? Как бы не так. Это он и есть. Имена устройств распознаются независимо от расширений. То есть, если «CON» закреплено за клавиатурой, то и CON.TXT, и CON.BUG тоже. Хм. Это хак, но он работает. При том на всяком хламе с 4КБ оперативки, не пофиг ли?

Что ж, CP/M получила широкое распространение в конце 70-х – начале 80-х. Она стала одной из основных операционок для бизнеса, определив стандартный интерфейс. Это означало, что вы могли писать CP/M код на NorthStar Horizon и запускать его на Seequa Chameleon. Отсутствие графического стандарта по большей части не пускало её на игровой рынок (хотя и были релизы Infocom), ориентируя в основном на бизнес-пользователей. Но всё-таки это было существенно, так что желание IBM использовать её в своём проекте «PC» в начале 80-х стало естественным. Тогда IBM собиралась запустить IBM PC с несколькими операционными системами, ожидая, что CP/M станет одной из основных. Но CP/M для x86 так и не вышла спустя полгода после запуска IBM PC, да и стоила она 240$ против 40$ за DOS.

В результате подавляющее большниство пользователей стали использовать PC-DOS от Microsoft, которая стала эволюцией новой операционки, разработанной Seattle Computer Products. Microsoft купила проект Тима Патерсона и создала на его основе PC-DOS, ставший впоследствии MS-DOS'ом. Операционка Тима Патерсона называлась «QDOS», что означало «Quick and Dirty Operating System» («быстрая и грязная операционная система»). Она была основана на CP/M, не имевшей x86 версии, и пыталась решить некоторые ограничения CP/M. Во многом это были очень схожие системы. Одной из общих черт была идея использования специальных файлов и отсутствия директорий. Поэтому QDOS и PC-DOS 1.0 имели все эти AUX, PRN, CON, LPT и т. д.

С выходом PC-DOS 2.0 в 1983 для нового IBM XT Microsoft значительно переделала PC-DOS. Вам очевидно были просто необходимы директории, чтобы держать в порядке ваши огромные 10-мегабайтные диски, появившиеся тогда на рынке. И снова незадача: пользователи работали со своими специальными файлами уже пару лет с момента выхода предыдущей версии PC DOS 1.0. Программы и скрипты были написаны, чтобы использовать эти файлы. С поддержкой директорий Microsoft могла бы наконец убрать всё в C:\DEV..., но не стала этого делать. Как будет случаться ещё не раз, Microsoft принесла здравый смысл на алтарь обратной совместимости: специальные файлы остались в каждой директории с любым расширением. Это наследие было пронесено через все версии вплоть до Windows 95. Но погодите-ка, мы сейчас не используем Windows 95, ведь современная ветвь операционок основана на Windows NT. Но и ей нужна была совместимость с DOS/Windows программами. Поэтому эти специальные файлы работают до сих пор, спустя сорок четыре грёбаных года! Попробуйте сами: откройте explorer, создайте новый текстовый файл и назовите его con.txt. aux.txt или prn.txt. Не тут-то было.



То есть благодаря Гэри Килдаллу, сказавшему «Специальные файлы представляют оброудование! Отличная идея, Unix. Я заимствую её и попытаюсь реализовать в моей игрушечной операционке» так давно, что родившиеся тогда люди могут уже иметь детей, которым разрешёно употреблять спиртное..., мы до сих пор не можем называть файлы con.txt. У Microsoft даже есть специальный список: CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, и LPT9. Для пущего веселья, вспомните, что попытка доступа к C:\con\con (или C:\aux\aux) сразу выкидывала Windows 95 в BSOD. Это было забавно в 1995 году, потому что тогда этому багу уже был 21 год!



Предыстория
Я наткнулся на это, когда понял, что у меня есть файл, который не может быть скопирован. Эти специальные имена файлов реализованы на уровне операционки, а не на уровне файловой системы. Таким образом, они являются валидными именами файлов в NTFS. А я использовал NTFS диск в linux. И судя по всему, OS/2 не поддерживает эту систему специальных имён, в результате чего среди файлов opengl оказался AUX.H на одном из дисков для Devcon.



А сегодня я попытался забэкапить этот NTFS диск на своём основном компьютере, и «упс, не могу скопировать все файлы из-за бага, старше, чем большинство людей, читающих это».

Пояснения
В CP/M работа со специальными именами реализована на самом деле не так просто, как я описал. Например, для обращения к устройству нужно, чтобы в имени было двоеточие: PRN: — это принтер, а PRN — нет. Кроме того, в CP/M работа с файлами устройств реализована не на уровне операционки, как в DOS. Это просто часть команды PIP для копирования файлов. То есть вы не сможете провернуть, как в DOS, трюк с указанием программе сохранить PRN.TXT для того, чтобы напечатать его.

И на всякий случай уточняю: я не имею ввиду ничего вроде «Винда — отстой». Обратная совместимость, как правило, прекрасная вещь. На самом деле я хочу БОЛЬШЕ обратной совместимости, не меньше. Просто я офигел, столкнувшись с 44-летним багом на запущенной Windows 10 при попытке копирования с одного USB 3.0 SSD диска на другой SSD. Это как жить на космической станции и быть затоптанным лошадью.
Tags:
Hubs:
Total votes 69: ↑61 and ↓8+53
Comments14

Articles