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