Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Файлы, файлы, файлы (продолжение)

Виктор Хименко

Статья была опубликована в журнале «Мир ПК», #03/2000.
Первую часть статьи см. здесь.

Права доступа

Теперь, когда мы выяснили, какие объекты встречаются в файловой системе, полезно вспомнить, что Linux, подобно другим Unix-системам, является многопользовательской ОС, а значит, доступ к файлам должен ограничиваться: вряд ли вы будете в восторге, если все пользователи машины смогут читать ваши любовные письма...

Пользователи и группы

Стандартная система прав доступа в Linux, пришедшая все из тех же далеких 70-х, весьма проста и логична, хотя и не всегда удобна*. Ее базовые понятия - пользователь и группа. Каждый зарегистрированный в системе пользователь получает уникальный номер-идентификатор. Кроме того, он должен входить хотя бы в одну группу, которая является для него <главной>, и может входить в другие - <дополнительные> (supplementary groups). Все группы также перенумерованы. Файл всегда связан с определенным пользователем - своим владельцем - и с определенной группой, т. е. у него есть UID (User ID, идентификатор пользователя) и GID (Group ID, идентификатор группы). Изменять права доступа к файлу разрешено только его владельцу. Изменить владельца файла может суперпользователь, группу - суперпользователь или владелец файла (см. рис. 1).

Рис. 1. Midnight Commander: изменение владельца и группы файла с помощью команды chown

Программа, выполняющаяся в системе, всегда запускается от имени какого-то пользователя и какой-то группы (обычно - основной группы этого пользователя), но связь процессов с пользователями и группами организована сложнее: здесь различаются идентификатор для доступа к файловой системе (FSUID - File System access User ID, FSGID - File System access Group ID) и эффективный идентификатор (EUID - Effective User ID, EGID - Effective Group ID), а при доступе к файлам учитываются еще и полномочия (capabilities), присвоенные самому процессу. Соответствующие механизмы мы разберем, когда будем рассматривать управление процессами.

При создании файл получает UID, совпадающий с FSUID процесса, который его создает, и, как правило, GID, совпадающий с FSGID этого процесса; об исключении будет сказано чуть ниже.

Атрибуты доступа

Права доступа приписываются узлу файла. Каждому файлу сопоставлены три набора атрибутов доступа: для владельца, для группы и для всех остальных.

Атрибуты определяют, что разрешено делать с данным файлом данной категории пользователей. Каков же набор возможных операций в Linux (и - шире - в Unix)? Оказывается, их всего три: чтение, запись и выполнение. Как же, спросите вы, быть, например, с созданием и удалением файлов? И как можно выполнить каталог?

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

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

Помимо трех названных основных атрибутов доступа существуют дополнительные, используемые в особых случаях. Наиболее важные из них - SUID, SGID и SVTX.

Атрибуты SUID и SGID существенны при запуске программы на выполнение: они требуют, чтобы программа выполнялась не от имени запустившего ее пользователя (группы), а от имени владельца (группы) того файла, в котором она находится. Выражаясь более формально, если файл программы имеет атрибут SUID (SGID), то FSUID и EUID (FSGID и EGID) соответствующего процесса не наследуются от процесса, запустившего его, а совпадают с UID (GID) файла. Благодаря этому <рядовые> пользователи получают, например, возможность запустить системную программу, которая создает свои рабочие файлы в закрытых для них каталогах.

Кроме того, если процесс создает файл в каталоге, имеющем атрибут SGID, то файл получает GID не по FSGID процесса, а по GID каталога. Это удобно для коллективной работы: все файлы и подкаталоги в каталоге автоматически оказываются принадлежащими одной и той же группе, хотя создавать их могут разные пользователи.

Атрибут SVTX (называемый также sticky bit, т. е. бит-липучка) в эпоху молодости Unix определял, нужно ли выгружать программу из памяти по окончании ее выполнения, однако сейчас от ручного управления выгрузкой отказались. Зато SVTX приобрел новое значение применительно к каталогам: из каталога, имеющего этот атрибут, ссылку на файл может удалить только владелец файла. SVTX применяется в первую очередь в каталоге /tmp, где хранятся временные файлы: создать там файл может любой пользователь системы, а удалить - только тот, кто его создал (и, разумеется, суперпользователь).

