Linux программирование в примерах - Роббинс Арнольд
Шрифт:
Интервал:
Закладка:
245 int m1[] = { 1, S_IREAD>>0, 'r', '-' };
246 int m2[] = { 1, S_IWRITE>>0, 'w', '-' };
247 int m3[] = { 2, S_ISUID, 's', S_IEXEC>>0, 'x', '-' };
248 int m4[] = { 1, S_IREAD>>3, 'r', '-' };
249 int m5[] = { 1, S_IWRITE>>3, 'w', '-' };
250 int m6[] = { 2, S_ISGID, 's', S_IEXEC>>3, 'x', '-' };
251 int m7[] = { 1, S_IREAD>>6, 'r', '-' };
252 int m8[] = { 1, S_IWRITE>>6, 'w', '-' };
253 int m9[] = { 2, S_ISVTX, ' t', S_IEXEC>>6, 'x', '-' };
254
255 int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9 };
256
257 pmode(aflag) /* void pmode(int aflag) */
258 {
259 register int **mp;
260
261 flags = aflag;
262 for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])];)
263 select(*mp++);
264 }
265
266 select(pairp) /* void select(register int *pairp) */
267 register int *pairp;
268 {
269 register int n;
270
271 n = *pairp++;
272 while (--n>=0 && (flags&*pairp++)==0)
273 pairp++;
274 putchar(*pairp);
275 }
Строки 245–275 выдают права доступа к файлу. Код компактен и довольно элегантен, он требует тщательного изучения.
• Строки 245–253: массивы с m1 по m9 кодируют биты прав доступа для проверки вместе с соответствующими буквами для вывода. На каждую выводимую букву режима файла имеется один массив. Первый элемент каждого массива является числом пар (право доступа, буква), закодированных в данном конкретном массиве. Последний элемент является буквой, которая должна быть выведена в случае, если не найден ни один из битов прав доступа.
Обратите также внимание, что права доступа обозначены как 'I_READ>>0', 'I_READ>>3', 'I_READ>>6' и т.д. Отдельные константы для каждого бита (S_IRUSR, S_IRGRP и т.п.) не были еще придуманы. (См. табл. 4.5 в разделе 4 6.1 «Указание начальных прав доступа к файлу».)
• Строка 255: массив m указывает на каждый из массивов с m1 по m9.
• Строки 257–264: функция pmode() сначала устанавливает глобальную переменную flags равной переданному параметру aflag. Затем она просматривает в цикле массив m, передавая каждый элемент функции select(). Переданный элемент представляет один из массивов с m1 по m9.
• Строки 266–275: функция select() понимает структуру каждого из массивов с m1 по m9. n является числом пар в массиве (первый элемент); его устанавливает строка 271. Строки 272–273 ищут биты прав доступа, проверяя установленную ранее в строке 261 глобальную переменную flags.
Обратите внимание на использование оператора ++ как в проверке цикла, так и в теле цикла. Результатом является пропуск пары в массиве, если в flags не обнаружен бит доступа в первом элементе пары.
Когда цикл завершается, либо бит разрешения был найден, в этом случае pairp указывает на второй элемент пары, являющийся нужным для вывода символом, либо он не был найден, в этом случае pairp указывает на символ по умолчанию. В любом случае, строка 274 выводит символ, на который указывает pairp.
Последним стоящим внимания моментом является то, что на С символьные константы (такие как 'x') имеют тип int, а не char[75]. Поэтому проблем с помещением этих констант в массив целых нет; все работает правильно.
277 char* /* char *makename(char *dir, char *file) */
278 makename(dir, file)
279 char *dir, *file;
280 {
281 static char dfile[100];
282 register char *dp, *fp;
283 register int i;
284
285 dp = dfile;
286 fp = dir;
287 while (*fp)
288 *dp++ = *fp++;
289 *dp++ = '/';
290 fp = file;
291 for (i=0; i<DIRSIZ; i++)
292 *dp++ = * fp++;
293 *dp = 0;
294 return(dfile);
295 }
Строки 277–295 определяют функцию makename(). Ее работа заключается в соединении имени каталога с именем файла, разделенным символом косой черты, с образованием строки. Она осуществляет это в static буфере dfile. Обратите внимание, что dfile всего лишь 100 символов длиной и что проверка ошибок не выполняется.
Сам код прост, он копирует по одному символу за раз. makename() используется функцией readdir().
297 readdir(dir) /* void readdir(char *dir) */