Программа в листинге 15.1 использует системный вызов stat() для извлечения информации о файле, чье имя передано в командную строку. Если указан параметр командной строки — l, то программа задействует системный вызов lstat(), чтобы мы смогли извлечь информацию о символической ссылке, а не о файле, на который она указывает. Данная программа выводит все поля возвращаемой структуры stat. (Объяснение того, почему мы присваиваем полям st_size и st_blocks тип long long, см. в разделе 5.10.) Функция filePermStr(), примененная в этой программе, показана в листинге 15.4.
Приведу пример использования данной программы:
$ echo 'All operating systems provide services for programs they run' > apue
$ chmod g+s apue
$ cat apue
All operating systems provide services for programs they run
$ ./t_stat apue
File type: regular file
Device containing i-node: major=3 minor=11
I-node number: 234363
Mode: 102644 (rw-r — r-)
special bits set: set-GID
Number of (hard) links: 1
Ownership: UID=1000 GID=100
File size: 61 bytes
Optimal I/O block size: 4096 bytes
512B blocks allocated: 8
Last file access: Mon Jun 8 09:40:07 2011
Last file modification: Mon Jun 8 09:39:25 2011
Last status change: Mon Jun 8 09:39:51 2011
Листинг 15.1. Извлечение информации о файле из структуры stat и ее интерпретация
files/t_stat.c
#define _BSD_SOURCE /* Берем major() и minor() из файла
#include
#include
#include
#include "file_perms.h"
#include "tlpi_hdr.h"
static void
displayStatInfo(const struct stat *sb)
{
printf("File type: ");
switch (sb->st_mode & S_IFMT) {
case S_IFREG: printf("regular file\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFBLK: printf("block device\n"); break;
case S_IFLNK: printf("symbolic (soft) link\n"); break;
case S_IFIFO: printf("FIFO or pipe\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown file type?\n"); break;
}
printf("Device containing i-node: major=%ld minor=%ld\n",
(long) major(sb->st_dev), (long) minor(sb->st_dev));
printf("I-node number: %ld\n", (long) sb->st_ino);
printf("Mode: %lo (%s)\n",
(unsigned long) sb->st_mode, filePermStr(sb->st_mode, 0));
if (sb->st_mode & (S_ISUID | S_ISGID | S_ISVTX))
printf(" special bits set: %s%s%s\n",
(sb->st_mode & S_ISUID)? "set-UID": "",
(sb->st_mode & S_ISGID)? "set-GID": "",
(sb->st_mode & S_ISVTX)? "sticky": "");
printf("Number of (hard) links: %ld\n", (long) sb->st_nlink);
printf("Ownership: UID=%ld GID=%ld\n",
(long) sb->st_uid, (long) sb->st_gid);
if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode))
printf("Device number (st_rdev): major=%ld; minor=%ld\n",
(long) major(sb->st_rdev), (long) minor(sb->st_rdev));
printf("File size: %lld bytes\n", (long long) sb->st_size);
printf("Optimal I/O block size: %ld bytes\n", (long) sb->st_blksize);
printf("512B blocks allocated: %lld\n", (long long) sb->st_blocks);
printf("Last file access: %s", ctime(&sb->st_atime));
printf("Last file modification: %s", ctime(&sb->st_mtime));
printf("Last status change: %s", ctime(&sb->st_ctime));
}
int
main(int argc, char *argv[])
{
struct stat sb;
Boolean statLink; /* Истина, если указано "-l" (то есть использовать lstat) */
int fname; /* Место аргумента filename в массиве argv[] */
statLink = (argc > 1) && strcmp(argv[1], "-l") == 0;
/* Простой синтаксический анализ для "-l" */
fname = statLink? 2: 1;
if (fname >= argc || (argc > 1 && strcmp(argv[1], " — help") == 0))
usageErr("%s [-l] file\n"
" — l = use lstat() instead of stat()\n", argv[0]);
if (statLink) {
if (lstat(argv[fname], &sb) == -1)
errExit("lstat");
} else {
if (stat(argv[fname], &sb) == -1)
errExit("stat");
}
displayStatInfo(&sb);
exit(EXIT_SUCCESS);
}
files/t_stat.c
Поля st_atime, st_mtime и st_ctime структуры stat содержат файловые метки времени. В эти поля записывается соответственно время последнего доступа к файлу, время последнего изменения файла и время последнего изменения статуса файла (то есть последнего изменения информации в файловом дескрипторе). Метки времени выражаются в секундах, прошедших с начала «эры UNIX» (1 января 1970 года; см. раздел 10.1).
Большинство нативных файловых систем Linux и UNIX поддерживают все поля меток времени, однако некоторые не-UNIX системы могут этого не делать.