Branch: Tag:

2016-11-17

2016-11-17 13:48:00 by Henrik Grubbström (Grubba) <grubba@grubba.org>

FSGC: Added support for quarantining instead of deleting.

This moves files to a quarantine directory instead of just deleting them.

Fixes some of [ep-31].

53:    mapping(string:object) handle_lookup = ([]);    ADT.Priority_queue pending_gc = ADT.Priority_queue();    - #ifdef FSGC_PRETEND +  //! If set, move files to this directory instead of deleting them. +  //! +  //! If set to @[root] or @expr{""@} keep the files as is. +  string quarantine; +     protected int rm(string path)    { -  werror("FSGC: Zap %O\n", path); +  GC_WERR("FSGC: Zap %O\n", path); +  if (quarantine) { +  if ((quarantine == root) || (quarantine == "")) return 0; +  if (!has_prefix(path, root)) return 0; +  string rel = path[sizeof(root)..]; +  +  // First try the trivial case. +  if (mv(path, quarantine + rel)) return 1; +  +  string dirs = dirname(rel); +  if (sizeof(dirs)) { +  if (Stdio.mkdirhier(quarantine + dirs)) { +  // Try again with the directory existing. +  if (mv(path, quarantine + rel)) return 1;    } - #endif +  }    -  +  // Different filesystems? +  if (Stdio.cp(path, quarantine + rel)) { +  return predef::rm(path); +  } +  werror("FSGC: Failed to copy file %O to %O: %s.\n", +  path, quarantine + rel, strerror(errno())); +  return 0; +  } else { +  return predef::rm(path); +  } +  } +     void check_threshold()    {    GC_WERR("FSGC: Checking thresholds...\n"
302:    }       protected void create(string modid, string path, int max_age, -  int|void max_size, int|void max_files) +  int|void max_size, int|void max_files, +  string|void quarantine)    {    GC_WERR("FSGC: Max age: %d\n", max_age);    GC_WERR("FSGC: Max size: %d\n", max_size);
316:       root = canonic_path(path);    +  if (quarantine) { +  if (sizeof(quarantine)) { +  quarantine = canonic_path(quarantine); +  } +  this::quarantine = quarantine; +  } +     ::create(max_age/file_interval_factor, 0, max_age);       // Workaround for too strict type-check in Pike 7.8.
429:   }      FSGarbWrapper register_fsgarb(string modid, string path, int max_age, -  int|void max_size, int|void max_files) +  int|void max_size, int|void max_files, +  string|void quarantine)   {    if ((path == "") || (path == "/") || (max_age <= 0)) return 0;    string id = modid + "\0" + path + "\0" + gethrtime(); -  FSGarb g = FSGarb(modid, path, max_age, max_size, max_files); +  FSGarb g = FSGarb(modid, path, max_age, max_size, max_files, +  quarantine);    fsgarbs[id] = g;    GC_WERR("FSGC: Register garb on %O ==> id: %O\n", path, id);    return FSGarbWrapper(id);