Функция
gstat()
добавляет каждую новую
struct lbuf
к глобальному массиву
flist
(строка 137). Она также обновляет глобальный указатель
lastp
, чтобы он указывал в этом массиве на текущий последний элемент.
Строки 142–143 сортируют массив, используя
qsort()
, и сохраняют текущее значение
lastp
в
slastp
. Строки 144–159 перебирают в цикле каждый элемент массива, выводя соответствующим образом сведения о файле или каталоге.
Код для каталогов заслуживает дальнейшего объяснения:
if (ep->ltype=='d' && dflg==0 || fflg) ...
Строка 146. Если файл является каталогом и
-d
не предусмотрено или было установлено
-f
,
ls
должна прочесть каталог вместо того, чтобы выводить сведения о самом каталоге.
if (argc>1) printf ("\n%s:\n", ep->ln.namep)
Строки 147–148. Выводят имя каталога и двоеточие, если в командной строке было указано несколько файлов.
lastp = slastp;
readdir(ep->ln.namep)
Строки 149–150. Восстанавливают
lastp
из
slastp
. Массив
flist
действует как двухуровневый стек имен файлов. Аргументы командной строки хранятся с
firstp
до
slastp - 1
. Когда
readdir()
читает каталог, она помещает структуры
struct lbuf
для содержимого каталога в стек, начиная с
slastp
и до
lastp
. Это показано на рис. 7.1.
Рис. 7.1. Массив
flist
как двухуровневый стек
if (fflg==0) qsort(slastp, lastp - slastp, sizeof *lastp, compar)
Строки 151–152. Сортируют элементы подкаталога, если не действует
-f
.
if (lflg || sflg) printf("total %D\n", tblocks)
Строки 153–154. Выводят для
-l
или
-s
общее число блоков, используемых файлами в каталоге. Эта сумма хранится в переменной
tblocks
, которая сбрасывается для каждого каталога. На современных системах форматирующая строка
%D
для
printf()
эквивалентна
%ld
; она означает «вывести длинное целое». (В V7 есть также
%ld
, см. строку 192.)
for (ep1=slastp; ep1<lastp; ep1++) pentry(*ep1)
Строки 155–156. Выводит сведения о каждом файле в подкаталоге. Обратите внимание, что V7
ls
спускается лишь на один уровень в дереве каталогов. У нее отсутствует современная «рекурсивная» опция
-R
.
163 pentry(ap) /* void pentry(struct lbuf *ap) */
164 struct lbuf *ap;
165 {
166 struct { char dminor, dmajor;}; /* He использующийся исторический артефакт из V6 ls */
167 register t;
168 register struct lbuf *p;
169 register char *cp;
170
171 p = ap;
172 if (p->lnum == -1)
173 return;
174 if (iflg)
175 printf("%5u ", p->lnum); /* Номер индекса */
176 if (sflg)
177 printf("%4D nblock(p->lsize)); /* Размер в блоках */
Процедура
pentry()
выводит сведения о файле. Строки 172–173 проверяют, установлен ли -1 в поле
lnum
, и если так, функция возвращается. Когда верно '
p->lnum == -1
', структура
struct lbuf
недействительна. В противном случае это поле содержит номер индекса файла.
Строки 174–175 выводят номер индекса, если действует
-i
. Строки 176–177 выводят общее число блоков, если действует
-s
. (Как мы увидим ниже, это число может быть неточным.)
178 if (lflg) { /* Расширенный листинг: */
179 putchar(p->ltype); /* - Тип файла */
180 pmode(p->lflags); /* - Права доступа */
181 printf("%2d ", p->lnl); /* - Число ссылок */
182 t = p->luid;
183 if (gflg)
184 t = p->lgid;
185 if (getname(t, tbuf)==0)
186 printf("%-6.6s", tbuf); /* - Владелец или группа */
187 else
188 printf("%-6d", t);
189 if (p->ltype=='b' || p->ltype=='c') /* - Устройство: старший и младший номера */
190 printf("%3d,%3d", major((int)p->lsize), minor((int)p->lsize));
191 else
192 printf("%71d", p->lsize); /* - Размер в байтах */
193 cp = ctime(&p->lmtime);
194 if (p->lmtime < year) /* - Время изменения */
195 printf(" %-7.7s %-4.4s ", cp+4, cp+20); else
196 printf(" %-12.12s ", cp+4);
197 }
198 if (p->lflags & ISARG) /* - Имя файла */
199 printf("%s\n", p->ln.namep);
200 else
201 printf("%.14s\n", p->ln.lname);
202 }