[Commits] utils.c 1.36.2.209 1.36.2.210 utils.h 1.20.2.83 1.20.2.84

colin at claws-mail.org colin at claws-mail.org
Sat Dec 1 22:03:50 CET 2012


Update of /home/claws-mail/claws/src/common
In directory srv:/tmp/cvs-serv8152/src/common

Modified Files:
      Tag: gtk2
	utils.c utils.h 
Log Message:
2012-12-01 [colin]	3.9.0cvs34

	* src/common/utils.c
	* src/common/utils.h
		Add a canonicalizer function and use it to
		canonicalize rc_dir.

Index: utils.c
===================================================================
RCS file: /home/claws-mail/claws/src/common/utils.c,v
retrieving revision 1.36.2.209
retrieving revision 1.36.2.210
diff -u -d -r1.36.2.209 -r1.36.2.210
--- utils.c	16 Nov 2012 23:42:15 -0000	1.36.2.209
+++ utils.c	1 Dec 2012 21:03:48 -0000	1.36.2.210
@@ -1874,21 +1874,26 @@
 
 void set_rc_dir(const gchar *dir)
 {
+	gchar *canonical_dir;
 	if (claws_rc_dir != NULL) {
 		g_print("Error: rc_dir already set\n");
 	} else {
-		rc_dir_alt = TRUE;
-		if (g_path_is_absolute(dir))
-			claws_rc_dir = g_strdup(dir);
-		else {
-			claws_rc_dir = g_strconcat(g_get_current_dir(),
-				G_DIR_SEPARATOR_S, dir, NULL);
+		int err = cm_canonicalize_filename(dir, &canonical_dir);
+		if (err) {
+			g_print("Error looking for %s: %d(%s)\n",
+				dir, -err, strerror(-err));
+			exit(0);
 		}
+		rc_dir_alt = TRUE;
+
+		claws_rc_dir = canonical_dir;
+		
 		debug_print("set rc_dir to %s\n", claws_rc_dir);
 		if (!is_dir_exist(claws_rc_dir)) {
 			if (make_dir_hier(claws_rc_dir) != 0) {
 				g_print("Error: can't create %s\n",
 				claws_rc_dir);
+				exit(0);
 			}
 		}
 	}
@@ -5346,3 +5351,139 @@
 	g_mutex_free(mutex);
 #endif
 }
+
+static gchar *canonical_list_to_file(GSList *list)
+{
+	GString *result = g_string_new(NULL);
+	GSList *pathlist = g_slist_reverse(g_slist_copy(list));
+	GSList *cur;
+	gchar *str;
+
+	result = g_string_append(result, G_DIR_SEPARATOR_S);
+
+	for (cur = pathlist; cur; cur = cur->next) {
+		result = g_string_append(result, (gchar *)cur->data);
+		if (cur->next)
+			result = g_string_append(result, G_DIR_SEPARATOR_S);
+	}
+	g_slist_free(pathlist);
+
+	str = result->str;
+	g_string_free(result, FALSE);
+
+	return str;
+}
+
+static GSList *cm_split_path(const gchar *filename, int depth)
+{
+	gchar **path_parts;
+	GSList *canonical_parts = NULL;
+	struct stat st;
+	int i;
+	gboolean follow_symlinks = TRUE;
+
+	if (depth > 32) {
+		errno = ELOOP;
+		return NULL;
+	}
+
+	if (!g_path_is_absolute(filename)) {
+		errno =EINVAL;
+		return NULL;
+	}
+
+	path_parts = g_strsplit(filename, G_DIR_SEPARATOR_S, -1);
+
+	for (i = 0; path_parts[i] != NULL; i++) {
+		if (!strcmp(path_parts[i], ""))
+			continue;
+		if (!strcmp(path_parts[i], "."))
+			continue;
+		else if (!strcmp(path_parts[i], "..")) {
+			if (i == 0) {
+				errno =ENOTDIR;
+				return NULL;
+			}
+			else /* Remove the last inserted element */
+				canonical_parts = 
+					g_slist_delete_link(canonical_parts,
+							    canonical_parts);
+		} else {
+			gchar *tmp_path;
+
+			canonical_parts = g_slist_prepend(canonical_parts,
+						g_strdup(path_parts[i]));
+
+			tmp_path = canonical_list_to_file(canonical_parts);
+
+			if(g_stat(tmp_path, &st) < 0) {
+				if (errno == ENOENT) {
+					errno = 0;
+					follow_symlinks = FALSE;
+				}
+				if (errno != 0) {
+					g_free(tmp_path);
+					slist_free_strings_full(canonical_parts);
+					g_strfreev(path_parts);
+
+					return NULL;
+				}
+			}
+			if (follow_symlinks && g_file_test(tmp_path, G_FILE_TEST_IS_SYMLINK)) {
+				GError *error = NULL;
+				gchar *target = g_file_read_link(tmp_path, &error);
+
+				slist_free_strings_full(canonical_parts);
+				canonical_parts = NULL;
+				if (!error)
+					canonical_parts = cm_split_path(target, depth + 1);
+				else
+					g_error_free(error);
+				if (canonical_parts == NULL) {
+					g_free(tmp_path);
+					g_strfreev(path_parts);
+					return NULL;
+				}
+				g_free(target);
+			}
+			g_free(tmp_path);
+		}
+	}
+	g_strfreev(path_parts);
+	return canonical_parts;
+}
+
+/*
+ * Canonicalize a filename, resolving symlinks along the way.
+ * Returns a negative errno in case of error.
+ */
+int cm_canonicalize_filename(const gchar *filename, gchar **canonical_name) {
+	GSList *canonical_parts;
+	gboolean is_absolute;
+
+	if (filename == NULL)
+		return -EINVAL;
+	if (canonical_name == NULL)
+		return -EINVAL;
+	*canonical_name = NULL;
+
+	is_absolute = g_path_is_absolute(filename);
+	if (!is_absolute) {
+		/* Always work on absolute filenames. */
+		gchar *cur = g_get_current_dir();
+		gchar *absolute_filename = g_strconcat(cur, G_DIR_SEPARATOR_S,
+						       filename, NULL);
+		
+		canonical_parts = cm_split_path(absolute_filename, 0);
+		g_free(absolute_filename);
+		g_free(cur);
+	} else
+		canonical_parts = cm_split_path(filename, 0);
+
+	if (canonical_parts == NULL)
+		return -errno;
+
+	*canonical_name = canonical_list_to_file(canonical_parts);
+	slist_free_strings_full(canonical_parts);
+	return 0;
+}

Index: utils.h
===================================================================
RCS file: /home/claws-mail/claws/src/common/utils.h,v
retrieving revision 1.20.2.83
retrieving revision 1.20.2.84
diff -u -d -r1.20.2.83 -r1.20.2.84
--- utils.h	25 Oct 2012 07:44:59 -0000	1.20.2.83
+++ utils.h	1 Dec 2012 21:03:48 -0000	1.20.2.84
@@ -591,6 +591,7 @@
 GMutex *cm_mutex_new(void);
 void cm_mutex_free(GMutex *mutex);
 
+int cm_canonicalize_filename(const gchar *filename, gchar **canonical_name);
 #ifdef __cplusplus
 }
 #endif



More information about the Commits mailing list