]> www.vanbest.org Git - backupusage.git/commitdiff
Initial commit
authorJan-Pascal van Best <janpascal@vanbest.org>
Mon, 29 Aug 2011 07:07:46 +0000 (09:07 +0200)
committerJan-Pascal van Best <janpascal@vanbest.org>
Mon, 29 Aug 2011 07:07:46 +0000 (09:07 +0200)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
backupusage.cc [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..6dd1022
--- /dev/null
@@ -0,0 +1 @@
+backupusage
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..b8c673d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+# Dependencies:
+#   libboost-filesystem.dev
+#   libboost-regex-dev
+#   libboost-program-options-dev
+
+LIBS=-lboost_program_options -lboost_filesystem -lboost_regex
+
+all: backupusage
+
+test: backupusage
+       ./backupusage --limit=1000000 > result.txt
+
+backupusage: backupusage.cc
+       g++ $(LIBS) $^ -o $@
diff --git a/backupusage.cc b/backupusage.cc
new file mode 100644 (file)
index 0000000..2143ce0
--- /dev/null
@@ -0,0 +1,117 @@
+#include <set>
+#include <map>
+#include <string>
+#include <iostream>
+#include <sys/stat.h>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string/regex.hpp>
+#include <boost/regex.hpp>
+#include <boost/format.hpp>
+#include <boost/program_options.hpp>
+
+using namespace std;
+using namespace boost::filesystem;
+using namespace boost::algorithm;
+
+namespace po = boost::program_options;
+
+set<ino_t> inodes;
+map<path,long> dirs;
+
+boost::regex prefix_re;
+
+path strip_path( const path& dir ) {
+  return erase_regex_copy(dir.string(), prefix_re );
+}
+
+string ToHumanReadable(long x)
+{
+    //CONSTANTS FOR SIZING
+    double KB = 1024;
+    double MB = 1024 * KB;
+    double GB = 1024 * MB;
+    if (x < KB)
+        return (boost::format("%6d") % x).str();
+    else if (x < MB)
+    {
+        return (boost::format("%6.1fkB") % (x / KB)).str();
+    }
+    else if (x < GB)
+    {
+        return (boost::format("%6.1fMB") % (x / MB)).str();
+    }
+    else if (x >= GB)
+    {
+        return (boost::format("%6.1fGB") % (x / GB)).str();
+    }
+}
+
+void handle_file( const path& dir, const path& p ) {
+  struct stat buf;
+  if ( lstat(p.string().c_str(), &buf  )) {
+    cout << "error" << endl;
+  } else {
+    // cout << "inode: " << buf.st_ino << "; size: " << buf.st_size << endl;
+    if (inodes.find( buf.st_ino ) == inodes.end() ) {
+      inodes.insert( buf.st_ino );
+      dirs[strip_path(dir)] += buf.st_size;
+      // cout << "New inode, size of " << strip_path(dir) << " is now " << dirs[strip_path(dir)] << endl;
+    } else {
+      // cout << "Old inode" << endl;
+    }
+  }
+}
+
+void handle_dir( const path& dir ) {
+  // cout << dir << endl;
+  if ( dirs.find(strip_path(dir)) == dirs.end() ) {
+    dirs[strip_path(dir)] = 0;
+  }
+  directory_iterator i(dir), dir_end;
+  for(;i!= dir_end; ++i) {
+    if ( is_directory( *i ) ) {
+      handle_dir( *i );
+    } else {
+      handle_file( dir, *i );
+    }
+  }
+}
+
+int main( int argc, char** argv ) {
+  string start_dir;
+  string prefix;
+  long size_limit;
+
+  // Declare the supported options.
+  po::options_description desc("Allowed options");
+  desc.add_options()
+      ("help", "produce help message")
+      ("start-dir,s", po::value<string>(&start_dir)->default_value("/var/lib/backuppc/pc/nogrod"), "Starting directory")
+      ("prefix,p", po::value<string>(&prefix)->default_value("/var/lib/backuppc/pc/nogrod/[0-9]*/(f%2f|f)"), "Prefix to remove for counting (regular expression)")
+      ("limit,l", po::value<long>(&size_limit)->default_value(1), "Minimal directory size to show")
+  ;
+
+  po::variables_map vm;
+  po::store(po::parse_command_line(argc, argv, desc), vm);
+  po::notify(vm);    
+
+  if (vm.count("help")) {
+      cout << desc << "\n";
+      return 1;
+  }
+
+  prefix_re = boost::regex(prefix);
+
+  handle_dir( start_dir );
+
+
+  map<long,path> result;
+  for( map<path,long>::const_iterator i = dirs.begin(); i != dirs.end(); ++i ) {
+    if ( i->second >= size_limit ) result[i->second] = i->first;
+  }
+  for( map<long,path>::const_iterator i = result.begin(); i != result.end(); ++i ) {
+    cout << ToHumanReadable(i->first) << " (" << i->first << ") " << i->second << endl;
+  }
+}