diff --git a/src/statfs.cpp b/src/statfs.cpp index 4741b444..2ac375e8 100644 --- a/src/statfs.cpp +++ b/src/statfs.cpp @@ -21,45 +21,18 @@ #include #include -#include +#include #include #include #include "config.hpp" #include "rwlock.hpp" +#include "success_fail.hpp" #include "ugid.hpp" using std::string; +using std::map; using std::vector; -using std::pair; - -#define EQ(FOO) (lhs.f_##FOO == rhs.f_##FOO) - -static -bool -operator==(const struct statvfs &lhs, - const struct statvfs &rhs) -{ - return (EQ(bsize) && - EQ(frsize) && - EQ(blocks) && - EQ(bfree) && - EQ(bavail) && - EQ(files) && - EQ(ffree) && - EQ(favail) && - EQ(fsid) && - EQ(flag) && - EQ(namemax)); -} - -static -bool -member(const vector &haystack, - const struct statvfs &needle) -{ - return (std::find(haystack.begin(),haystack.end(),needle) != haystack.end()); -} static void @@ -90,47 +63,62 @@ _merge_statvfs(struct statvfs * const out, out->f_favail += in->f_favail; } +static +void +_statfs_core(const char *srcmount, + unsigned long &min_bsize, + unsigned long &min_frsize, + unsigned long &min_namemax, + map &fsstats) +{ + int rv; + struct stat st; + struct statvfs fsstat; + + rv = ::statvfs(srcmount,&fsstat); + if(STATVFS_FAILED(rv)) + return; + + rv = ::stat(srcmount,&st); + if(STAT_FAILED(rv)) + return; + + if(min_bsize > fsstat.f_bsize) + min_bsize = fsstat.f_bsize; + if(min_frsize > fsstat.f_frsize) + min_frsize = fsstat.f_frsize; + if(min_namemax > fsstat.f_namemax) + min_namemax = fsstat.f_namemax; + + fsstats.insert(std::make_pair(st.st_dev,fsstat)); +} + static int _statfs(const vector &srcmounts, struct statvfs &fsstat) { - vector fsstats; + map fsstats; unsigned long min_bsize = ULONG_MAX; unsigned long min_frsize = ULONG_MAX; unsigned long min_namemax = ULONG_MAX; for(size_t i = 0, ei = srcmounts.size(); i < ei; i++) { - int rv; - struct statvfs fsstat; - - rv = ::statvfs(srcmounts[i].c_str(),&fsstat); - if((rv == -1) || member(fsstats,fsstat)) - continue; - - if(min_bsize > fsstat.f_bsize) - min_bsize = fsstat.f_bsize; - if(min_frsize > fsstat.f_frsize) - min_frsize = fsstat.f_frsize; - if(min_namemax > fsstat.f_namemax) - min_namemax = fsstat.f_namemax; - - fsstats.push_back(fsstat); + _statfs_core(srcmounts[i].c_str(),min_bsize,min_frsize,min_namemax,fsstats); } - if(!fsstats.empty()) + map::iterator iter = fsstats.begin(); + map::iterator enditer = fsstats.end(); + if(iter != enditer) { - fsstat = fsstats[0]; + fsstat = iter->second; _normalize_statvfs(&fsstat,min_bsize,min_frsize,min_namemax); - for(size_t i = 1, ei = fsstats.size(); i < ei; i++) + for(++iter; iter != enditer; ++iter) { - struct statvfs tmp = fsstats[i]; - - _normalize_statvfs(&tmp,min_bsize,min_frsize,min_namemax); - - _merge_statvfs(&fsstat,&tmp); + _normalize_statvfs(&iter->second,min_bsize,min_frsize,min_namemax); + _merge_statvfs(&fsstat,&iter->second); } } diff --git a/src/success_fail.hpp b/src/success_fail.hpp index 9809f37a..85495689 100644 --- a/src/success_fail.hpp +++ b/src/success_fail.hpp @@ -18,6 +18,8 @@ #define STATVFS_SUCCESS 0 #define STATVFS_SUCCEEDED(RV) ((RV) == STATVFS_SUCCESS) +#define STATVFS_FAIL -1 +#define STATVFS_FAILED(RV) ((RV) == STATVFS_FAIL) #define STAT_SUCCESS 0 #define STAT_SUCCEEDED(RV) ((RV) == STAT_SUCCESS)