Запись прав доступа

Существуют две стандартных формы записи прав доступа - символьная и восьмеричная. Символьная представляет собой цепочку из десяти знаков, первый из которых не относится собственно к правам, а обозначает тип файла ('-' - обычный файл, 'd' - каталог, 'c' - символьное устройство, 'b' - блочное устройство, 'p' - именованный канал, 's' - <гнездо>, 'l' - символическая ссылка). Далее следуют три последовательности, каждая из трех символов, соответствующие правам пользователя, группы и всех остальных. Наличие права на чтение обозначается буквой 'r', на запись - 'w' на выполнение - 'x', отсутствие какого-либо права - знаком '-' в соответствующей позиции. Наличие атрибута SUID (SGID) обозначается буквой 'S' в позиции права на выполнение для владельца (группы), если выполнение не разрешено, и буквой 's', если разрешено. SVTX записывается соответственно буквой 'T' или 't' в позиции права на выполнение для <посторонней публики>.

Восьмеричная запись - шестизначное число, первые два знака которого обозначают тип файла и довольно часто опускаются, третий - атрибуты GUID (4), SGID (2) и SVTX (1), а оставшиеся три - соответственно права владельца, группы и всех остальных: чтение - 4, запись - 2, выполнение - 1.

Например, стандартный набор прав доступа для каталога /tmp в символьной форме выглядит как drwxrwxrwt, а в восьмеричной как 041777 (это каталог; чтение, запись и поиск разрешены всем; установлен атрибут SVTX). А набор прав -r-S-xw-, или 102412, будет означать, что это обычный файл, владельцу разрешается читать его, но не выполнять и не изменять, пользователям из группы файла (за исключением владельца) - выполнять (причем во время работы программа получит права владельца файла), но не читать и не изменять, а всем остальным - изменять, но не читать и не выполнять. Пример, конечно, условный: трудно вообразить себе ситуацию, в которой действительно потребовалось бы назначить файлу подобные права доступа.

А вот несколько более реалистичный пример. Вообразим себе, что среди пользователей некой машины имеется группа <писателей>, которые сочиняют коллективную монографию, и группа <читателей>, которые по ходу написания читают ее и высказывают свои замечания. Пользователям, не входящим ни в одну из этих групп, материалы должны быть недоступны. На первый взгляд кажется, что здесь мы натыкаемся на ограниченность системы прав Linux: у файла (или каталога) может быть только один GID.

Однако выход достаточно прост: если сформировать группы так, чтобы список <писателей> был включен в список группы <читателей> (что вполне логично - только в анекдоте чукча может быть писателем, не будучи читателем), то нужного результата можно добиться с помощью иерархии из двух каталогов:

d--r-x-- /readers UID=0,
GID=
d--rwsr-x /readers/writers
UID=0, GID=

Все файлы размещаются в каталоге /readers/writers. Модифицировать их разрешено <писателям>, а читать всем, но реально добраться до этого каталога смогут только те, у кого есть право на выполнение каталога /readers, т. е. <читатели>.

Большинство программ создают файлы с разрешением на чтение и запись для всех пользователей, а каталоги - с разрешением на чтение, запись и поиск для всех пользователей. Этот исходный набор атрибутов логически складывается с <пользовательской маской> - user file-creation mask, сокращенно umask, которая обычно ограничивает доступ. Так, для описанного только что примера значение umask должно быть u=rwx,g=rwx,o=rx, т. е. у владельца и группы остается полный набор прав, а всем остальным запрещается запись. В восьмеричном виде оно запишется как 002 (первый знак - ограничения для владельца, второй - для группы, третий - для остальных, запрещение чтения - 4, записи - 2, выполнения - 1).

В дальнейшем владелец файла может изменить права доступа к нему командой chmod, а если он не хочет разбираться с запутанным синтаксисом команды, то с помощью какой-либо из многочисленных программ-оболочек (например, Midnight Commander - см. рис. 2).

Рис. 2. Midnight Commander: изменение прав доступа к файлу

Новые пользователи часто не могут понять, в чем разница между атрибутами <время модификации> (modification time) и <время изменения> (change time). В действительности первое соответствует тому моменту, когда в последний раз изменялось содержимое файла, а второе - тому, когда изменялись его характеристики, например ссылки или права доступа.

