refactor(fs): Read /proc/self/mountinfo

Refs #271
This commit is contained in:
Michael Carlberg 2017-01-12 23:31:52 +01:00
parent c737493620
commit 6dd72aa6f7
2 changed files with 34 additions and 62 deletions

View File

@ -1,37 +0,0 @@
#pragma once
#include <mntent.h>
#include "common.hpp"
#include "errors.hpp"
POLYBAR_NS
namespace mtab_util {
/**
* Wrapper for reading mtab entries
*/
class reader {
public:
explicit reader() {
if ((m_ptr = setmntent("/etc/mtab", "r")) == nullptr) {
throw system_error("Failed to read mtab");
}
}
~reader() {
if (m_ptr != nullptr) {
endmntent(m_ptr);
}
}
bool next(mntent** dst) {
return (*dst = getmntent(m_ptr)) != nullptr;
}
protected:
FILE* m_ptr = nullptr;
};
}
POLYBAR_NS_END

View File

@ -1,19 +1,23 @@
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <fstream>
#include "modules/fs.hpp"
#include "drawtypes/label.hpp" #include "drawtypes/label.hpp"
#include "drawtypes/progressbar.hpp" #include "drawtypes/progressbar.hpp"
#include "drawtypes/ramp.hpp" #include "drawtypes/ramp.hpp"
#include "modules/fs.hpp"
#include "utils/factory.hpp" #include "utils/factory.hpp"
#include "utils/math.hpp" #include "utils/math.hpp"
#include "utils/mtab.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "modules/meta/base.inl" #include "modules/meta/base.inl"
POLYBAR_NS POLYBAR_NS
// Columns in /proc/self/mountinfo
#define MOUNTINFO_DIR 4
#define MOUNTINFO_TYPE 7
#define MOUNTINFO_FSNAME 8
namespace modules { namespace modules {
template class module<fs_module>; template class module<fs_module>;
@ -57,42 +61,47 @@ namespace modules {
} }
/** /**
* Update values by reading mtab entries * Update mountpoints
*/ */
bool fs_module::update() { bool fs_module::update() {
m_mounts.clear(); m_mounts.clear();
for (auto&& mountpoint : m_mountpoints) { vector<vector<string>> mountinfo;
struct statvfs buffer {}; std::ifstream filestream("/proc/self/mountinfo");
struct mntent* mnt{nullptr}; string line;
m_mounts.emplace_back(new fs_mount{mountpoint, false}); // Get details for mounted filesystems
while (std::getline(filestream, line)) {
if (statvfs(mountpoint.c_str(), &buffer) == -1) { auto cols = string_util::split(line, ' ');
m_log.err("%s: Failed to query filesystem (statvfs() error: %s)", name(), strerror(errno)); if (std::find(m_mountpoints.begin(), m_mountpoints.end(), cols[MOUNTINFO_DIR]) != m_mountpoints.end()) {
continue; mountinfo.emplace_back(move(cols));
} }
}
auto mtab = factory_util::unique<mtab_util::reader>(); // Get data for defined mountpoints
auto& mount = m_mounts.back(); for (auto&& mountpoint : m_mountpoints) {
auto details = std::find_if(mountinfo.begin(), mountinfo.end(),
[&](const vector<string>& m) { return m.size() > 4 && m[4] == mountpoint; });
while (mtab->next(&mnt)) { m_mounts.emplace_back(new fs_mount{mountpoint, details != mountinfo.end()});
if (strlen(mnt->mnt_dir) != mountpoint.size()) { struct statvfs buffer {};
continue;
} else if (strncmp(mnt->mnt_dir, mountpoint.c_str(), mountpoint.size()) != 0) { if (!m_mounts.back()->mounted) {
continue; m_log.warn("%s: Mountpoint %s is not mounted", name(), mountpoint);
} } else if (statvfs(mountpoint.c_str(), &buffer) == -1) {
m_log.err("%s: Failed to query filesystem (statvfs() error: %s)", name(), strerror(errno));
} else {
auto& mount = m_mounts.back();
mount->mountpoint = details->at(MOUNTINFO_DIR);
mount->type = details->at(MOUNTINFO_TYPE);
mount->fsname = details->at(MOUNTINFO_FSNAME);
mount->mounted = true;
mount->mountpoint = mnt->mnt_dir;
mount->type = mnt->mnt_type;
mount->fsname = mnt->mnt_fsname;
mount->bytes_total = buffer.f_bsize * buffer.f_blocks; mount->bytes_total = buffer.f_bsize * buffer.f_blocks;
mount->bytes_free = buffer.f_bsize * buffer.f_bfree; mount->bytes_free = buffer.f_bsize * buffer.f_bfree;
mount->bytes_used = mount->bytes_total - buffer.f_bsize * buffer.f_bavail; mount->bytes_used = mount->bytes_total - buffer.f_bsize * buffer.f_bavail;
mount->percentage_free = math_util::percentage<double>(mount->bytes_avail, mount->bytes_total); mount->percentage_free = math_util::percentage<double>(mount->bytes_avail, mount->bytes_total);
mount->percentage_used = math_util::percentage<double>(mount->bytes_used, mount->bytes_total); mount->percentage_used = math_util::percentage<double>(mount->bytes_used, mount->bytes_total);
break;
} }
} }