diff --git a/src/hwmon.cpp b/src/hwmon.cpp index f6c0e3a..bdf9a01 100644 --- a/src/hwmon.cpp +++ b/src/hwmon.cpp @@ -31,14 +31,17 @@ #include #include #include +#include namespace thinkfan { +namespace filesystem = std::filesystem; + static int filter_hwmon_dirs(const struct dirent *entry) { return (entry->d_type == DT_DIR || entry->d_type == DT_LNK) - && (!strncmp("hwmon", entry->d_name, 5) || !strcmp("device", entry->d_name)); + && (string(entry->d_name) == "hwmon" || string(entry->d_name) == "device"); } @@ -50,6 +53,43 @@ static int filter_subdirs(const struct dirent *entry) } +template<> +int HwmonInterface::filter_driver_file(const struct dirent *entry) +{ + int idx; + return (entry->d_type == DT_REG || entry->d_type == DT_LNK) + && !::sscanf(entry->d_name, "temp%d_input", &idx) + ; +} + +template<> +int HwmonInterface::filter_driver_file(const struct dirent *entry) +{ + int idx; + return (entry->d_type == DT_REG || entry->d_type == DT_LNK) + && !::sscanf(entry->d_name, "pwm%d", &idx) + ; +} + + +template +vector dir_entries(const filesystem::path &dir) +{ + struct dirent **entries; + int nentries = ::scandir(dir.c_str(), &entries, filter_fn, nullptr); + if (nentries == -1) + return {}; + + vector rv; + for (int i = 0; i < nentries; ++i) { + rv.emplace_back(dir / entries[i]->d_name); + ::free(entries[i]); + } + ::free(entries); + return rv; +} + + template vector HwmonInterface::find_files(const string &path, const vector &indices) { @@ -87,6 +127,7 @@ HwmonInterface::HwmonInterface(const string &base_path, opt vector HwmonInterface::find_hwmons_by_name( const string &path, @@ -108,15 +149,7 @@ vector HwmonInterface::find_hwmons_by_name( return result; // don't recurse to subdirs } - struct dirent **entries; - int nentries = ::scandir(path.c_str(), &entries, filter_subdirs, nullptr); - if (nentries == -1) { - return result; - } - for (int i = 0; i < nentries; i++) { - auto subdir = path + "/" + entries[i]->d_name; - free(entries[i]); - + for (const filesystem::path &subdir : dir_entries(path)) { struct stat statbuf; int err = stat(path.c_str(), &statbuf); if (err || (statbuf.st_mode & S_IFMT) != S_IFDIR) @@ -125,11 +158,11 @@ vector HwmonInterface::find_hwmons_by_name( auto found = find_hwmons_by_name(subdir, name, depth + 1); result.insert(result.end(), found.begin(), found.end()); } - free(entries); return result; } + template vector HwmonInterface::find_hwmons_by_model( const string &path, @@ -154,15 +187,7 @@ vector HwmonInterface::find_hwmons_by_model( return result; // don't recurse to subdirs } - struct dirent **entries; - int nentries = ::scandir(path.c_str(), &entries, filter_subdirs, nullptr); - if (nentries == -1) { - return result; - } - for (int i = 0; i < nentries; i++) { - auto subdir = path + "/" + entries[i]->d_name; - free(entries[i]); - + for (const filesystem::path &subdir : dir_entries(path)) { struct stat statbuf; int err = stat(path.c_str(), &statbuf); if (err || (statbuf.st_mode & S_IFMT) != S_IFDIR) @@ -171,11 +196,11 @@ vector HwmonInterface::find_hwmons_by_model( auto found = find_hwmons_by_model(subdir, model, depth + 1); result.insert(result.end(), found.begin(), found.end()); } - free(entries); return result; } + template vector HwmonInterface::find_hwmons_by_indices( const string &path, @@ -189,24 +214,20 @@ vector HwmonInterface::find_hwmons_by_indices( } catch (IOerror &) { if (depth <= max_depth) { - struct dirent **entries; - int nentries = ::scandir(path.c_str(), &entries, filter_hwmon_dirs, alphasort); - if (nentries < 0) + vector hwmon_dirs = dir_entries(path); + if (hwmon_dirs.empty()) throw IOerror("Error scanning " + path + ": ", errno); vector rv; - for (int i = 0; i < nentries; i++) { + for (const filesystem::path &hwmon_dir : hwmon_dirs) { rv = HwmonInterface::find_hwmons_by_indices( - path + "/" + entries[i]->d_name, + hwmon_dir, indices, depth + 1 ); if (rv.size()) break; } - for (int i = 0; i < nentries; i++) - free(entries[i]); - free(entries); return rv; } @@ -216,7 +237,6 @@ vector HwmonInterface::find_hwmons_by_indices( } - template string HwmonInterface::lookup() { @@ -231,7 +251,7 @@ string HwmonInterface::lookup() if (paths.size() != 1) { string msg(path + ": "); if (paths.size() == 0) { - msg += "Could not find a hwmon with this name: " + name_.value(); + msg += "Could not find an hwmon with this name: " + name_.value(); } else { msg += MSG_MULTIPLE_HWMONS_FOUND; for (string hwmon_path : paths) @@ -261,8 +281,10 @@ string HwmonInterface::lookup() if (found_paths_.size() == 0) throw DriverInitError(path + ": " + "Could not find any hwmons in " + path); } - else - found_paths_.push_back(path); + else { + vector paths = dir_entries(path); + found_paths_.assign(paths.begin(), paths.end()); + } paths_it_.emplace(found_paths_.begin()); } diff --git a/src/hwmon.h b/src/hwmon.h index 87551e5..f8f8fbe 100644 --- a/src/hwmon.h +++ b/src/hwmon.h @@ -41,6 +41,7 @@ class HwmonInterface { string lookup(); private: + static int filter_driver_file(const struct dirent *entry); static vector find_files(const string &path, const vector &indices); static string filename(int index); @@ -48,6 +49,7 @@ class HwmonInterface { static vector find_hwmons_by_name(const string &path, const string &name, unsigned char depth); static vector find_hwmons_by_indices(const string &path, const vector &indices, unsigned char depth); + protected: opt base_path_; opt name_;