[evolution-patches] bug 37329, cleaning up temp files from older sessions



I came up with the attached patch.  Any objections?  This is something
we covered in the last meeting, and implements one of the solutions
suggested.

It removes any internal recording of the filename, and just expires
files based on their access time.  Currently set to a minimum of 2
hours.

It also (optionally) creates the files in ~/.evolution/cache/tmp instead
of /tmp.  And if you do build it to talk to /tmp it just uses evolution-
uid not evolution-uid-pid anymore, so it can find it later.

I just realised now that it leaks the filenames - but it basically
leaked them before anyway (just kept them around for the entire session
in a list).  To fix that requires fixing everywhere its used to free the
strings I guess, which isn't a big task.

I think the atime checks will work properly for expiring directories,
etc.  My testing suggests that it should.  It depends a bit on the
filesystem mind you, and you can mount things with noatime, but then its
just the same as ctime anyway - and should still work.

 Michael

Index: e-util/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/e-util/ChangeLog,v
retrieving revision 1.438
diff -u -3 -r1.438 ChangeLog
--- e-util/ChangeLog	25 Feb 2004 21:15:45 -0000	1.438
+++ e-util/ChangeLog	27 Feb 2004 08:05:51 -0000
@@ -1,3 +1,17 @@
+2004-02-27  Not Zed  <NotZed Ximian com>
+
+	** See Bug #37329.
+
+	* e-mktemp.c (get_dir): setup a comjpile time option for storing
+	in the homedir, and also just use the uid as the key for a /tmp
+	dir option.
+	(e_mktemp_cleanup): removed entirely.
+	(e_mkstemp, e_mkdtemp, e_mktemp): dont save the file/dirname in a
+	list anymore.
+	(expire_dir_rec): expire old temp data from previous runs/old data
+	lying around.  Based on access time.
+	(get_dir): run an expirey every now and then.
+
 2004-02-25  Jeffrey Stedfast  <fejj ximian com>
 
 	* e-gui-utils.c (e_icon_for_mime_type): Protect against feeding
Index: e-util/e-mktemp.c
===================================================================
RCS file: /cvs/gnome/evolution/e-util/e-mktemp.c,v
retrieving revision 1.8
diff -u -3 -r1.8 e-mktemp.c
--- e-util/e-mktemp.c	27 Aug 2003 20:55:46 -0000	1.8
+++ e-util/e-mktemp.c	27 Feb 2004 08:05:51 -0000
@@ -33,40 +33,95 @@
 #include <unistd.h>
 #include <dirent.h>
 #include <errno.h>
+#include <stdio.h>
+#include <time.h>
 
-#ifdef ENABLE_THREADS
-#include <pthread.h>
-#endif
+#include <gal/util/e-util.h>
 
 #include "e-mktemp.h"
 
+#define d(x) x
 
-static gboolean initialized = FALSE;
-static GSList *temp_files = NULL;
-static GSList *temp_dirs = NULL;
-#ifdef ENABLE_THREADS
-static pthread_mutex_t temp_files_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t temp_dirs_lock = PTHREAD_MUTEX_INITIALIZER;
-#define TEMP_FILES_LOCK() pthread_mutex_lock (&temp_files_lock)
-#define TEMP_FILES_UNLOCK() pthread_mutex_unlock (&temp_files_lock)
-#define TEMP_DIRS_LOCK() pthread_mutex_lock (&temp_dirs_lock)
-#define TEMP_DIRS_UNLOCK() pthread_mutex_unlock (&temp_dirs_lock)
-#else
-#define TEMP_FILES_LOCK()
-#define TEMP_FILES_UNLOCK()
-#define TEMP_DIRS_LOCK()
-#define TEMP_DIRS_UNLOCK()
-#endif /* ENABLE_THREADS */
+/* define to put temporary files in ~/evolution/cache/tmp */
+#define TEMP_HOME (1)
+
+/* how old things need to be to expire */
+#define TEMP_EXPIRE (60*60*2)
+/* dont scan more often than this */
+#define TEMP_SCAN (60)
+
+static int
+expire_dir_rec(const char *base, time_t now)
+{
+	DIR *dir;
+	struct dirent *d;
+	GString *path;
+	size_t len;
+	struct stat st;
+	int count = 0;
+
+	printf("expire dir '%s'\n", base);
+
+	dir = opendir(base);
+	if (dir == NULL)
+		return 0;
+
+	path = g_string_new(base);
+	len = path->len;
+
+	while ( (d = readdir(dir)) ) {
+		if (strcmp(d->d_name, ".") == 0
+		    || strcmp(d->d_name, "..") == 0)
+			continue;
+
+		g_string_truncate(path, len);
+		g_string_append_printf(path, "/%s", d->d_name);
+		d(printf("Checking '%s' for expiry\n", path->str));
+
+		if (stat(path->str, &st) == 0
+		    && st.st_atime + TEMP_EXPIRE < now) {
+			if (S_ISDIR(st.st_mode)) {
+				if (expire_dir_rec(path->str, now) == 0) {
+					printf("Removing dir '%s'\n", path->str);
+					rmdir(path->str);
+				} else {
+					count++;
+				}
+			} else if (unlink(path->str) == -1) {
+				printf("expiry failed: %s\n", strerror(errno));
+				count++;
+			} else {
+				printf("expired %s\n", path->str);
+			}
+		} else {
+			count++;
+		}
+	}
+	g_string_free(path, TRUE);
+	closedir(dir);
 
+	printf("expire dir '%s' %d remaining files\n", base, count);
+
+	return count;
+}
 
 static GString *
