1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of version 2 of the GNU Lesser General Public
8
* License as published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this program; if not, write to the
17
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA.
23
#include <sys/types.h>
29
#include <glib/gstdio.h>
33
#define SUBFOLDER_DIR_NAME "subfolders"
34
#define SUBFOLDER_DIR_NAME_LEN 10
38
* @prefix: a prefix to prepend to the path, or %NULL
39
* @path: the virtual path to convert to a filesystem path.
41
* This converts the "virtual" path @path into an expanded form that
42
* allows a given name to refer to both a file and a directory. The
43
* expanded path will have a "subfolders" directory inserted between
44
* each path component. If the path ends with "/", the returned
45
* physical path will end with "/subfolders"
47
* If @prefix is non-%NULL, it will be prepended to the returned path.
49
* Return value: the expanded path
52
e_path_to_physical (const gchar *prefix, const gchar *vpath)
54
const gchar *p, *newp;
65
/* Calculate the length of the real path. */
66
ppath_len = strlen (vpath);
67
ppath_len++; /* For the ending zero. */
69
prefix_len = strlen (prefix);
70
ppath_len += prefix_len;
71
ppath_len++; /* For the separating slash. */
73
/* Take account of the fact that we need to translate every
74
* separator into `subfolders/'.
78
newp = strchr (p, '/');
82
ppath_len += SUBFOLDER_DIR_NAME_LEN;
83
ppath_len++; /* For the separating slash. */
85
/* Skip consecutive slashes. */
92
ppath = g_malloc (ppath_len);
95
memcpy (dp, prefix, prefix_len);
99
/* Copy the mangled path. */
102
newp = strchr (p, '/');
108
memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */
111
memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN);
112
dp += SUBFOLDER_DIR_NAME_LEN;
116
/* Skip consecutive slashes. */
127
find_folders_recursive (const gchar *physical_path, const gchar *path,
128
EPathFindFoldersCallback callback, gpointer data)
131
gchar *subfolder_directory_path;
135
if (!callback (physical_path, path, data))
138
subfolder_directory_path = g_strdup_printf ("%s/%s", physical_path, SUBFOLDER_DIR_NAME);
140
/* On the top level, we have no folders and,
141
* consequently, no subfolder directory.
144
subfolder_directory_path = g_strdup (physical_path);
147
/* Now scan the subfolders and load them. */
148
dir = g_dir_open (subfolder_directory_path, 0, NULL);
150
g_free (subfolder_directory_path);
156
struct stat file_stat;
161
dirent = g_dir_read_name (dir);
165
file_path = g_strdup_printf ("%s/%s", subfolder_directory_path,
168
if (g_stat (file_path, &file_stat) < 0 ||
169
! S_ISDIR (file_stat.st_mode)) {
174
new_path = g_strdup_printf ("%s/%s", path, dirent);
176
ok = find_folders_recursive (file_path, new_path, callback, data);
183
g_free (subfolder_directory_path);
189
* e_path_find_folders:
190
* @prefix: directory to start from
191
* @callback: Callback to invoke on each folder
192
* @data: Data for @callback
194
* Walks the folder tree starting at @prefix and calls @callback
197
* Return value: %TRUE on success, %FALSE if an error occurs at any point
200
e_path_find_folders (const gchar *prefix,
201
EPathFindFoldersCallback callback,
204
return find_folders_recursive (prefix, "", callback, data);
209
* @prefix: a prefix to prepend to the path, or %NULL
210
* @path: the virtual path to convert to a filesystem path.
212
* This removes the directory pointed to by @prefix and @path
213
* and attempts to remove its parent "subfolders" directory too
216
* Return value: -1 (with errno set) if it failed to rmdir the
217
* specified directory. 0 otherwise, whether or not it removed
218
* the parent directory.
221
e_path_rmdir (const gchar *prefix, const gchar *vpath)
223
gchar *physical_path, *p;
225
/* Remove the directory itself */
226
physical_path = e_path_to_physical (prefix, vpath);
227
if (g_rmdir (physical_path) == -1) {
228
g_free (physical_path);
232
/* Attempt to remove its parent "subfolders" directory,
233
* ignoring errors since it might not be empty.
236
p = strrchr (physical_path, '/');
238
g_free (physical_path);
242
p = strrchr (physical_path, '/');
243
if (!p || strcmp (p + 1, SUBFOLDER_DIR_NAME) != 0) {
244
g_free (physical_path);
248
g_rmdir (physical_path);
249
g_free (physical_path);