#include "modules/disk.hpp" #include using namespace waybar::util; waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config) : ALabel(config, "disk", id, "{}%", 30), header_(""), paths_(), separator_(" ") { thread_ = [this] { dp.emit(); thread_.sleep_for(interval_); }; if (config["header"].isString()) { header_ = config["header"].asString(); } if (config["path"].isString() && !config["paths"].isArray()) { spdlog::warn("Disk: path is deprecated use paths instead!"); paths_.push_back(config["path"].asString()); } if (config["paths"].isArray()) { for (const auto& path : config["paths"]) { paths_.push_back(path.asString()); } } if (!config["path"].isString() && !config["paths"].isArray()) { paths_.emplace_back("/"); } if (config["separator"].isString()) { separator_ = config["separator"].asString(); } if (config["unit"].isString()) { unit_ = config["unit"].asString(); } } auto waybar::modules::Disk::update() -> void { std::string tooltip_label; std::string label = header_; bool had_valid_disk = false; for (size_t i = 0; i < paths_.size(); ++i) { const auto& path = paths_[i]; struct statvfs /* { unsigned long f_bsize; // filesystem block size unsigned long f_frsize; // fragment size fsblkcnt_t f_blocks; // size of fs in f_frsize units fsblkcnt_t f_bfree; // # free blocks fsblkcnt_t f_bavail; // # free blocks for unprivileged users fsfilcnt_t f_files; // # inodes fsfilcnt_t f_ffree; // # free inodes fsfilcnt_t f_favail; // # free inodes for unprivileged users unsigned long f_fsid; // filesystem ID unsigned long f_flag; // mount flags unsigned long f_namemax; // maximum filename length }; */ stats; int err = statvfs(path.c_str(), &stats); /* Conky options fs_bar - Bar that shows how much space is used fs_free - Free space on a file system fs_free_perc - Free percentage of space fs_size - File system size fs_used - File system used space */ if (err != 0 || stats.f_blocks == 0) { spdlog::warn("Disk: statvfs failed for path '{}' (errno={})", path, errno); continue; } float specific_free, specific_used, specific_total, divisor; divisor = calc_specific_divisor(unit_); specific_free = (stats.f_bavail * stats.f_frsize) / divisor; specific_used = ((stats.f_blocks - stats.f_bfree) * stats.f_frsize) / divisor; specific_total = (stats.f_blocks * stats.f_frsize) / divisor; auto free = pow_format(stats.f_bavail * stats.f_frsize, "B", true); auto used = pow_format((stats.f_blocks - stats.f_bfree) * stats.f_frsize, "B", true); auto total = pow_format(stats.f_blocks * stats.f_frsize, "B", true); auto percentage_used = (stats.f_blocks - stats.f_bfree) * 100 / stats.f_blocks; std::string disk_format = format_; auto state = getState(percentage_used); if (!state.empty() && config_["format-" + state].isString()) { disk_format = config_["format-" + state].asString(); } if (!disk_format.empty()) { if (had_valid_disk) { label += separator_; } label += fmt::format( fmt::runtime(disk_format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), fmt::arg("total", total), fmt::arg("path", path), fmt::arg("specific_free", specific_free), fmt::arg("specific_used", specific_used), fmt::arg("specific_total", specific_total)); } std::string tooltip_format = "{used} used out of {total} on {path} ({percentage_used}%)"; if (config_["tooltip-format"].isString()) { tooltip_format = config_["tooltip-format"].asString(); } if (!tooltip_format.empty()) { if (had_valid_disk) { tooltip_label += "\n"; } tooltip_label += fmt::format( fmt::runtime(tooltip_format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), fmt::arg("total", total), fmt::arg("path", path), fmt::arg("specific_free", specific_free), fmt::arg("specific_used", specific_used), fmt::arg("specific_total", specific_total)); } had_valid_disk = true; } if (had_valid_disk) { event_box_.show(); } else { event_box_.hide(); } setLabelMarkup(label); if (tooltipEnabled() && !tooltip_label.empty()) { setTooltipMarkup(tooltip_label); } // Call parent update ALabel::update(); } float waybar::modules::Disk::calc_specific_divisor(const std::string& divisor) { if (divisor == "kB") { return 1000.0; } else if (divisor == "kiB") { return 1024.0; } else if (divisor == "MB") { return 1000.0 * 1000.0; } else if (divisor == "MiB") { return 1024.0 * 1024.0; } else if (divisor == "GB") { return 1000.0 * 1000.0 * 1000.0; } else if (divisor == "GiB") { return 1024.0 * 1024.0 * 1024.0; } else if (divisor == "TB") { return 1000.0 * 1000.0 * 1000.0 * 1000.0; } else if (divisor == "TiB") { return 1024.0 * 1024.0 * 1024.0 * 1024.0; } else { // default to Bytes if it is anything that we don't recognise return 1.0; } }