- •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.8. Объединение всего вместе: Is2.C
Мы проверили каждый компонент в выводе Is -1. Для каждого из них мы знаем, что означает каждое поле и как можно преобразовать значение поля в форму, наиболее понятную для пользовательского восприятия. В результате программа ls2.c будет такой:
/* Is2.c
* цель - вывод списка содержимого каталога или каталогов
* при отсутствии аргументов используется., в противном случае
* используется список имен файлов через список аргументов
* замечание - использует stat, pwd.h и grp.h
ж BUG: попробуйте Is2 /tmp
*/
#include <stdio.h>
«include <sys/types.h>
«include <dirent.h>
«include <sys/stat.h>
voiddo_ls(char[]); void dostatfchar *);
void showfilejnfofchar * struct stat *);
void mode_tOiletters(int, char []);
char *uidJo_name(uid_t);
char *gid_to_name(gid_t);
main(int ac, char *av[ ])
{
if(ac==l)
dojsf'.");
else
while (--ac){
prinrf("%s:\n", *++av);
do_ls(*av);
}
}
void do ls(char dirname[ ])
/*
* перечисляет файлы в каталоге с именем dirname
/*
{
DIR *dir_ptr; Г каталог */
struct dirent *direntp; /* какая запись */
if ((dir_ptr = opendir(dirname)) == NULL)
fprintf(stderr,"ls1: cannot open %s\n", dirname);
else
{
while ((direntp = readdir(dir_ptr)) != NULL)
dostat(direntp- >d_name);
closedir(dir ptr);
}
}
void dostatfchar *filename)
{
struct stat info;
if (stat(filename, &info) == -1) /* неудача у stat */
perror(filename); /* посмотреть почему */
else /* иначе показать информациюshow_ file_ info(filename, &info);
}
void show_file_jnfo(char *filename, struct stat *info p)
/*
* выводит информацию о 'filename'. Эта информация записана в структуре
*info_p
*/
{
char *uid_to_name(), *ctime(), *gid_to^name(), *filemode();
void mode_to_letters();
charmodestr[11];
mode_toJetters(info_p- >st_mode, modestr);
prinrf("%s", modestr);
printf("%4d", (int) info_p->st_nlink);
printf("%-8s", uid_to_name(info_p->st_uid));
printf("%-8s", gid_to_name(info_p->st_gid));
printf("%8ld", (long)info_p->st_size);
printf("%.12s", 4+ctime(&info_p->st_mtime));
printf("%s\n", filename);
}
/*
* utility functions
*/
/*
* В этой функции извлекается значение mode и формируется символьный массив.
* В символьный массив помещается значение типа файла и
* девять символов для представления прав доступа.
* ЗАМЕЧАНИЕ: Коды setuid, setgid sticky
* не рассматриваются
*/
void modejojettersfint mode, char str[ ])
{
strcpy(str,"--------------"); /* по умолчанию отсутствие прав */
if(SJSDIR(mode))str[0] = 'd'; /* каталог?*/
if (SJSCHR(mode)) str[0] = 'с'; /* символьные устройства */
if (SJSBLK(mode)) str[0] = 'b'; /* блочное устройство 7
if (mode & S IRUSR) str[1] = 'r'; /* 3 разряда для собственника */
if(mode&SJWUSR)str[2] = 'w';
if(mode&SJXUSR)str[3] = 'x';
if (mode & SJRGRP) str[4] = 'r'; /* 3 разряда для группы */
if(mode&SJWGRP)str[5] = 'w';
if (mode & SJXGRP) str[6] = Y;
if (mode & SJROTH) str[7] = 'r'; /* 3 разряда для остальных */
if(mode&S_IWOTH)str[8] = W;
if(mode&SJXOTH)str[9] = 'x';
}
«include <pwd.h>
char *uid to name(uid t uid)
/*
* возвращается указатель на пользовательское имя, соотнесенное
ж идентификатору uid, используется getpw()
*/
{
struct passwd *getpwuid(), *pw_ptr;
static char numstr[10];
if ((pw_ptr = getpwuid(uid)) == NULL){
sprintf(numstr,"% d", uid);
return numstr;
}
else
return pw ptr->pw name;
}
«include <grp.h>
char *gid to name(gid t gid)
/*
* возвращается указатель на имя группы, используется getgrgid(3)
*/
{
struct group *getgrgid(), *grp_ptr;
static char numstr[10];
if ((grp_ptr = getgrgid(gid)) == NULL){
sprintf(numstr,"% d", gid);
return numstr;
}
else
return grp ptr- >gr name;
}
И вот теперь запустим нашу программу и получим также для сравнения стандартный вывод:
drwxrwxr-x drwxrwxr-x -rw-rw-r-- -rwxrwxr-x -rw-rw-r-- -rw-r--r-- -rw-r--r-- -rw-rw-r- drwxrwxr-x drwxrwxr-x |
4 bruce 5 bruce 1 bruce 1 bruce 2 bruce 1 bruce 1 bruce 1 bruce 2 bruce 2 bruce |
bruce bruce users users users users users users users users |
1024 Aug \1024 Aug 30720 Aug 37351 Aug 345 Jul 723 Aug 3045 Feb 27521 Aug 1024 Aug 1024 Aug |
218:18. 218:14.. 1 12:05 s.tar 1 12:13 taill 29 11:05 Makefile 1 14:26 Is 1.с 15 03:51 Is2.c 1 12:14 chap03 1 12:14oldsrc 1 12:15 docs |
-rwxrwxr-x |
1 bruce |
bruce |
37048 Aug |
1 14:26 Is1 |
•rw-r-r-- |
1 bruce |
support |
946 Feb |
1817:15stat1.c |
-rwxrwxr-x |
2 bruce |
bruce |
42295 Aug |
2 18:18 Is2 |
-rw-r-r- |
1 bruce |
support |
191 Feb |
9 21:01 statdemo.c |
-rw-r-r- |
1 bruce |
users |
1416Aug |
1 12:05 tain, с |
$ ls-I total 189 |
||||
-rw-rw-r-- |
2 bruce |
users |
345 Jul |
29 11:05 Makefile |
-rw-rw-r-- |
1 bruce |
users |
27521 Aug |
1 12:14chap03 |
drwxrwxr-x |
2 bruce |
users |
1024 Aug |
1 12:15 docs |
-rwxrwxr-x |
1 bruce |
bruce |
37048 Aug |
1 14:26 Isl |
-rw-r--r- |
1 bruce |
users |
723 Aug |
1 14:26 Isl. с . |
-rwxrwxr-x |
2 bruce |
bruce |
42295 Aug |
2 18:18 Is2 |
-rw-r-r-- |
1 bruce |
users |
3045 Feb |
15 03:51 Is2.c |
drwxrwxr-x |
2 bruce |
users |
1024 Aug |
1 12:14old_src |
-rw-rw-r-- |
1 bruce |
users |
30720 Aug |
1 12:05 s.tar |
-rw-r--r- |
1 bruce |
support |
946 Feb |
18 17:15 statl.c |
-rw-r--r-- |
1 bruce |
support |
191 Feb |
9 1998 statdemo.c |
-rwxrwxr-x |
1 bruce |
users |
37351 Aug |
1 12:13 tain |
-rw-r--r- |
1 bruce |
users |
1416 Aug |
1 12:05 taiH.с |
$
Чего мы достигли?
Программа Is2 отображает информацию о файлах в стандарте вывода команды Is -I. Вывод выглядит хорошо. Он происходит поколонно, производится преобразование из внутреннего представления разрядов доступа и числовых значений идентификатора в читабельные строки.
Но программа все же нуждается в доработке. В реальной версии в самой первой строке вывода печатается строка total. Зачем нужна эта строка? Кроме того, в нашей программе все еще нет сортировки имен файлов, не работает опция - а, не производится упорядочения имен файлов по колонкам, программа рассматривает каждый аргумент при обращении к ней в качестве имени каталога.
В программе Is2 есть еще более серьезные проблемы. Она не будет корректно выдавать информацию о файлах, которые находятся в других каталогах. Для рассмотрения проблемы попытайтесь выполнить команду Is2 /tmp. Следует решить эту проблему, что вы должны сделать в качестве упражнения.
