add get_free_diskspace()
authorGerd von Egidy <gerd.von.egidy@intra2net.com>
Wed, 16 Dec 2015 13:37:17 +0000 (14:37 +0100)
committerGerd von Egidy <gerd.von.egidy@intra2net.com>
Wed, 16 Dec 2015 13:37:17 +0000 (14:37 +0100)
src/filefunc.cpp
src/filefunc.hxx
test/test_filefunc.cpp

index 4316048..5359f46 100644 (file)
@@ -33,6 +33,7 @@ on this file might be covered by the GNU General Public License.
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/statvfs.h>
 #include <dirent.h>
 #include <pwd.h>
 #include <grp.h>
@@ -951,5 +952,37 @@ bool remove_unlisted_files(const std::string &directory,
     return all_fine;
 }
 
+/**
+ * @brief Get free size in bytes on a given path or filename
+ *
+ * @param path Directory or filename to look in
+ *
+ * @return Number of bytes available to a regular user, -1 in case of an error
+ **/
+long long get_free_diskspace(const std::string& path)
+{
+    struct statvfs sf;
+
+    int ret;
+    while ( ((ret=statvfs(path.c_str(),&sf)) == -1) && (errno==EINTR) );
+
+    if (ret==-1)
+    {
+        // a real error occured
+        return -1;
+    }
+
+    long long free_bytes=0;
+
+    // load block size
+    free_bytes=sf.f_bsize;
+
+    // multiply by number of free blocks accessible by normal users
+    // make sure we really multiply long long by long long and don't overflow at 2 GB
+    free_bytes*=(long long)sf.f_bavail;
+
+    return free_bytes;
+}
+
 
 } // eo namespace I2n
index a2f4bc0..7e71311 100644 (file)
@@ -190,6 +190,8 @@ bool chdir(const std::string &path, std::string *error=NULL);
 
 mode_t umask(mode_t mask);
 
+long long get_free_diskspace(const std::string& path);
+
 
 /*
 ** more specialized tool function(s)
index 88515d1..fd1efb0 100644 (file)
@@ -41,6 +41,8 @@ on this file might be covered by the GNU General Public License.
 
 #include <filefunc.hxx>
 #include <daemonfunc.hpp>
+#include <pipestream.hxx>
+#include <stringfunc.hxx>
 
 #ifdef NOISEDEBUG
 #define DOUT(msg) std::cout << msg << std::endl
@@ -512,4 +514,22 @@ BOOST_AUTO_TEST_CASE(FileContentDiffersEqualSize)
     BOOST_CHECK_EQUAL( true, res );
 }
 
+BOOST_AUTO_TEST_CASE(FreeDiskSpace1)
+{
+    inpipestream cmd_df("df -B 1 --output=avail /tmp | tail -n 1");
+    string dfstr;
+    if (cmd_df)
+        getline(cmd_df, dfstr);
+
+    long long dfout=-1;
+    string_to<long long>(dfstr,dfout);
+
+    BOOST_CHECK_EQUAL( dfout, get_free_diskspace("/tmp") );
+}
+
+BOOST_AUTO_TEST_CASE(FreeDiskSpace2)
+{
+    BOOST_CHECK_EQUAL( -1, get_free_diskspace("/this/path/is/really/bogus") );
+}
+
 BOOST_AUTO_TEST_SUITE_END()