$OpenBSD: patch-common_CommonUtils_vala,v 1.1 2013/01/21 08:23:30 ajacoutot Exp $

https://bugzilla.redhat.com/show_bug.cgi?id=892063

--- common/CommonUtils.vala.orig	Tue Aug 21 17:08:23 2012
+++ common/CommonUtils.vala	Mon Jan 21 08:43:45 2013
@@ -444,6 +444,9 @@ public bool initialize(out string header, out string m
   var unused_backend = DejaDup.Backend.get_default();
   unused_backend = null;
 
+  // And cleanup from any previous runs
+  clean_tempdirs.begin();
+
   return true;
 }
 
@@ -580,6 +583,128 @@ public Date get_full_backup_threshold_date()
   date.subtract_days(days);
   
   return date;
+}
+
+public bool ensure_directory_exists(string path)
+{
+  var gfile = File.new_for_path(path);
+  try {
+    if (gfile.make_directory_with_parents())
+      return true;
+  }
+  catch (IOError.EXISTS e) {
+    return true; // ignore
+  }
+  catch (Error e) {
+    warning("%s\n", e.message);
+  }
+  return false;
+}
+
+// By default, duplicity uses normal tmp folders like /tmp to store its
+// in-process files.  These can get quite large, especially when restoring.
+// You may need up to twice the size of the largest source file.
+// Because /tmp may not be super large, especially on systems that use
+// tmpfs by default (e.g. Fedora 18), we try to use a tempdir that is on
+// the same partition as the source files.
+public async string get_tempdir()
+{
+  var tempdirs = get_tempdirs();
+
+  // First, decide the "main include".  Assume that if $HOME
+  // is present, that is it.  Else, the first include we find decides it.
+  // This is admittedly fast and loose, but our primary concern is just
+  // avoiding silly choices like tmpfs or tiny special /tmp partitions.
+  var settings = get_settings();
+  var include_val = settings.get_value(INCLUDE_LIST_KEY);
+  var include_list = parse_dir_list(include_val.get_strv());
+  File main_include = null;
+  var home = File.new_for_path(Environment.get_home_dir());
+  foreach (var include in include_list) {
+    if (include.equal(home)) {
+      main_include = include;
+      break;
+    }
+    else if (main_include == null)
+      main_include = include;
+  }
+  if (main_include == null)
+    return tempdirs[0];
+
+  // Grab that include's fs ID
+  string filesystem_id;
+  try {
+    var info = yield main_include.query_info_async(FileAttribute.ID_FILESYSTEM,
+                                                   FileQueryInfoFlags.NONE);
+    filesystem_id = info.get_attribute_string(FileAttribute.ID_FILESYSTEM);
+  }
+  catch (Error e) {
+    return tempdirs[0];
+  }
+
+  // Then, see which of our possible tempdirs matches that partition.
+  foreach (var tempdir in tempdirs) {
+    string temp_id;
+    ensure_directory_exists(tempdir);
+    try {
+      var gfile = File.new_for_path(tempdir);
+      var info = yield gfile.query_info_async(FileAttribute.ID_FILESYSTEM,
+                                              FileQueryInfoFlags.NONE);
+      temp_id = info.get_attribute_string(FileAttribute.ID_FILESYSTEM);
+    }
+    catch (Error e) {
+      continue;
+    }
+    if (temp_id == filesystem_id)
+      return tempdir;
+  }
+
+  // Fallback to simply using the highest preferred tempdir
+  return tempdirs[0];
+}
+
+public string[] get_tempdirs()
+{
+  var tempdir = Environment.get_variable("DEJA_DUP_TEMPDIR");
+  if (tempdir != null && tempdir != "")
+    return {tempdir};
+  // Prefer directories that have their own cleanup logic in case ours isn't
+  // run for a while.  (e.g. /tmp every boot, /var/tmp every now and then)
+  return {Environment.get_tmp_dir(), "/var/tmp",
+          Path.build_filename(Environment.get_user_cache_dir(), Config.PACKAGE,
+                              "tmp")};
+}
+
+public async void clean_tempdirs()
+{
+  var tempdirs = get_tempdirs();
+  const int NUM_ENUMERATED = 16;
+  foreach (var tempdir in tempdirs) {
+    var gfile = File.new_for_path(tempdir);
+
+    // Now try to find and delete all files that start with "duplicity-"
+    try {
+      var enumerator = yield gfile.enumerate_children_async(
+                         FileAttribute.STANDARD_NAME,
+                         FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
+                         Priority.DEFAULT, null);
+      while (true) {
+        var infos = yield enumerator.next_files_async(NUM_ENUMERATED,
+                                                      Priority.DEFAULT, null);
+        foreach (FileInfo info in infos) {
+          if (info.get_name().has_prefix("duplicity-")) {
+            var child = gfile.get_child(info.get_name());
+            yield new DejaDup.RecursiveDelete(child).start_async();
+          }
+        }
+        if (infos.length() != NUM_ENUMERATED)
+          break;
+      }
+    }
+    catch (Error e) {
+      // No worries
+    }
+  }
 }
 
 } // end namespace
