Linux программирование в примерах
Часть 82 из 253 Информация о книге
86 statreq++;87 continue;8889 case 'r': /* Обратный порядок сортировки */90 rflg = -1;91 continue;9293 case 't': /* Сортировка по времени, не по имени */94 tflg++;95 statreq++;96 continue;9798 case 'u': /* Время доступа, а не изменения */99 uflg++;100 continue;101102 case 'c': /* Время изменения индекса, а не файла */103 cflg++;104 continue;105106 case 'i': /* Включить номер индекса */107 iflg++;108 continue;109110 case 'f': /* Форсировать чтение каждого arg как каталога */111 fflg++;112 continue;113114 default: /* Незнакомые буквы опций игнорировать */115 continue;116 }117 argc--;118 }Строки 63–118 разбирают опции командной строки. Обратите внимание на ручной разбор кода:
еще не была придумана. Переменнаяgetopt()устанавливается вstatreq, когда опция требует использования системного вызоваtrue.stat()Избежание ненужного вызова
для каждого файла дает большой выигрыш в производительности. Вызовstat()был чрезвычайно дорогим, поскольку он мог вызвать поиск расположения индекса на файле, дисковое чтение для получения индекса, а затем поиск на диске расположения содержимого каталога (для того, чтобы продолжить чтение элементов каталога).stat()В современных системах индексы находятся в группах, распределенных по всей файловой системе, вместо объединения их вместе в начале. Это дает заметный прирост производительности. Тем не менее, вызовы
до сих пор не бесплатны, вы должны использовать их лишь при необходимости, но не более.stat()119 if (fflg) { /* -f аннулирует -l, -s, -t, добавляя -a */120 aflg++;121 lflg = 0;122 sflg = 0;123 tflg = 0;124 statreq = 0;125 }126 if (lflg) { /* Открыть файл паролей или групп */127 t = "/etc/passwd";128 if (gflg)129 t = "/etc/group";130 pwdf = fopen(t, "r");131 }132 if (argc==0) { /* Если нет аргументов, использовать текущий */133 argc++;134 argv = &dotp - 1;135 }Строки 119–125 обрабатывают опцию
, выключая-f,-l,-sи-t. Строки 126–131 обрабатываютstatreq, устанавливая для файла чтение сведений о владельце или группе. Помните, что V7 показывает лишь одно из этих сведений, но не оба.-lЕсли аргументов больше не осталось, строки 132–135 устанавливают
таким образом, что он указывает на строку, представляющую текущий каталог. Назначение 'argv' действительно, хотя и необычно. 'argr = &dotp - 1' компенсирует '- 1' в строке 137. Это позволяет избежать в главной части программы специального случая для '++argv'.argc == 1136 for (i=0; i < argc; i++) { /* Получить сведения о каждом файле */137 if ((ер = gstat(*++argv, 1))==NULL)138 continue;139 ep->ln.namep = *argv;140 ep->lflags |= ISARG;141 }142 qsort(firstp, lastp - firstp, sizeof *lastp, compar);143 slastp = lastp;144 for (epp=firstp; epp<slastp; epp++) { /* Глав. код, см. текст */145 ер = *epp;146 if (ep->ltype=='d' && dflg==0 || fflg) {147 if (argc>1)148 printf("\n%s:\n", ep->ln.namep);149 lastp = slastp;150 readdir(ep->ln.namep);151 if (fflg==0)152 qsort(slastp, lastp - slastp, sizeof *lastp, compar);153 if (lflg || sflg)154 printf("total %D\n", tblocks);155 for (ep1=slastp; ep1<lastp; ep1++)156 pentry(*ep1);157 } else158 pentry(ep);159 }160 exit(0);161 } /* Конец main() */Строки 136–141 перебирают аргументы, собирая сведения о каждом. Второй аргумент
булевый:gstat(), если имя является аргументом командной строки, в противном случаеtrue. Строка 140 добавляет флагfalseк полюISARGдля каждого аргумента командной строки.lflags