, , , , , .
: info.c:
#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/statvfs.h>
#include <mntent.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
static void free_array(char **array)
{
if (array) {
size_t i;
for (i = 0; array[i] != NULL; i++) {
free(array[i]);
array[i] = NULL;
}
free(array);
}
}
static char **normal_mounts(void)
{
char **list = NULL, **temp;
size_t size = 0;
size_t used = 0;
char buffer[4096];
struct mntent entry;
FILE *mounts;
mounts = fopen("/proc/mounts", "r");
if (!mounts)
return NULL;
while (getmntent_r(mounts, &entry, buffer, sizeof buffer) == &entry)
if (strcmp(entry.mnt_fsname, "tmpfs") &&
strcmp(entry.mnt_fsname, "swap") &&
strcmp(entry.mnt_dir, "/proc") && strncmp(entry.mnt_dir, "/proc/", 6) &&
strcmp(entry.mnt_dir, "/boot") && strncmp(entry.mnt_dir, "/boot/", 6) &&
strcmp(entry.mnt_dir, "/sys") && strncmp(entry.mnt_dir, "/sys/", 5) &&
strcmp(entry.mnt_dir, "/run") && strncmp(entry.mnt_dir, "/run/", 5) &&
strcmp(entry.mnt_dir, "/dev") && strncmp(entry.mnt_dir, "/dev/", 5) &&
strcmp(entry.mnt_dir, "/mnt") && strncmp(entry.mnt_dir, "/mnt/", 5) &&
strcmp(entry.mnt_dir, "/media") && strncmp(entry.mnt_dir, "/media/", 7) &&
strcmp(entry.mnt_dir, "/var/run") && strncmp(entry.mnt_dir, "/var/run/", 9)) {
if (used >= size) {
size = (used | 15) + 17;
temp = realloc(list, size * sizeof list[0]);
if (!temp) {
endmntent(mounts);
free_array(list);
errno = ENOMEM;
return NULL;
}
list = temp;
}
if (!(list[used++] = strdup(entry.mnt_dir))) {
endmntent(mounts);
free_array(list);
errno = ENOMEM;
return NULL;
}
}
if (ferror(mounts) || !feof(mounts)) {
endmntent(mounts);
free_array(list);
errno = EIO;
return NULL;
} else
endmntent(mounts);
if (!used) {
free_array(list);
errno = 0;
return NULL;
}
if (size != used + 1) {
size = used + 1;
temp = realloc(list, size * sizeof list[0]);
if (!temp) {
free_array(list);
errno = ENOMEM;
return NULL;
}
list = temp;
}
list[used] = NULL;
errno = 0;
return list;
}
static int statistics(const char **mountpoint, uint64_t *bytes_total, uint64_t *bytes_free)
{
struct statvfs info;
uint64_t btotal = 0;
uint64_t bfree = 0;
size_t i;
if (!mountpoint)
return errno = EINVAL;
for (i = 0; mountpoint[i] != NULL; i++)
if (statvfs(mountpoint[i], &info) != -1) {
btotal += (uint64_t)info.f_frsize * (uint64_t)info.f_blocks;
bfree += (uint64_t)info.f_bsize * (uint64_t)info.f_bavail;
} else
return errno;
if (bytes_total)
*bytes_total = btotal;
if (bytes_free)
*bytes_free = bfree;
return 0;
}
int main(int argc, char *argv[])
{
uint64_t total = 0;
uint64_t nfree = 0;
if (argc > 1) {
if (statistics((const char **)argv + 1, &total, &nfree)) {
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
} else {
char **mounts = normal_mounts();
size_t i;
if (!mounts) {
if (errno)
fprintf(stderr, "Error determining file systems: %s.\n", strerror(errno));
else
fprintf(stderr, "No normal file systems found.\n");
return EXIT_FAILURE;
}
fprintf(stderr, "Considering mount points");
for (i = 0; mounts[i] != NULL; i++)
fprintf(stderr, " %s", mounts[i]);
fprintf(stderr, "\n");
if (statistics((const char **)mounts, &total, &nfree)) {
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
free_array(mounts);
}
printf("%20" PRIu64 " bytes total\n", total);
printf("%20" PRIu64 " bytes free\n", nfree);
return EXIT_SUCCESS;
}
statistics() NULL- 64- . 0 errno . .
, . (POSIX argv[argc] == NULL, .)
normal_mounts() /proc/mounts "" . getmntent() () , . tmpfs (ramdisks) swap , , /proc, /boot, /sys, /run, /dev, /mnt, /media, /var/run. , .
( ) statistics() . . : ( , /tmp /var/tmp tmpfs mounts), /home.
HUP USR1 USR2, , - . , DBUS /, , , , .
, ,
gcc -Wall -O2 info.c -o info
./info
-
Considering mount points / /home
119989497856 bytes total
26786156544 bytes free
, - . - , , -:
./info /home /tmp
, , : stat(path1, &info1) , stat(path2, &info2) - . (info1.st_dev == info2.st_dev), . ( , , , , , .)
, , df. C/POSIX ( , , ),
handle = popen("LANG=C LC_ALL=C df -Pl", "r");
, len = getline(&line, &size, handle).