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

56   do_statvfs(fs);

57

58  endmntent(fp);

59 }

Строки 1–59 в сущности те же самые, как и для

ch08-mounted.c
.
main()
обрабатывает командную стоку, a
process()
просматривает в цикле каждую смонтированную файловую систему.
do_statvfs()
осуществляет действительную работу, выводя для каждой интересующей файловой системы
struct statvfs
.

61  /* do_statvfs --- Использовать statvfs и вывести сведения */

62

63  void do_statvfs(const struct mntent *fs)

64  {

65   struct statvfs vfs;

66

67   if (fs->mnt_fsname[0] != '/') /* пропустить ненастоящие файловые системы */

68    return;

69

70   if (statvfs(fs->mnt_dir, &vfs) != 0) {

71    fprintf(stderr, "%s: %s: statvfs failed: %s\n",

72     myname, fs->mnt_dir, strerror(errno));

73    errors++;

74    return;

75   }

76

77   printf("%s, mounted on %s:\n", fs->mnt_dir, fs->mnt_fsname);

78   printf("\tf_bsize: %ld\n", (long)vfs.f_bsize);

79   printf("\tf_frsize: %ld\n", (long)vfs.f_frsize);

80   printf("\tf_blocks: %lu\n", (unsigned long)vfs.f_blocks);

81   printf("\tf_bfree: %lu\n", (unsigned long)vfs.f_bfree);

82   printf("\tf_bavail: %lu\n", (unsigned long)vfs.f_bavail);

83   printf("\tf_files: %lu\n", (unsigned long)vfs.f_files);

84   printf("\tf_ffree: %lu\n", (unsigned long)vfs.f_ffree);

85   printf("\tf_favail: %lu\n", (unsigned long)vfs.f_favail);

86   printf("\tf_fsid: %#lx\n", (unsigned long)vfs.f_fsid);

87

88   printf("\tf_flag: ");

89   if (vfs.f_flag == 0)

90    printf("(none)\n");

91   else {

92    if ((vfs.f_flag & ST_RDONLY) != 0)

93     printf("ST_RDONLY ");

94    if ((vfs.f_flag & ST_NOSUID) != 0)

95     printf("ST_NOSUID");

96    printf("\n");

97   }

98

99   printf("\tf_namemax: %#ld\n", (long)vfs.f_namemax);

100 }

Строки 67–68 пропускают файловые системы, которые не основываются на реальных дисковых устройствах. Это означает, что файловые системы типа

/proc
или
/dev/pts
игнорируются. (Правда, эта проверка эвристическая, но она работает: в
/etc/mtab
смонтированные устройства перечислены по полному пути устройства: например,
/dev/hda1
.) Строка 70 вызывает
statvfs()
с соответствующей проверкой ошибок, а строки 77-99 выводят сведения.

Строки 89–96 имеют дело с флагами: отдельные биты информации, которые присутствуют или не присутствуют. Обсуждение того, как биты флагов используются в коде С, см. во врезке. Вот вывод

ch08-statvfs
:

$ <b>ch08-statvfs</b> /* Запуск программы */

/, mounted on /dev/hda2: /* Результаты для файловой системы ext2 */

f_bsize: 4096

f_frsize: 4096

f_blocks: 1549609

f_bfree: 316663

f_bavail: 237945

f_files: 788704

f_ffree: 555482

f_favail: 555482

f_fsid: 0

f_flag: (none)

f_namemax: 255

...

/win, mounted on /dev/hda1: /* Результаты для файл. системы vfat */

f_bsize: 4096

f_frsize: 4096

f_blocks: 2092383

f_bfree: 1391952

f_bavail: 1391952

f_files: 0

f_ffree: 0

f_favail: 0

f_fsid: 0

f_flag: ST_NOSUID

f_namemax: 260

Во время написания этого, для GLIBC 2.3.2 и ранее, GNU

df
не использует
statvfs()
. Это потому, что код читает
/etc/mtab
и вызывает
stat()
для каждой смонтированной файловой системы, чтобы найти ту, номер устройства которой совпадает с соответствующим аргументом для файла (или дескриптора файла). Для того, чтобы прочесть опции монтирования, коду нужно найти файловую систему, поэтому он может установить биты
f_flag
. Проблема в том, что
stat()
на смонтированной удаленной файловой системе, сервер которой недоступен, может висеть неопределенно долго, вызвав также зависание
df
. С тех пор эта проблема в GLIBC была исправлена, но
df
не будет изменяться в течение некоторого времени, так что она сможет продолжать работать на более старых системах.

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