Об именах

Вернемся теперь к именам файлов. Как уже говорилось, они не очень важны с точки зрения Linux и вообще Unix: например, существует функция системной библиотеки, которая создает и сразу же <удаляет> файл со случайным именем, после чего возвращает ссылку на него. Ставший безымянным файл продолжает существовать до окончания использования, так что программа получает в свое распоряжение файл, к которому нельзя обычным образом обратиться извне. Однако с точки зрения пользователя имя все-таки представляет собой довольно существенный параметр файла.

Какие же ограничения накладываются на имена файлов? Их немного - поразительно немного для людей, работавших ранее с другими ОС:

  • имя файла не должно содержать символов '\0' (символ с кодом 0) и '/';
  • имя файла не должно быть длиннее 255 символов;
  • полный путь к файлу должен быть не длиннее 4096 символов.

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

Имена файлов считаются одинаковыми, если они совпадают побитно, т. е. разница между большими и маленькими буквами существенна. Тем самым, проблема поддержки разных кодировок отпадает: ядру системы неважно, какой набор символов использовался для записи имени - Latin 1, koi8-u, UTF-8 или Big5, лишь бы в нем не встречались два <запрещенных> символа. Иногда это приводит к курьезам. Например, в результате загрузки с помощью программы Minicom файла C:\WINDOWS\ COMMAND\EDIT.COM вполне может образоваться файл с именем из 27 символов - <C:\WINDOWS\ COMMAND\EDIT.COM> (первый символ - 'C', второй - ':', третий - '\\' и т. д).

К сожалению, допустимость имени с точки зрения ядра системы еще не гарантирует того, что с ним смогут работать прикладные программы. Среди последних немало даже таких, которые вообще не признают символов с ненулевым старшим битом (а значит, <не понимают> русских букв). В этом смысле русификация Linux является противоположностью русификации DOS: в DOS основной проблемой было <научить> систему вводить и отображать русские буквы (особенно в именах файлов); когда это было сделано, большинство программ начали совершенно свободно работать с кириллицей. В Linux же поддержка русских букв имелась в ядре системы <с самого начала> (их ввод и вывод на системной консоли был обеспечен хотя и не <с самого начала>, но также очень и очень давно), а все необходимое для русификации (за исключением, пожалуй, масштабируемых шрифтов) входит в комплект любого современного дистрибутива. Однако программы зачастую отказываются работать с русскими буквами, и их нужно либо специально настраивать (как, например, bash), либо обманывать с помощью <шаманских> приемов (так приходится поступать со StarOffice).

<Чужие> файловые системы

Поговорим теперь немного о поддерживаемых в Linux <чужих> файловых системах. В действительности общих правил работы с ними не существует - слишком уж они разнообразны, - поэтому ограничимся тем, что рассмотрим по отдельности несколько наиболее важных.

Файловые системы Unix

Начать удобнее с систем, которые нельзя считать в полном смысле слова <чужими>, поскольку они также применяются в ОС семейства Unix и обслуживаются ядром Linux наравне со стандартной Ext2 fs. Это Minix fs (Minix, Xenix), System V/Coherent fs (System V, Xenix) и UFS (FreeBSD, NetBSD, OpenBSD, SunOS/Solaris, NextStep, OpenStep).

Во всех названных системах (включая, естественно, и Ext2 fs) пользователи и группы представлены только идентификаторами (UID, GID); фактически ядро ОС ничего не знает об их именах. Следовательно, человек, сумевший подключить ваш диск к машине, на которой он является суперпользователем, получит возможность читать и модифицировать любую информацию на диске, не зная пароля суперпользователя вашей системы. (В ряде случаев для этого достаточно быть суперпользователем одной из установленных на машине ОС, причем не обязательно Linux - подойдет даже Windows 95, если только злоумышленнику удастся получить из нее доступ к вашему диску.)

Поэтому обычно не имеет смысла ограничивать права доступа к файлам на сменных носителях информации. Чтобы защитить хранящиеся там данные, лучше их зашифровать. О прозрачном шифровании файлов в Linux можно узнать по адресам http://www.kerneli.org/ и http://tcfs.dia.unisa.it/. В дальнейшем поддержка шифрования, видимо, будет встроена в ядро Linux (в связи с изменением законодательства США, касающегося экспорта криптотехнологий, такая возможность теперь появилась), однако неясно, произойдет ли это уже в версии 2.4.

