• Строки 385–388. заполняются поля lflags, luid, lgid и lnl из соответствующих полей в struct stat. Строка 385 удаляет биты типа файла, оставляя 12 битов прав доступа (на чтение/запись/исполнение для владельца/группы/остальных, а также setuid, setgid и save-text).

• Строки 389–394: основываясь на опциях командной строки, используют одно из трех полей времени в struct stat для поля lmtime в struct lbuf.

• Строка 395: обновляет глобальную переменную tblocks числом блоков в файле.

400 compar(pp1, pp2) /* int compar(struct lbuf **pp1, */

401 struct lbuf **pp1, **pp2; /* struct lbuf **pp2) */

402 {

403  register struct lbuf *p1, *p2;

404

405  p1 = *pp1;

406  p2 = *pp2;

407  if (dflg==0) {

408   if (p1->lflags&ISARG && p1->ltype=='d') {

409    if (!(p2->lflags&ISARG && p2->ltype=='d'))

410     return(1);

411   } else {

412    if (p2->lflags&ISARG && p2->ltype=='d')

413     return(-1);

414   }

415  }

416  if (tflg) {

417   if(p2->lmtime == p1->lmtime)

418    return(0);

419   if (p2->lmtime > p1->lmtime)

420    return(rflg);

421   return(-rflg);

422  }

423  return(rflg * strcmp(p1->lflags&ISARG ? p1->ln.namep : p1->ln.lname,

424   p2->lflags&ISARG ? p2->ln.namep : p2->ln.lname));

425 }

Функция compar() сжата: в небольшом пространстве происходит многое. Первая вещь, которую следует запомнить, это смысл возвращаемого значения: отрицательное значение означает, что первый файл должен идти перед вторым, ноль означает, что файлы равны, а положительное значение означает, что второй файл должен идти перед первым

Следующая вещь, которую нужно понять, это то, что ls выводит содержимое каталогов после выведения сведений о файлах. Поэтому результат сортировки должен быть таким, чтобы все каталоги, указанные в командной строке, следовали за всеми файлами, указанными там же

Наконец, переменная rflg помогает реализовать опцию -r, которая меняет порядок сортировки. Она инициализируется 1 (строка 30). Если -r используется, rflg устанавливается в -1 (строки 89–91).

Следующий псевдокод описывает логику compar(); номера строк на левой границе соответствуют номерам строк ls.c:

407 if ls должна прочесть каталоги # dflg == 0

408  if p1 аргумент командной строки и p1 каталог

409   if p2 не аргумент командной строки и не каталог

410    return 1 # первый идет после второго

      else

       перейти на тест времени

411  else

      # p1 не каталог командной строки

412   if p2 аргумент командной строки и каталог

413    return -1 # первый идет перед вторым

      else

       перейти на тест времени

416 if сортировка основана на времени # tflg равно true

     # сравнить времена:

417  if время p2 равно времени p1

418   return 0

419  if время p2 > времени p1

420   return значение rflg (положительное или отрицательное)

     # время p2 < времени p1

421  return противоположное rflg значение (положительное или отрицательное)

423 Умножить rflg на результат strcmp()

424 для двух имен и вернуть результат

Аргументы strcmp() в строках 423–424 выглядят сбивающими с толку. В зависимости от того, было ли имя файла указано в командной строке или было прочитано из каталога, должны использоваться различные члены объединения ln в struct lbuf.

<p>7.3. Резюме</p>

• V7 ls является сравнительно небольшой программой, хотя она затрагивает многие фундаментальные аспекты программирования Unix — файловый ввод-вывод, вспомогательные данные файлов, содержание каталогов, пользователи и группы, значения времени и даты, сортировку и динамическое управление памятью.

Перейти на страницу:

Похожие книги