]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
deferred_unlink: add (fix) the directory tree removal, fixes #2814
authorJaroslav Kysela <perex@perex.cz>
Sat, 2 May 2015 16:38:42 +0000 (18:38 +0200)
committerJaroslav Kysela <perex@perex.cz>
Sat, 2 May 2015 16:38:42 +0000 (18:38 +0200)
src/dvr/dvr_db.c
src/tvheadend.h
src/utils.c

index 1187a789e0802f2dd37bc0d3581f62dbc6b48abe..ce9c91a9fdf71e2eae68e93e8002959ee0c16d12 100644 (file)
@@ -2208,9 +2208,10 @@ dvr_val2pri(dvr_prio_t v)
 void
 dvr_entry_delete(dvr_entry_t *de)
 {
+  dvr_config_t *cfg = de->de_config;
   time_t t;
   struct tm tm;
-  char tbuf[64];
+  char tbuf[64], *rdir;
   int r;
 
   t = dvr_entry_get_start_time(de);
@@ -2229,38 +2230,14 @@ dvr_entry_delete(dvr_entry_t *de)
 #if ENABLE_INOTIFY
     dvr_inotify_del(de);
 #endif
-    r = deferred_unlink(de->de_filename);
+    rdir = NULL;
+    if(cfg->dvr_title_dir || cfg->dvr_channel_dir || cfg->dvr_dir_per_day || de->de_directory)
+      rdir = cfg->dvr_storage;
+
+    r = deferred_unlink(de->de_filename, rdir);
     if(r && r != -ENOENT)
       tvhlog(LOG_WARNING, "dvr", "Unable to remove file '%s' from disk -- %s",
             de->de_filename, strerror(-errno));
-
-    /* Also delete directories, if they were created for the recording and if they are empty */
-
-    dvr_config_t *cfg = de->de_config;
-    char path[500];
-
-    snprintf(path, sizeof(path), "%s", cfg->dvr_storage);
-
-    if(cfg->dvr_title_dir || cfg->dvr_channel_dir || cfg->dvr_dir_per_day || de->de_directory) {
-      char *p;
-      int l;
-
-      l = strlen(de->de_filename);
-      p = alloca(l + 1);
-      memcpy(p, de->de_filename, l);
-      p[l--] = 0;
-
-      for(; l >= 0; l--) {
-        if(p[l] == '/') {
-          p[l] = 0;
-          if(strncmp(p, cfg->dvr_storage, strlen(p)) == 0)
-            break;
-          if(rmdir(p) == -1)
-            break;
-        }
-      }
-    }
-
   }
   dvr_entry_destroy(de, 1);
 }
index 81b8930f2efefc6fa0136629fe30d21ddefaed98..be0948d5c23b7fc9d8043522f69ed08f28efc860 100644 (file)
@@ -759,7 +759,7 @@ char *url_encode(char *str);
 
 int mpegts_word_count(const uint8_t *tsb, int len, uint32_t mask);
 
-int deferred_unlink(const char *filename);
+int deferred_unlink(const char *filename, const char *rootdir);
 
 static inline int32_t deltaI32(int32_t a, int32_t b) { return (a > b) ? (a - b) : (b - a); }
 static inline uint32_t deltaU32(uint32_t a, uint32_t b) { return (a > b) ? (a - b) : (b - a); }
index 4e8030d9666a97992fe80b4ee63ebbbb2a986906..0e621c71f631d00de8ee962625dc11887824ded3 100644 (file)
@@ -653,9 +653,45 @@ deferred_unlink_cb(void *s, int dearmed)
   free(s);
 }
 
+typedef struct {
+  char *filename;
+  char *rootdir;
+} deferred_unlink_t;
+
+static void
+deferred_unlink_dir_cb(void *s, int dearmed)
+{
+  deferred_unlink_t *du = s;
+  char *p;
+  int l;
+
+  if (unlink((const char *)du->filename))
+    tvherror("main", "unable to remove file '%s'", (const char *)du->filename);
+
+  /* Remove all directories up to rootdir */
+
+  l = strlen(du->filename) - 1;
+  p = du->filename;
+
+  for(; l >= 0; l--) {
+    if(p[l] == '/') {
+      p[l] = 0;
+      if(strncmp(p, du->rootdir, l) == 0)
+        break;
+      if(rmdir(p) == -1)
+        break;
+    }
+  }
+
+  free(du->filename);
+  free(du->rootdir);
+  free(du);
+}
+
 int
-deferred_unlink(const char *filename)
+deferred_unlink(const char *filename, const char *rootdir)
 {
+  deferred_unlink_t *du;
   char *s;
   size_t l;
   int r;
@@ -672,6 +708,15 @@ deferred_unlink(const char *filename)
     free(s);
     return r;
   }
-  tasklet_arm_alloc(deferred_unlink_cb, s);
+  if (rootdir == NULL)
+    tasklet_arm_alloc(deferred_unlink_cb, s);
+  else {
+    du = calloc(1, sizeof(*du));
+    if (du == NULL)
+      return -ENOMEM;
+    du->filename = s;
+    du->rootdir = strdup(rootdir);
+    tasklet_arm_alloc(deferred_unlink_dir_cb, du);
+  }
   return 0;
 }