FAT

Наиболее распространенная файловая система - это, конечно же, FAT (в Linux она называется msdos). Множество пророков множество раз предсказывали ей смерть, и все же ее модификации (VFAT, FAT32) до сих пор служат основной файловой системой в Windows 9x, а для дискет даже Windows NT не предлагает ничего другого. Оригинальная версия FAT, сохранявшаяся практически неизменной от MS-DOS 2.0 до MS-DOS 6.22, крайне проста: вся информация о файле хранится в каталоге, и для доступа к ней используется имя файла, построенное по так называемой <формуле 8+3>, т. е. состоящее из собственно имени длиной до 8 символов и расширения длиной до 3 символов, разделенных точкой.

Большие и маленькие буквы в именах файлов не различаются: при всех операциях с файлами используются большие буквы (именно это свойство породило известные проблемы с русскими буквами в именах файлов, продержавшиеся вплоть до появления русифицированной версии Windows 3.1). У каждого файла хранится время последней модификации (с точностью до 2 с) и могут быть установлены атрибуты Read Only (только для чтения), Archive (архивный), Hidden (скрытый) и System (системный).

При монтировании диска с FAT атрибут Read Only отображается в соответствующий атрибут файловой системы Linux, остальные же игнорируются, поскольку не имеют аналога. В результате файлы с атрибутом Read Only получают набор прав доступа r-xr-xr-x, а все прочие - rwxrwxrwx. Чтобы как-то еще ограничить права доступа, следует задать среди параметров монтирования нужное значение umask, а чтобы при этом предоставить привилегии определенным пользователям, - указать соответствующие UID и GID. Можно также просто разрешить пользователям самим монтировать разделы, но это не очень удобно, поскольку нельзя смонтировать один и тот же раздел дважды.

VFAT и FAT32

Файловая система VFAT впервые появилась в Windows NT, а широкое распространение получила после выхода Windows 95: это усовершенствованная версия FAT, в которой разрешены длинные имена файлов. FAT32, введенная в Windows 95 OSR2 и поддерживаемая в Windows 98, отличается от VFAT лишь количественными параметрами: она допускает меньший размер кластеров и больший размер дисков, не ограничивает число файлов в корневом каталоге и т. д. Поэтому в Linux работа с VFAT и FAT32 происходит совершенно одинаково; для FAT32 нет даже отдельного драйвера. С этим связан забавный момент: RedHat Linux 5.1 поддерживает FAT32, но единственный способ узнать об этом - попытаться смонтировать соответствующий раздел и убедиться, что он монтируется. В документации FAT32 не упоминается.

Появившиеся в VFAT длинные имена сделали работу с файлами более удобной, однако породили ряд проблем. Во-первых, VFAT сохраняет в именах разницу между большими и маленькими буквами, но для доступа к файлам разрешает использовать любые их комбинации. Во-вторых, что более существенно, у каждого файла в VFAT есть два имени - длинное и короткое. При просмотре диска Linux показывает в смонтированном разделе VFAT только длинные имена, но по короткому имени доступ к файлу также будет предоставлен, а при попытке создать новый файл, имя которого совпадет с коротким именем существующего файла, вы получите сообщение о том, что такой файл уже есть, - точно так же, как и в Windows.

Далее, если в VFAT дать файлу имя, удовлетворяющее ограничениям FAT и состоящее из символов стандартного набора ASCII, то Windows 95 и NT будут считать, что он имеет только короткое имя. При этом с точки зрения Windows 95 такое имя будет состоять только из больших букв, а с точки зрения Windows NT - только из маленьких. Linux здесь выбирает строну NT (по историческим причинам). В большинстве случаев все это не имеет значения; сложности возникают лишь при работе с программой установки RedHat Linux и ее производными, которые отличаются повышенной чувствительностью к названиям каталогов с исходными файлами.

