-/*
- * Conky, a system monitor, based on torsmo
+/* Conky, a system monitor, based on torsmo
*
- * This program is licensed under BSD license, read COPYING
+ * Any original torsmo code is licensed under the BSD license
+ *
+ * All code written since the fork of torsmo is licensed under the GPL
+ *
+ * Please see COPYING for details
+ *
+ * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
+ * Copyright (c) 2005-2008 Brenden Matthews, Philip Kovacs, et. al.
+ * (see AUTHORS)
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * $Id$
*/
#include "conky.h"
+#include "logging.h"
+#include "fs.h"
#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mount.h>
#endif
-/* TODO: benchmark which is faster, fstatvfs() or pre-opened fd and
- * statvfs() (fstatvfs() would handle mounts I think...) */
+#if !defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && !defined (__OpenBSD__) && !defined(__FreeBSD__)
+#include <mntent.h>
+#endif
+
+#define MAX_FS_STATS 64
-static struct fs_stat fs_stats_[64];
+static struct fs_stat fs_stats_[MAX_FS_STATS];
struct fs_stat *fs_stats = fs_stats_;
-void update_fs_stats()
+static void update_fs_stat(struct fs_stat *fs);
+
+void get_fs_type(const char *path, char *result);
+
+void update_fs_stats(void)
{
- unsigned int i;
- struct statfs s;
- for (i = 0; i < 16; i++) {
- if (fs_stats[i].fd <= 0)
- break;
+ unsigned i;
- fstatfs(fs_stats[i].fd, &s);
+ for (i = 0; i < MAX_FS_STATS; ++i) {
+ if (fs_stats[i].set) {
+ update_fs_stat(&fs_stats[i]);
+ }
+ }
+}
- fs_stats[i].size = (long long) s.f_blocks * s.f_bsize;
- /* bfree (root) or bavail (non-roots) ? */
- fs_stats[i].avail = (long long) s.f_bavail * s.f_bsize;
+void clear_fs_stats(void)
+{
+ unsigned i;
+ for (i = 0; i < MAX_FS_STATS; ++i) {
+ memset(&fs_stats[i], 0, sizeof(struct fs_stat));
}
}
-void clear_fs_stats()
+struct fs_stat *prepare_fs_stat(const char *s)
{
- unsigned int i;
- for (i = 0; i < 16; i++) {
- if (fs_stats[i].fd) {
- close(fs_stats[i].fd);
- fs_stats[i].fd = -1;
- }
- if (fs_stats[i].path != NULL) {
- free(fs_stats[i].path);
- fs_stats[i].path = NULL;
+ struct fs_stat *new = 0;
+ unsigned i;
+
+ /* lookup existing or get new */
+ for (i = 0; i < MAX_FS_STATS; ++i) {
+ if (fs_stats[i].set) {
+ if (strncmp(fs_stats[i].path, s, DEFAULT_TEXT_BUFFER_SIZE) == 0) {
+ return &fs_stats[i];
+ }
+ } else {
+ new = &fs_stats[i];
}
}
+ /* new path */
+ if (!new) {
+ ERR("too many fs stats");
+ return 0;
+ }
+ strncpy(new->path, s, DEFAULT_TEXT_BUFFER_SIZE);
+ new->set = 1;
+ update_fs_stat(new);
+ return new;
}
-/*void clear_fs_stat(unsigned int i)
+static void update_fs_stat(struct fs_stat *fs)
{
- if (fs_stats[i].fd) {
- close(fs_stats[i].fd);
- fs_stats[i].fd = -1;
+ struct statfs s;
+
+ if (statfs(fs->path, &s) == 0) {
+ fs->size = (long long)s.f_blocks * s.f_bsize;
+ /* bfree (root) or bavail (non-roots) ? */
+ fs->avail = (long long)s.f_bavail * s.f_bsize;
+ fs->free = (long long)s.f_bfree * s.f_bsize;
+ get_fs_type(fs->path, fs->type);
+ } else {
+ fs->size = 0;
+ fs->avail = 0;
+ fs->free = 0;
+ strncpy(fs->type, "unknown", DEFAULT_TEXT_BUFFER_SIZE);
+ ERR("statfs '%s': %s", fs->path, strerror(errno));
}
- if (fs_stats[i].path != NULL) {
- free(fs_stats[i].path);
- fs_stats[i].path = NULL;
+}
+
+void get_fs_type(const char *path, char *result)
+{
+
+#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || defined(__FreeBSD__) || defined (__OpenBSD__)
+
+ struct statfs s;
+ if (statfs(path, &s) == 0) {
+ strncpy(result, s.f_fstypename, DEFAULT_TEXT_BUFFER_SIZE);
+ } else {
+ ERR("statfs '%s': %s", path, strerror(errno));
}
-}*/
+ return;
+#else /* HAVE_STRUCT_STATFS_F_FSTYPENAME */
-struct fs_stat *prepare_fs_stat(const char *s)
-{
- unsigned int i;
-
- for (i = 0; i < 16; i++) {
- struct fs_stat *fs = &fs_stats[i];
-
- if (fs->path && strcmp(fs->path, s) == 0)
- return fs;
-
- if (fs->fd <= 0) {
- /* when compiled with icc, it crashes when leaving function and open()
- * is used, I don't know why
- * fuck icc */
-
- /* this icc workaround didn't seem to work */
-#if 0
- {
- FILE *fp = fopen(s, "r");
- if (fp)
- fs->fd = fileno(fp);
- else
- fs->fd = -1;
- }
-#endif
+ struct mntent *me;
+ FILE *mtab = setmntent("/etc/mtab", "r");
+ char *search_path;
+ int match;
+ char *slash;
- fs->fd = open(s, O_RDONLY);
+ if (mtab == NULL) {
+ ERR("setmntent /etc/mtab: %s", strerror(errno));
+ strncpy(result, "unknown", DEFAULT_TEXT_BUFFER_SIZE);
+ return;
+ }
- if (fs->fd <= 0) { /* 0 isn't error but actually it is :) */
- ERR("open '%s': %s", s, strerror(errno));
- return 0;
- }
+ me = getmntent(mtab);
- fs->path = strdup(s);
- update_fs_stats();
- return fs;
- }
+ // find our path in the mtab
+ search_path = strdup(path);
+ do {
+ while ((match = strcmp(search_path, me->mnt_dir))
+ && getmntent(mtab));
+ if (!match)
+ break;
+ fseek(mtab, 0, SEEK_SET);
+ slash = strrchr(search_path, '/');
+ if (slash == NULL)
+ CRIT_ERR("invalid path '%s'", path);
+ if (strlen(slash) == 1) /* trailing slash */
+ *(slash) = '\0';
+ else if (strlen(slash) > 1)
+ *(slash + 1) = '\0';
+ else
+ CRIT_ERR("found a crack in the matrix!");
+ } while (strlen(search_path) > 0);
+ free(search_path);
+
+ endmntent(mtab);
+
+ if (me && !match) {
+ strncpy(result, me->mnt_type, DEFAULT_TEXT_BUFFER_SIZE);
+ return;
}
+#endif /* HAVE_STRUCT_STATFS_F_FSTYPENAME */
+
+ strncpy(result, "unknown", DEFAULT_TEXT_BUFFER_SIZE);
- ERR("too many fs stats");
- return 0;
}