- •2.1. Введение
- •2.2. Вопросы, относящиеся к команде who
- •2.2.1. Программы состоят из команд
- •2.3. Вопрос 1: Что делает команда who?
- •2.3.1. Обращение к справочнику
- •2.4. Вопрос 2: Как работает команда who?
- •2.4.1. Мы теперь знаем, как работает who
- •2.5. Вопрос 3: Могу ли я написать who?
- •2.5.1. Вопрос: Как я буду читать структуры из файла?
- •2.5.2. Ответ: Использование open, read и close
- •2.5.3. Написание программы who 1.С
- •2.5.4. Отображение записей о вхождениях в систему
- •2.5.5. Написание версии who2.С
- •2.6. Проект два: Разработка программы ср (чтение и запись)
- •2.6.1. Вопрос 1: Что делает команда ср?
- •2.6.2. Вопрос 2: Как команда ср создает файл и как пишет в него? Создание/транкатенация файла
- •2.6.3. Вопрос 3: Могу ли я написать программу ср?
- •2.6.4. Программирование в Unix кажется достаточно простым
- •2.7. Увеличение эффективности файловых операций ввода/ вывода: Буферирование
- •2.7.1. Какой размер буфера следует считать лучшим?
- •2.7.2 Почему на системные вызовы требуется тратить время?
- •2.7.3. Означает ли, что наша программа who2.С неэффективна?
- •2.7.4. Добавление буферирования к программе who2.С
- •2.8. Буферизация и ядро
- •2.8.1. Если буферизация столь хороша, то почему ее не использует ядро?
- •2.9. Чтение файла и запись в файл
- •2.9.1. Выход из системы: Что происходит?
- •2.9.2. Выход из системы: Как это происходит
- •2.9.3. Смещение текущего указателя: Iseek
- •2.9.4. Кодирование выхода из системы через терминал
- •2.10. Что делать с ошибками системных вызовов?
- •3.1. Введение
- •3.2. Вопрос 1: Что делает команда is?
- •3.2.1. Команда Is выводит список имен файлов и оповещает об атрибутах файлов
- •3.2.3. Наиболее употребимые опции
- •3.2.4. Первый ответ: Итоговые замечания
- •3.3. Краткий обзор дерева файловой системы
- •3.4. Вопрос 2: Как работает команда Is?
- •3.4.1. Что же такое каталог, в конце концов?
- •3.4.2. Работают ли системные вызовы open, read и close в отношении каталогов?
- •3.4.3. Хорошо, хорошо. Но как же мне прочитать каталог?
- •3.5. Вопрос 3: Могу ли я написать Is?
- •3.5.1. Что еще нужно делать?
- •3.6. Проект 2: Написание версии Is -I
- •3.6.1. Вопрос 1: Что делает Is-I?
- •3.6.2. Вопрос 2: Какработает Is -I?
- •3.6.3. Ответ: Системный вызов stat получает информацию о файле
- •3.6.4. Какую еще информацию можно получить с помощью системного вызова stat?
- •3.6.5. Чего мы достигли?
- •3.6.6. Преобразование числового значения поля mode в символьное значение
- •3.6.7. Преобразования числового представления идентификаторов собственника/группы в строковое представление
- •3.6.8. Объединение всего вместе: Is2.C
- •3.7. Три специальных разряда
- •3.7.1. Разряд Set-User-id
- •3.7.2Разряд Set-Group-id
- •3.7.3 Разряд Sticky Bit
- •3.7.4. Специальные разряды nls-l
- •3.8. Итоги для команды is
- •3.9. Установка и модификация свойств файла
- •3.9.1. Тип файла
- •3.9.2. Разряды прав доступа и специальные разряды
- •3.9.3. Число ссылок на файл
- •3.9.4. Собственник и группа для файла
- •3.9.5. Размер файла
- •3.9.6. Время последней модификации и доступа
- •3.9.7. Имя файла
3.6.7. Преобразования числового представления идентификаторов собственника/группы в строковое представление
В нашем варианте в выводе для представления собственника и группы выдаются числа. В стандартном выводе команды Is выводится символьное пользовательское имя и имя группы. Какая связь между числовым идентификатором пользователя иго и пользовательским именем?
При обращении к документации для поиска по ключевым словам username, uid и group будет получен весьма различный по составу результат поиска, который будет зависеть от версии Unix. Посмотрим, что можно найти. Есть несколько интересующих нас факторов.
Фактор первый: Файл /etc/passwd содержит список пользователей
Как производится ваш вход в Unix - машину? Сначала система запросит у вас входное пользовательское имя, а затем пароль. Далее система определяет, верны ли указанные значения входного пользовательского имени и пароля. Как она узнает об их правильности?
Традиционная система для учета пользовательских имен и паролей состоит из файла /etc/1 passwd. В этом поле находится список всех пользователей данной системы. СодержимоеI файла выглядит так:
root:WPA4d1OwUxypE:0:0:root:/root:/bin/bash bin:*: 1:1.'Dim/bin:
daemon:*:2:2:daemon:/sbin:
smith:x 1 mEPcp4TNokc:9768:3073: James Q Smith:/home/s/smith:/shells/tcsh fred:mSuVNOF4CRTmE:20359:550:Fred:/homeA/fred:/shellsAcsh diane:7oUS8f1PsrccY:20555:550:DianeAbramov.7home/d/diane.7shellsAcsh ajr:WitmEBWylar1w:3607:3034:AnnReuter:/home/a/ajr:/shells/bash
Этот последовательный текст представляет собой список пользователей и информации о каждом из пользователей. Каждая строка в файле представляет одного пользователя. Поля в каждой строке разделяются знаком двоеточия. Первое поле предназначено для хранения пользовательского имени. Второе поле содержит зашифрованный пароль. Третье поле хранит значение пользовательского идентификатора, четвертое поле предназначено для хранения идентификатора группы, членом которой является пользователь. Следующие поля: поля для представления фактического имени пользователя, поле для указания домашнего каталога пользователя, поле для хранения маршрутного имени программы. которую пользователь использует в качестве shell. (Речь идет о произвольной про-
грамме, которая запускается в начале сессии пользователя. - Примеч. пер.) Файл passwd доступен для чтения для всех категорий, пользователей. Для более детального ознакомления с файлом обратитесь к электронному справочнику с аргументом passwd.
Все выглядит вполне оптимистично. Достаточно найти в файле запись, которая содержит необходимый идентификатор пользователя, а далее необходимо прочитать первое поле в выбранной строке. Но этот метод не перспективен и вот почему: поиск в файле /etc/passwd - достаточно скучное занятие, кроме того метод не работает во многих сетевых системах.
Фактор второй: В файле /etc/passwd не всегда содержится полный список пользователей
В каждой системе Unix есть файл /etc/passwd, но во многих системах Unix в этот файл включаются не все пользователи. В сетевых реализациях систем предполагается регистрация пользователей на любой машине в сети с одним и тем же именем пользователя и паролем. Чтобы достигнуть такой возможности, используют файл /etc/passwd . Системный администратор должен будет добавить в этот файл на каждой машине в сети одно и то же пользовательское имя и текущий пароль. Когда пользователь захочет изменить на какой-то машине пароль, то это изменение должно быть сделано в каждом файле /etc/passwd сети. Если одна из машин будет недоступна, то это может привести к нарушению процесса синхронизации в отношении оставшихся машин.
Одно из решений - инсталлировать минимально файл /etc/passwd на каждой машине для автономных действий, но поддерживать полный список пользователей в базе данных, которая доступна в сети. Все новые пользователи и изменения паролей записываются в эту центральную базу данных. Все программы, которым необходима информация о пользователе, будут обращаться к центральной базе данных. Система с централизованной сетевой информацией называется nis. В электронном справочнике можно получить дополнительную информацию по этому поводу.
Фактор третий: Доступ к полному списку пользователей обеспечивает функция getpwuid
Библиотечная функция getpwuid предоставляет доступ к пользовательской информации в базе данных. Если в вашей системе используется файл passwd, то функция будет работать с этим файлом. А если используется центральная база данных, то функция getpwuid будет работать с этой базой. При использовании функции getpwuid в качестве аргумента задается идентификатор пользователя, а в результате функция возвращает указатель на структуру struct passwd, которая описана в файле /usr/include/pwd.h так:
/* Структура passwd. *,'
struct passwd
{
char *pw_name; /* Пользовательское имя. */
char *pw_passwd; /* Пароль. */
_uid_t pw_uid; /* Пользовательский ID. */
_gid_t pwgid; /* Групповой ID. */
char *pw_gecos; /* Реальное имя. */
char *pw_dir; /* Домашний каталог. */ '
char *pw shell; /* Программа Shell. */
};
Эта функция и описание этой структуры дают нам возможность организовать вывод поля с пользовательским именем в длинном формате. Вот таким может быть простое решение:
/*
* возвращается пользовательское имя, соотнесенное uid
* ЗАМЕЧАНИЕ: код не работает, если нет пользовательского имени
*/
char *uid_to_name(uid t uid)
{
return getpwuid(uid)->pw name;
}
Эта функция проста, но ненадежна. Если значению uid не найдено соответствующее пользовательское имя, то функция getpwuid возвращает указатель NULL. В этом случае нечего разыменовывать в pwjiame. Как это может произойти? В стандартной версии команды Is приводится решение этой проблемы.
Фактор четертый: Для некоторых UID нет входных имен
Скажем, что вы зарегистрированы на некоторой Unix-машине и вам присвоено пользовательское входное имя pat, значение идентификатора пользователя равно 2000. Когда вы создаете файлы, то будете собственником этих файлов. То есть системный вызов stat будет возвращать в качестве результата структуры для ваших файлов, где в поле stuid будет находиться 2000. Это число является атрибутом файла.
Далее вы уехали в другой город. Системный администратор удалит учетную запись о вас из файла passwd. Тем самым удаляется связь между числом 2000 и пользовательским именем pat. Если программа будет передавать число 2000 при обращении к системному вызову getpwuid, то системный вызов будет возвращать null.
В стандартной версии Is происходит обработка данной ситуации - будет выводиться uid, если нет соответствующего пользовательского имени.
Что произойдет, если в системе будет зарегистрирован новый пользователь и ему будет присвоено значение старого иго? В системе могли остаться файлы, у которых теперь собственником становится этот новый пользователь. Этот пользователь имеет права на чтение, запись и удаление этих файлов.
И наконец, как мы можем преобразовать идентификатор группы в имя группы? Что такое группа? Что такое идентификатор группы?
Фактор пятый: Файл /etc/group содержит список групп
Рассмотрим Unix-машину, которая используется в сфере бизнеса. В этой области все работники сгруппированы по отделам и отдельным проектам. Может быть группа людей, которые занимаются продажами, группа менеджмента и т. д.
Рассмотрим школу. Весь состав людей в школе можно представить так: учителя, школьники, администрация. Людей можно сгруппировать и по другим признакам - по принадлежности студентов к одному и тому же курсу, по месту работы в одном и том же отделе.
В Unix имеется система для регистрации групп и введения пользователей в состав групп: Имеется файл /etc/group, который является обыкновенным текстовым файлом и который выглядит примерно так:
root::0:root
other:: 1:
bin::2:root,bin,daemon
sys::3:root,bin,sys,adm
adm::4:root,adm,daemo
uucp::5:root,uucp
mail::6:root
tty::7:root,tty,adm
lp::8:root,lp,adm
Первое поле предназначено для хранения имени группы, во второе поле записывается пароль группы (редко используется на практике), в третье поле записывается идентификатор группы, в четвертом поле хранится список пользовательских имен. Элементы списка разделяются запятыми. Эти пользователи составляют группы.
Фактор шестой: Пользователь может быть членом более чем одной группы
В файле passwd для каждого пользователя заведены поля иго и gid. Идентификатор группы в файле passwd указывает первичную группу для пользователя, но пользователь может быть также зарегистрирован в составе других групп. В примере, приведенном выше, вы можете заметить, что пользователь adm находится в группах с именами sys, adm, tty, lp. Этот список используется при работе с разрядами прав доступа для группы. Например, если файл принадлежит группе с именем 1р и для группы установлены права на запись, тогда пользователь adm может модифицировать этот файл.
Фактор седьмой: Системный вызов getgrgid предоставляет доступ к списку групп
В сетевом варианте системы данные, которые размещаются в файле /etc/group, также можно переместить в центральную базу данных. Аналогично работе со статусной информацией для файлов в Unix есть возможность получать доступ к списку групп независимо от реализации системы. В документации на getgrgid приведены детали и необходимая информация. Для наших целей будем использовать код, подобный приведенному ниже.
/*
* возвращает имя группы, которое соотнесено указанному gid
* ЗАМЕЧАНИЕ: не работает, если нет имени группы
*/
char "gid to name(gid t uid)
{
return getgrgid(gid)- >gr name;
}