И, наконец, длинные имена файлов записываются в кодировке Unicode. Поэтому при монтировании разделов с VFAT необходимо задавать правила их преобразования, что делается с помощью параметра iocharset; в наших условиях обычно указывают iocharset=koi8-r. Если длинное имя содержит символы, не имеющие соответствия в текущем iocharset, к файлу обратиться невозможно. Чтобы получить доступ ко всем файлам (правда, имена их примут неудобочитаемый вид), нужно вместо iocharset указать uni_xlate= true или utf8= true (подробнее см. /usr/src/linux/Documentation/filesystems/vfat.txt).

Набор символов для коротких имен задается параметром codepage. Когда Windows настроена на русский язык, для коротких имен применяется CP 866 (кодировка DOS), поэтому следует указать codepage=cp866.

ISO-9660

Хотя название этой файловой системы вам, возможно, незнакомо, вы с ней наверняка не раз сталкивались: ISO-9660 используется на CD-ROM**. Ее исходная версия не поддерживает прав доступа и символических ссылок; для имен файлов допустима длина до 32 символов, причем большие и маленькие буквы не различаются. Кроме того, если имя файла не укладывается в схему 8+3, то файл не будет доступен из MS-DOS, а если оно состоит из маленьких букв (некоторые программы позволяют так сделать), то и из Windows NT.

Ограничения ISO-9660 преодолеваются в ее расширенном варианте, который называется Rock Ridge. С ним работают различные Unix-системы, включая Linux, но ни в одной из версий Windows он не поддерживается. Зато для Windows 95 разработано альтернативное расширение - Joliet, обеспечивающее только поддержку длинных имен файлов (в формате Unicode); с ним Linux также умеет работать.

При монтировании CD-ROM разрешается отключить Rock Ridge (Joliet) и, если не используется RockRidge, указать UID, GID и umask. Для дисков с Joliet задается iocharset; можно указать и utf8, но не uni_xlate. Все эти параметры имеют то же значение, что и для (V)FAT.

NTFS

О работе с NTFS, к сожалению, можно сказать мало утешительного. Это исключительно сложная и гибкая файловая система, а открытая документация по ней практически отсутствует. Два названных свойства и определяют границы поддержки NTFS в Linux. Обеспечивается работа с версиями вплоть до NTFS4 (Windows NT 4.0). Версия же NTFS5 (Windows 2000 Pro) не поддерживается, и неизвестно, когда появится ее поддержка (если появится вообще).

Даже для тех версий, с которыми Linux работает, доступ предоставляется только к основной секции файла: в NTFS файл может иметь произвольное число секций, аналогичных <вилкам> (forks) MacOS (но в MacOS у каждого файла ровно две секции - <вилка данных> и <вилка ресурсов>). А запись в раздел NTFS возможна только в особом экспериментальном режиме, перед включением которого рекомендуется подготовиться к восстановлению диска после полной потери данных, - и это не просто громкое предупреждение.

Вся система прав доступа NTFS в Linux игнорируется, и доступ к файлам регулируется так же, как для FAT. Правда, если указать параметр posix=yes, можно будет увидеть все имена файлов - и короткие, и длинные. Заодно это позволит увидеть файлы с именами, отличающимися только регистром символов. Откуда они берутся? Дело в том, что в Windows NT есть подсистема POSIX, внутри которой различаются большие и маленькие буквы, есть возможность создавать жесткие ссылки и т. д. Она иногда используется при переносе программ из Unix в Windows NT.

В Linux поддерживается еще много файловых систем (HFS, HPFS и др.), но они реже встречаются на практике, и исследование их особенностей я оставляю читателю. Сетевые файловые системы - coda, smbfs, nсpfs и nfs - мы рассмотрим позже, когда перейдем к работе Linux в сети.

Об авторе

Виктор Хименко, e-mail: khim@sch57.msk.ru

Окончание. Начало см. в <Мире ПК>, © 2/2000, с. 64.


* Сейчас предпринимаются попытки заменить систему прав доступа в Linux на другую, более гибкую, но в ядре 2.4 она, видимо, останется прежней.


** Что касается звуковых компакт-дисков, то работа с ними как в Windows, так и в Linux осуществляется специальными программами и не требует поддержки со стороны файловой системы. Для Linux разработана также файловая система audiofs (http:// fly.cc.fer.hr/~ptolomei/ audiofs/), в которой данные на звуковых CD представляются как нормальные файлы, однако она не включена в стандартное ядро.

Постоянный URL статьи: http://www.osp.ru/pcworld/2000/03/154782/