Литмир - Электронная Библиотека
A
A

356  if (argfl || statreq) {

357   if (stat(file, &statb)<0) { /* stat() завершилась неудачей */

358    printf("%s not found\n", file);

359    statb.st_ino = -1;

360    statb.st_size = 0;

361    statb.st_mode = 0;

362    if (argfl) {

363     lastp--;

364     return(0);

365    }

366   }

367   rep->lnum = statb.st_ino; /* stat() OK, копировать сведения */

368   rep->lsize = statb.st_size;

369   switch(statb.st_mode & S_IFMT) {

370

371   case S_IFDIR:

372    rep->ltype = 'd';

373    break;

374

375   case S_IFBLK:

376    rep->ltype = 'b';

377    rep->lsize = statb.st_rdev;

378    break;

379

380   case S_IFCHR:

381    rep->ltype = 'c';

382    rep->lsize = statb.st_rdfev;

383    break;

384   }

385   rep->lflags = statb.st_mode & ~S_IFMT;

386   rep->luid = statb.st_uid;

387   rep->lgid = statb.st_gid;

388   rep->lnl = statb.st_nlink;

389   if (uflg)

390    rep->lmtime = statb.st_atime;

391   else if (cflg)

392    rep->lmtime = statb.st_ctime;

393   else

394    rep->lmtime = statb.st_mtime;

395   tblocks += nblock(statb.st_size);

396  }

397  return(rep);

398 }

Строки 356–396 обрабатывают вызов

stat()
. Если это аргумент командной строки или если
statreq
установлен в
true
благодаря опции, код заполняет
struct lbuf
следующим образом:

• Строки 357–366: вызывают

stat()
, при ее неудаче выводится сообщение об ошибке с установкой соответствующих значений, затем возвращается
NULL
(выраженный в виде 0).

• Строки 367–368: устанавливают в struct stat поля номера индекса и размера, если вызов

stat()
был успешным.

• Строки 369–384: обрабатывают особые случаи каталогов, блочных и символьных устройств. Во всех случаях код обновляет поле

ltype
. Для устройств значение
lsize
замещается значением
st_rdev
.

• Строки 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
выводит содержимое каталогов после выведения сведений о файлах. Поэтому результат сортировки должен быть таким, чтобы все каталоги, указанные в командной строке, следовали за всеми файлами, указанными там же

87
{"b":"576259","o":1}