mpd password
[monky] / 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
61                 if (fs_stats[i].path != NULL) {
62                         free(fs_stats[i].path);
63                         fs_stats[i].path = NULL;
64                 }
65         }
66 }
67
68 struct fs_stat *prepare_fs_stat(const char *s)
69 {
70         unsigned int i;
71
72         for (i = 0; i < 16; i++) {
73                 struct fs_stat *fs = &fs_stats[i];
74
75                 if (fs->path && strcmp(fs->path, s) == 0)
76                         return fs;
77
78                 if (fs->fd <= 0) {
79                         /* when compiled with icc, it crashes when leaving function and open()
80                          * is used, I don't know why */
81
82                         /* this icc workaround didn't seem to work */
83 #if 0
84                         {
85                                 FILE *fp = fopen(s, "r");
86                                 if (fp)
87                                         fs->fd = fileno(fp);
88                                 else
89                                         fs->fd = -1;
90                         }
91 #endif
92
93                         fs->fd = open(s, O_RDONLY);
94
95                         if (fs->fd <= 0) {      /* 0 isn't error but actually it is :) */
96                                 ERR("open '%s': %s", s, strerror(errno));
97                                 return 0;
98                         }
99
100                         fs->path = strdup(s);
101                         update_fs_stats();
102                         return fs;
103                 }
104         }
105
106         ERR("too many fs stats");
107         return 0;
108 }