evolution-3.6.4/mail/e-mail-migrate.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-mail-migrate.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-mail-migrate.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
  1 /*
  2  * e-mail-migrate.c
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) version 3.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 16  *
 17  *
 18  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 19  *
 20  */
 21 
 22 #ifdef HAVE_CONFIG_H
 23 #include <config.h>
 24 #endif
 25 
 26 #include "e-mail-migrate.h"
 27 
 28 #include <stdio.h>
 29 #include <stdlib.h>
 30 #include <string.h>
 31 #include <sys/types.h>
 32 #include <sys/stat.h>
 33 #include <utime.h>
 34 #include <unistd.h>
 35 #include <dirent.h>
 36 #include <regex.h>
 37 #include <errno.h>
 38 #include <ctype.h>
 39 
 40 #include <glib/gi18n.h>
 41 #include <glib/gstdio.h>
 42 
 43 #include <gtk/gtk.h>
 44 
 45 #include <libxml/tree.h>
 46 #include <libxml/parser.h>
 47 #include <libxml/xmlmemory.h>
 48 
 49 #include <shell/e-shell.h>
 50 #include <shell/e-shell-migrate.h>
 51 
 52 #include <e-util/e-util.h>
 53 #include <libevolution-utils/e-xml-utils.h>
 54 
 55 #include <libevolution-utils/e-alert-dialog.h>
 56 #include <e-util/e-util-private.h>
 57 #include <e-util/e-plugin.h>
 58 
 59 #include <libemail-engine/e-mail-folder-utils.h>
 60 
 61 #include "e-mail-backend.h"
 62 #include "em-utils.h"
 63 
 64 #define d(x) x
 65 
 66 /* 1.4 upgrade functions */
 67 
 68 static GtkProgressBar *progress;
 69 
 70 static void
 71 em_migrate_set_progress (double percent)
 72 {
 73 	gchar text[5];
 74 
 75 	snprintf (text, sizeof (text), "%d%%", (gint) (percent * 100.0f));
 76 
 77 	gtk_progress_bar_set_fraction (progress, percent);
 78 	gtk_progress_bar_set_text (progress, text);
 79 
 80 	while (gtk_events_pending ())
 81 		gtk_main_iteration ();
 82 }
 83 
 84 enum {
 85 	CP_UNIQUE = 0,
 86 	CP_OVERWRITE,
 87 	CP_APPEND
 88 };
 89 
 90 static gint open_flags[3] = {
 91 	O_WRONLY | O_CREAT | O_TRUNC,
 92 	O_WRONLY | O_CREAT | O_TRUNC,
 93 	O_WRONLY | O_CREAT | O_APPEND,
 94 };
 95 
 96 static gboolean
 97 cp (const gchar *src,
 98     const gchar *dest,
 99     gboolean show_progress,
100     gint mode)
101 {
102 	guchar readbuf[65536];
103 	gssize nread, nwritten;
104 	gint errnosav, readfd, writefd;
105 	gsize total = 0;
106 	struct stat st;
107 	struct utimbuf ut;
108 
109 	/* if the dest file exists and has content, abort - we don't
110 	 * want to corrupt their existing data */
111 	if (g_stat (dest, &st) == 0 && st.st_size > 0 && mode == CP_UNIQUE) {
112 		errno = EEXIST;
113 		return FALSE;
114 	}
115 
116 	if (g_stat (src, &st) == -1
117 	    || (readfd = g_open (src, O_RDONLY | O_BINARY, 0)) == -1)
118 		return FALSE;
119 
120 	if ((writefd = g_open (dest, open_flags[mode] | O_BINARY, 0666)) == -1) {
121 		errnosav = errno;
122 		close (readfd);
123 		errno = errnosav;
124 		return FALSE;
125 	}
126 
127 	do {
128 		do {
129 			nread = read (readfd, readbuf, sizeof (readbuf));
130 		} while (nread == -1 && errno == EINTR);
131 
132 		if (nread == 0)
133 			break;
134 		else if (nread < 0)
135 			goto exception;
136 
137 		do {
138 			nwritten = write (writefd, readbuf, nread);
139 		} while (nwritten == -1 && errno == EINTR);
140 
141 		if (nwritten < nread)
142 			goto exception;
143 
144 		total += nwritten;
145 		if (show_progress)
146 			em_migrate_set_progress (((gdouble) total) / ((gdouble) st.st_size));
147 	} while (total < st.st_size);
148 
149 	if (fsync (writefd) == -1)
150 		goto exception;
151 
152 	close (readfd);
153 	if (close (writefd) == -1)
154 		goto failclose;
155 
156 	ut.actime = st.st_atime;
157 	ut.modtime = st.st_mtime;
158 	utime (dest, &ut);
159 	chmod (dest, st.st_mode);
160 
161 	return TRUE;
162 
163  exception:
164 
165 	errnosav = errno;
166 	close (readfd);
167 	close (writefd);
168 	errno = errnosav;
169 
170  failclose:
171 
172 	errnosav = errno;
173 	unlink (dest);
174 	errno = errnosav;
175 
176 	return FALSE;
177 }
178 
179 static gboolean
180 emm_setup_initial (const gchar *data_dir)
181 {
182 	GDir *dir;
183 	const gchar *d;
184 	gchar *local = NULL, *base;
185 	const gchar * const *language_names;
186 
187 	/* special-case - this means brand new install of evolution */
188 	/* FIXME: create default folders and stuff... */
189 
190 	d (printf ("Setting up initial mail tree\n"));
191 
192 	base = g_build_filename (data_dir, "local", NULL);
193 	if (g_mkdir_with_parents (base, 0700) == -1 && errno != EEXIST) {
194 		g_free (base);
195 		return FALSE;
196 	}
197 
198 	/* e.g. try en-AU then en, etc */
199 	language_names = g_get_language_names ();
200 	while (*language_names != NULL) {
201 		local = g_build_filename (
202 			EVOLUTION_PRIVDATADIR, "default",
203 			*language_names, "mail", "local", NULL);
204 		if (g_file_test (local, G_FILE_TEST_EXISTS))
205 			break;
206 		g_free (local);
207 		language_names++;
208 	}
209 
210 	/* Make sure we found one. */
211 	g_return_val_if_fail (*language_names != NULL, FALSE);
212 
213 	dir = g_dir_open (local, 0, NULL);
214 	if (dir) {
215 		while ((d = g_dir_read_name (dir))) {
216 			gchar *src, *dest;
217 
218 			src = g_build_filename (local, d, NULL);
219 			dest = g_build_filename (base, d, NULL);
220 
221 			cp (src, dest, FALSE, CP_UNIQUE);
222 			g_free (dest);
223 			g_free (src);
224 		}
225 		g_dir_close (dir);
226 	}
227 
228 	g_free (local);
229 	g_free (base);
230 
231 	return TRUE;
232 }
233 
234 static void
235 em_rename_view_in_folder (gpointer data,
236                           gpointer user_data)
237 {
238 	const gchar *filename = data;
239 	const gchar *views_dir = user_data;
240 	gchar *folderpos, *dotpos;
241 
242 	g_return_if_fail (filename != NULL);
243 	g_return_if_fail (views_dir != NULL);
244 
245 	folderpos = strstr (filename, "-folder:__");
246 	if (!folderpos)
247 		folderpos = strstr (filename, "-folder___");
248 	if (!folderpos)
249 		return;
250 
251 	/* points on 'f' from the "folder" word */
252 	folderpos++;
253 	dotpos = strrchr (filename, '.');
254 	if (folderpos < dotpos && g_str_equal (dotpos, ".xml")) {
255 		GChecksum *checksum;
256 		gchar *oldname, *newname, *newfile;
257 		const gchar *md5_string;
258 
259 		*dotpos = 0;
260 
261 		/* use MD5 checksum of the folder URI, to not depend on its length */
262 		checksum = g_checksum_new (G_CHECKSUM_MD5);
263 		g_checksum_update (checksum, (const guchar *) folderpos, -1);
264 
265 		*folderpos = 0;
266 		md5_string = g_checksum_get_string (checksum);
267 		newfile = g_strconcat (filename, md5_string, ".xml", NULL);
268 		*folderpos = 'f';
269 		*dotpos = '.';
270 
271 		oldname = g_build_filename (views_dir, filename, NULL);
272 		newname = g_build_filename (views_dir, newfile, NULL);
273 
274 		g_rename (oldname, newname);
275 
276 		g_checksum_free (checksum);
277 		g_free (oldname);
278 		g_free (newname);
279 		g_free (newfile);
280 	}
281 }
282 
283 static void
284 em_rename_folder_views (EShellBackend *shell_backend)
285 {
286 	const gchar *config_dir;
287 	gchar *views_dir;
288 	GDir *dir;
289 
290 	g_return_if_fail (shell_backend != NULL);
291 
292 	config_dir = e_shell_backend_get_config_dir (shell_backend);
293 	views_dir = g_build_filename (config_dir, "views", NULL);
294 
295 	dir = g_dir_open (views_dir, 0, NULL);
296 	if (dir) {
297 		GSList *to_rename = NULL;
298 		const gchar *filename;
299 
300 		while (filename = g_dir_read_name (dir), filename) {
301 			if (strstr (filename, "-folder:__") ||
302 			    strstr (filename, "-folder___"))
303 				to_rename = g_slist_prepend (to_rename, g_strdup (filename));
304 		}
305 
306 		g_dir_close (dir);
307 
308 		g_slist_foreach (to_rename, em_rename_view_in_folder, views_dir);
309 		g_slist_free_full (to_rename, g_free);
310 	}
311 
312 	g_free (views_dir);
313 }
314 
315 gboolean
316 e_mail_migrate (EShellBackend *shell_backend,
317                 gint major,
318                 gint minor,
319                 gint micro,
320                 GError **error)
321 {
322 	struct stat st;
323 	const gchar *data_dir;
324 
325 	/* make sure ~/.evolution/mail exists */
326 	data_dir = e_shell_backend_get_data_dir (shell_backend);
327 	if (g_stat (data_dir, &st) == -1) {
328 		if (errno != ENOENT || g_mkdir_with_parents (data_dir, 0700) == -1) {
329 			g_set_error (
330 				error, E_SHELL_MIGRATE_ERROR,
331 				E_SHELL_MIGRATE_ERROR_FAILED,
332 				_("Unable to create local mail folders at "
333 				"'%s': %s"), data_dir, g_strerror (errno));
334 			return FALSE;
335 		}
336 	}
337 
338 	if (major == 0)
339 		return emm_setup_initial (data_dir);
340 
341 	if (major <= 2 || (major == 3 && minor < 4))
342 		em_rename_folder_views (shell_backend);
343 
344 	return TRUE;
345 }