1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 500
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/statvfs.h>
#include <math.h>
#include <limits.h>
static unsigned long g_output_block_size = 512;
typedef struct
{
char name[PATH_MAX + 1];
char mount[PATH_MAX + 1];
} t_fs_info;
static t_fs_info g_fs_info_dummy = { .name = "", .mount = "" };
static t_fs_info *g_fs_infos = NULL;
static size_t g_fs_infos_size = 0;
void put_file_fs_info(char *file_relpath, bool allow_empty)
{
char file_path[PATH_MAX + 1] = {'\0'};
realpath(file_relpath, file_path);
struct statvfs statvfsbuf;
if (statvfs(file_path, &statvfsbuf) == -1)
exit(1);
long block_size = statvfsbuf.f_bsize;
unsigned long total = statvfsbuf.f_blocks * statvfsbuf.f_frsize / g_output_block_size;
long used = total - statvfsbuf.f_bfree * block_size / g_output_block_size;
long available = statvfsbuf.f_bavail * block_size / g_output_block_size;
bool empty_fs = used + available == 0;
if (empty_fs && !allow_empty)
return;
t_fs_info *fs_info = &g_fs_info_dummy;
for (size_t i = 0; i < g_fs_infos_size; i++)
{
char *mount = g_fs_infos[i].mount;
size_t mount_len = strlen(mount);
if (strncmp(file_path, mount, mount_len) == 0 && mount_len > strlen(fs_info->mount))
fs_info = &g_fs_infos[i];
}
printf("%-15s", fs_info->name);
printf("%11ld", total);
printf("%9ld", used);
printf("%10ld", available);
if (!empty_fs)
printf("%8.0f%%", ceil(((double)used / (double)(used + available)) * 100));
else
printf("%9c", '-');
printf(" %s", fs_info->mount);
fputc('\n', stdout);
}
int main(int argc, char **argv)
{
int option;
while ((option = getopt(argc, argv, "kPt")) != -1)
{
switch (option)
{
case 'k':
g_output_block_size = 1024;
break;
case 'P':
case 't':
break;
}
}
FILE *mounts_file = fopen("/etc/mtab", "r");
if (mounts_file == NULL)
exit(1);
while (!feof(mounts_file))
{
g_fs_infos_size++;
g_fs_infos = realloc(g_fs_infos, sizeof(t_fs_info) * g_fs_infos_size);
if (g_fs_infos == NULL)
{
fclose(mounts_file);
exit(1);
}
t_fs_info *last = &g_fs_infos[g_fs_infos_size - 1];
fscanf(mounts_file, "%s %s", last->name, last->mount);
int c;
do
c = fgetc(mounts_file);
while (c != '\n' && c != EOF);
}
fclose(mounts_file);
g_fs_infos_size--;
printf("Filesystem %4lu-blocks Used Available Capacity Mounted on\n", g_output_block_size);
if (optind == argc)
{
for (size_t i = 0; i < g_fs_infos_size; i++)
put_file_fs_info(g_fs_infos[i].mount, false);
return 0;
}
for (; optind < argc; optind++)
put_file_fs_info(argv[optind], true);
free(g_fs_infos);
return 0;
}
|