Выбрать главу

23  while ((c = getopt(argc, argv, "f:")) != -1) {

24   switch (c) {

25   case 'f':

26    file = optarg;

27    break;

28   default:

29    fprintf(stderr, "usage: %s [-f fstab-file]\n", argv[0]);

30    exit(1);

31   }

32  }

33

34  process(file);

35  return 0;

36 }

37

38 /* process --- прочесть структуры struct mntent из файла */

39

40 void process(const char *filename)

41 {

42  FILE *fp;

43  struct mntent *fs;

44

45  fp = setmntent(filename, "r"); /* только для чтения */

46  if (fp == NULL) {

47   fprintf(stderr, "%s: %s: could not open: %s\n",

48    myname, filename, strerror(errno));

49   exit(1);

50  }

51

52  while ((fs = getmntent(fp)) != NULL)

53   print_mount(fs);

54

55  endmntent(fp);

56 }

57

58 /* print_mount --- вывод одного смонтированного элемента */

59

60 void print_mount(const struct mntent *fs)

61 {

62  printf("%s %s %s %s %d %d\n",

63   fs->mnt_fsname,

64   fs->mnt_dir,

65   fs->mnt_type,

66   fs->mnt_opts,

67   fs->mnt_freq,

68   fs->mnt_passno);

69 }

В отличие от большинства программ, которые мы до сих пор видели, эта специфична для Linux. Во многих Unix-системах есть схожие процедуры, но их идентичность не гарантируется.

По умолчанию, ch08-mounted читает /etc/mtab, выводя сведения о каждой смонтированной файловой системе. Опция -f позволяет указать другой файл для чтения, такой, как /proc/mounts или даже /etc/fstab.

Функция main() обрабатывает командную строку (строки 23–32) и вызывает для указанного файла process(). (Эта программа следует нашему стандартному шаблону.)

process(), в свою очередь, открывает файл (строка 45) и проходит в цикле через каждую возвращённую файловую систему (строки 52–53). После завершения она закрывает файл (строка 55).

Функция print_mount() выводит информацию из struct mnent. Вывод во многом напоминает вывод 'cat /etc/mtab':

$ ch08-mounted /* Запуск программы */

/dev/hda2 / ext3 rw 0 0

none /proc proc rw 0 0

usbdevfs /proc/bus/usb usbdevfs rw 0 0

/dev/hda5 /d ext3 rw 0 0

none /dev/pts devpts rw,gid=5,mode=620 0 0

none /dev/shm tmpfs rw 0 0

none /proc/sys/fs/binfmt_misc binfmt_misc rw 0 0

/dev/hda1 /win vfat rw,noexec,nosuid,nodev,uid=2076,gid=10,user=arnold 0 0

8.3. Получение сведений о файловой системе

Вывод сведений о файловой системе, рассмотренный ранее — это хорошо и замечательно, но это не захватывает. Раз мы знаем, что определенная точка монтирования представляет файловую систему, нам нужны сведения о файловой системе. Это даст нам возможность выводить вещи наподобие сведений, полученных с помощью df и 'df -i'.

$ df /* Показать свободное/используемое пространство */

Filesystem 1K-blocks Used Available Use% Mounted on

/dev/hda2 6198436 4940316 943248 84% /

/dev/hda5 61431520 27618536 30692360 48% /d

none 256616 0 256616 0% /dev/shm

/dev/hda1 8369532 2784700 5584832 34% /win

$ df -i /* Показать свободные/используемые индексы */

Filesystem Inodes IUsed IFree IUse% Mounted on

/dev/hda2 788704 233216 555488 30% /

/dev/hda5 7815168 503243 7311925 7% /d

none 64154 1 64153 1% /dev/shm

/dev/hda1 0 0 0 - /win

8.3.1. Стиль POSIX: statvfs() и fstatvfs()

На ранних системах Unix была только одна разновидность файловой системы. Для них было достаточно, если df считывала суперблок каждой смонтированной файловой системы, извлекала значимые сведения и красиво форматировала их для отображения. (Суперблок обычно был вторым блоком в файловой системе; первым был загрузочный блок, содержащий загрузочный код).

Однако в современном мире такой подход был бы непригодным. POSIX предоставляет расширение XSI для получения доступа к этой информации. Главная функция называется statvfs() («vfs» часть происходит от лежащей в основе технологии SunOS, использованной позже в System V Release 4, которая называется виртуальной файловой системой.) Имеется две функции:

#include <sys/types.h> /* XSI */

#include <sys/statvfs.h>

int statvfs(const char *path, struct statvfs *buf);

int fstatvfs(int fd, struct statvfs *buf);

statvfs() использует для любого файла имя пути; она возвращает сведения о файловой системе, содержащей файл. fstatvfs() принимает в качестве первою аргумента дескриптор открытого файла, здесь также возвращается информация о файловой системе, содержащей открытый файл, struct statvfs содержит следующие члены:

struct statvfs {

 unsigned long int f_bsize;   /* Размер блока */

 unsigned long int f_frsize;

  /* Размер фрагмента («основной размер блока») */

 fsblkcnt_t f_blocks;         /* Общее число блоков */

 fsblkcnt_t f_bfree;          /* Общее число свободных блоков */

 fsblkcnt_t f_bavail;         /* Число доступных блоков (≤f_bfree) */

 fsfilcnt_t f_files;          /* Общее число индексов */

 fsfilcnt_t f_ffree;          /* Общее число свободных индексов */

 fsfilcnt_t f_favail;         /* Число доступных индексов (≤f_files) */

 unsigned long int f_fsid;    /* ID файловой системы */

 unsigned long int f_flag;    /* Флаги: ST_RDONLY и/или ST_NOSUID */

 unsigned long int f_namemax; /* Максимальная длина имени файла */

};

Сведений, которые в ней содержатся, достаточно для написания df:

unsigned long int f_bsize

Размер блока является предпочтительным размером для осуществления ввода/вывода. Файловая система пытается хранить по крайней мере f_bsize байтов стоящих данных в смежных секторах на диске. (Сектор является наименьшим количеством адресуемых данных на диске. Обычно дисковый сектор равен 512 байтам.)