Initial revision
[monky] / fs.c
1 #include "conky.h"
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <sys/types.h>
7 #include <fcntl.h>
8
9 /* linux */
10 #ifdef HAVE_SYS_STATFS_H
11 #include <sys/statfs.h>
12 #endif
13
14 /* freebsd && netbsd */
15 #ifdef HAVE_SYS_PARAM_H
16 #include <sys/param.h>
17 #endif
18 #ifdef HAVE_SYS_MOUNT_H
19 #include <sys/mount.h>
20 #endif
21
22 /* TODO: benchmark which is faster, fstatvfs() or pre-opened fd and
23  * statvfs() (fstatvfs() would handle mounts I think...) */
24
25 static struct fs_stat fs_stats_[64];
26 struct fs_stat *fs_stats = fs_stats_;
27
28 void update_fs_stats()
29 {
30         unsigned int i;
31         struct statfs s;
32         for (i = 0; i < 16; i++) {
33                 if (fs_stats[i].fd <= 0)
34                         break;
35
36                 fstatfs(fs_stats[i].fd, &s);
37
38                 fs_stats[i].size = (long long) s.f_blocks * s.f_bsize;
39                 /* bfree (root) or bavail (non-roots) ? */
40                 fs_stats[i].avail = (long long) s.f_bavail * s.f_bsize;
41         }
42 }
43
44 void clear_fs_stats()
45 {
46         unsigned int i;
47         for (i = 0; i < 16; i++) {
48                 if (fs_stats[i].fd) {
49                         close(fs_stats[i].fd);
50                         fs_stats[i].fd = -1;
51                 }
52
53                 if (fs_stats[i].path != NULL) {
54                         free(fs_stats[i].path);
55                         fs_stats[i].path = NULL;
56                 }
57         }
58 }
59
60 struct fs_stat *prepare_fs_stat(const char *s)
61 {
62         unsigned int i;
63
64         for (i = 0; i < 16; i++) {
65                 struct fs_stat *fs = &fs_stats[i];
66
67                 if (fs->path && strcmp(fs->path, s) == 0)
68                         return fs;
69
70                 if (fs->fd <= 0) {
71                         /* when compiled with icc, it crashes when leaving function and open()
72                          * is used, I don't know why */
73
74                         /* this icc workaround didn't seem to work */
75 #if 0
76                         {
77                                 FILE *fp = fopen(s, "r");
78                                 if (fp)
79                                         fs->fd = fileno(fp);
80                                 else
81                                         fs->fd = -1;
82                         }
83 #endif
84
85                         fs->fd = open(s, O_RDONLY);
86
87                         if (fs->fd <= 0) {      /* 0 isn't error but actually it is :) */
88                                 ERR("open '%s': %s", s, strerror(errno));
89                                 return 0;
90                         }
91
92                         fs->path = strdup(s);
93                         update_fs_stats();
94                         return fs;
95                 }
96         }
97
98         ERR("too many fs stats");
99         return 0;
100 }