-get_path (gboolean make)
+get_dir (gboolean make)
 {
 	GString *path;
+	time_t now = time(0);
+	static time_t last = 0;
 	
-	path = g_string_new ("/tmp/evolution-");
-	g_string_append_printf (path, "%d-%d", (int) getuid (), (int) getpid ());
-	
+#ifdef TEMP_HOME
+	path = g_string_new (g_get_home_dir());
+	g_string_append_printf(path, "/.evolution/cache/tmp");
+	if (make && e_mkdir_hier(path->str, 0777) == -1) {
+		g_string_free(path, TRUE);
+		path = NULL;
+	}
+#else
+	path = g_string_new("/tmp/evolution-");
+	g_string_append_printf (path, "%d", (int) getuid ());
 	if (make) {
 		int ret;
 		
@@ -96,69 +151,19 @@
 			}
 		}
 	}
-	
-	return path;
-}
+#endif	
 
-static void
-e_mktemp_cleanup (void)
-{
-	GString *path;
-	GSList *node;
-	
-	TEMP_FILES_LOCK ();
-	if (temp_files) {
-		node = temp_files;
-		while (node) {
-			unlink (node->data);
-			g_free (node->data);
-			node = node->next;
-		}
-		g_slist_free (temp_files);
-		temp_files = NULL;
-	}
-	TEMP_FILES_UNLOCK ();
-	
-	TEMP_DIRS_LOCK ();
-	if (temp_dirs) {
-		node = temp_dirs;
-		while (node) {
-			/* perform the equivalent of a rm -rf */
-			struct dirent *dent;
-			DIR *dir;
-			
-			/* first empty out this directory of it's files... */
-			dir = opendir (node->data);
-			if (dir) {
-				while ((dent = readdir (dir)) != NULL) {
-					char *full_path;
-					
-					if (!strcmp (dent->d_name, ".") || !strcmp (dent->d_name, ".."))
-						continue;
-					
-					full_path = g_strdup_printf ("%s/%s", node->data, dent->d_name);
-					unlink (full_path);
-					g_free (full_path);
-				}
-				closedir (dir);
-			}
-			
-			/* ...then rmdir the directory */
-			rmdir (node->data);
-			g_free (node->data);
-			node = node->next;
-		}
-		g_slist_free (temp_dirs);
-		temp_dirs = NULL;
+	if (path)
+		printf("temp dir '%s'\n", path->str);
+
+	/* fire off an expirey attempt no more often than TEMP_SCAN seconds */
+	if (path && (last+TEMP_SCAN) < now) {
+		last = now;
+		expire_dir_rec(path->str, now);
 	}
-	TEMP_DIRS_UNLOCK ();
-	
-	path = get_path (FALSE);
-	rmdir (path->str);
-	
-	g_string_free (path, TRUE);
-}
 
+	return path;
+}
 
 const char *
 e_mktemp (const char *template)
@@ -166,7 +171,7 @@
 	GString *path;
 	char *ret;
 	
-	path = get_path (TRUE);
+	path = get_dir (TRUE);
 	if (!path)
 		return NULL;
 	
@@ -177,18 +182,7 @@
 		g_string_append (path, "unknown-XXXXXX");
 	
 	ret = mktemp (path->str);
-	if (ret) {
-		TEMP_FILES_LOCK ();
-		if (!initialized) {
-			g_atexit (e_mktemp_cleanup);
-			initialized = TRUE;
-		}
-		temp_files = g_slist_prepend (temp_files, ret);
-		g_string_free (path, FALSE);
-		TEMP_FILES_UNLOCK ();
-	} else {
-		g_string_free (path, TRUE);
-	}
+	g_string_free(path, ret == NULL);
 	
 	return ret;
 }
@@ -200,7 +194,7 @@
 	GString *path;
 	int fd;
 	
-	path = get_path (TRUE);
+	path = get_dir (TRUE);
 	if (!path)
 		return -1;
 	
@@ -211,18 +205,7 @@
 		g_string_append (path, "unknown-XXXXXX");
 	
 	fd = mkstemp (path->str);
-	if (fd != -1) {
-		TEMP_FILES_LOCK ();
-		if (!initialized) {
-			g_atexit (e_mktemp_cleanup);
-			initialized = TRUE;
-		}
-		temp_files = g_slist_prepend (temp_files, path->str);
-		g_string_free (path, FALSE);
-		TEMP_FILES_UNLOCK ();
-	} else {
-		g_string_free (path, TRUE);
-	}
+	g_string_free(path, TRUE);
 	
 	return fd;
 }
@@ -234,7 +217,7 @@
 	GString *path;
 	char *tmpdir;
 	
-	path = get_path (TRUE);
+	path = get_dir (TRUE);
 	if (!path)
 		return NULL;
 	
@@ -253,19 +236,7 @@
 			tmpdir = NULL;
 	}
 #endif
-	
-	if (tmpdir) {
-		TEMP_DIRS_LOCK ();
-		if (!initialized) {
-			g_atexit (e_mktemp_cleanup);
-			initialized = TRUE;
-		}
-		temp_dirs = g_slist_prepend (temp_dirs, tmpdir);
-		g_string_free (path, FALSE);
-		TEMP_DIRS_UNLOCK ();
-	} else {
-		g_string_free (path, TRUE);
-	}
+	g_string_free(path, tmpdir == NULL);
 	
 	return tmpdir;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]