333 register struct lbuf *rep;
334 static int nomocore;
335
336 if (nomocore) /* Ранее была нехватка памяти */
337 return(NULL);
338 rep = (struct lbuf*)malloc(sizeof(struct lbuf));
339 if (rep==NULL) {
340 fprintf(stderr, "ls: out of memory\n");
341 nomocore = 1;
342 return(NULL);
343 }
344 if (lastp >= &flist[NFILES]) { /* Проверить, не дано ли слишком много файлов */
345 static int msg;
346 lastp--;
347 if (msg==0) {
348 fprintf(stderr, "ls: too many files\n");
349 msg++;
350 }
351 }
352 *lastp++ = rep; /* Заполнить сведения */
353 rep->lflags = 0;
354 rep->lnum = 0;
355 rep->ltype = '-'; /* Тип файла по умолчанию */
Статическая переменная nomocore
[важно] указывает, что malloc()
при предыдущем вызове завершилась неудачей. Поскольку она статическая, она автоматически инициализируется 0 (т.е. false
). Если на входе она равна true
, gstat()
просто возвращает NULL
. В противном случае, если malloc()
завершается неудачей, ls
выводит сообщение об ошибке, устанавливает в nomocore
true
и возвращает NULL
(строки 334–343).
Строки 344–351 гарантируют, что в массиве flist
все еще остается место. Если нет, ls
выдает сообщение (но лишь однажды; заметьте использование статической переменной msg
), а затем повторно использует последний слот flist
.
Строка 352 заставляет слот lastp
указывать на новую struct lbuf
(rep
). Это также обновляет lastp
, который используется для сортировки в main()
(строки 142 и 152). Строки 353–355 устанавливают значения по умолчанию для полей флагов, номеров индексов и типов в struct lbuf
.
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
.