~ubuntu-branches/ubuntu/maverick/evolution-data-server/maverick-proposed

« back to all changes in this revision

Viewing changes to servers/exchange/lib/e2k-path.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-05-17 17:02:06 UTC
  • mfrom: (1.1.79 upstream) (1.6.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20100517170206-4ufr52vwrhh26yh0
Tags: 2.30.1-1ubuntu1
* Merge from debian experimental. Remaining change:
  (LP: #42199, #229669, #173703, #360344, #508494)
  + debian/control:
    - add Vcs-Bzr tag
    - don't use libgnome
    - Use Breaks instead of Conflicts against evolution 2.25 and earlier.
  + debian/evolution-data-server.install,
    debian/patches/45_libcamel_providers_version.patch:
    - use the upstream versioning, not a Debian-specific one 
  + debian/libedata-book1.2-dev.install, debian/libebackend-1.2-dev.install,
    debian/libcamel1.2-dev.install, debian/libedataserverui1.2-dev.install:
    - install html documentation
  + debian/rules:
    - don't build documentation it's shipped with the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
 
/* e-path.c
3
 
 *
4
 
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
5
 
 *
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.
9
 
 *
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.
14
 
 *
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.
19
 
 */
20
 
 
21
 
#include <config.h>
22
 
 
23
 
#include <sys/types.h>
24
 
#include <string.h>
25
 
#include <sys/stat.h>
26
 
#include <unistd.h>
27
 
 
28
 
#include <glib.h>
29
 
#include <glib/gstdio.h>
30
 
 
31
 
#include "e2k-path.h"
32
 
 
33
 
#define SUBFOLDER_DIR_NAME     "subfolders"
34
 
#define SUBFOLDER_DIR_NAME_LEN 10
35
 
 
36
 
/**
37
 
 * e_path_to_physical:
38
 
 * @prefix: a prefix to prepend to the path, or %NULL
39
 
 * @path: the virtual path to convert to a filesystem path.
40
 
 *
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"
46
 
 *
47
 
 * If @prefix is non-%NULL, it will be prepended to the returned path.
48
 
 *
49
 
 * Return value: the expanded path
50
 
 **/
51
 
gchar *
52
 
e_path_to_physical (const gchar *prefix, const gchar *vpath)
53
 
{
54
 
        const gchar *p, *newp;
55
 
        gchar *dp;
56
 
        gchar *ppath;
57
 
        gint ppath_len;
58
 
        gint prefix_len;
59
 
 
60
 
        while (*vpath == '/')
61
 
                vpath++;
62
 
        if (!prefix)
63
 
                prefix = "";
64
 
 
65
 
        /* Calculate the length of the real path. */
66
 
        ppath_len = strlen (vpath);
67
 
        ppath_len++;    /* For the ending zero.  */
68
 
 
69
 
        prefix_len = strlen (prefix);
70
 
        ppath_len += prefix_len;
71
 
        ppath_len++;    /* For the separating slash.  */
72
 
 
73
 
        /* Take account of the fact that we need to translate every
74
 
         * separator into `subfolders/'.
75
 
         */
76
 
        p = vpath;
77
 
        while (1) {
78
 
                newp = strchr (p, '/');
79
 
                if (newp == NULL)
80
 
                        break;
81
 
 
82
 
                ppath_len += SUBFOLDER_DIR_NAME_LEN;
83
 
                ppath_len++; /* For the separating slash.  */
84
 
 
85
 
                /* Skip consecutive slashes.  */
86
 
                while (*newp == '/')
87
 
                        newp++;
88
 
 
89
 
                p = newp;
90
 
        };
91
 
 
92
 
        ppath = g_malloc (ppath_len);
93
 
        dp = ppath;
94
 
 
95
 
        memcpy (dp, prefix, prefix_len);
96
 
        dp += prefix_len;
97
 
        *(dp++) = '/';
98
 
 
99
 
        /* Copy the mangled path.  */
100
 
        p = vpath;
101
 
        while (1) {
102
 
                newp = strchr (p, '/');
103
 
                if (newp == NULL) {
104
 
                        strcpy (dp, p);
105
 
                        break;
106
 
                }
107
 
 
108
 
                memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too.  */
109
 
                dp += newp - p + 1;
110
 
 
111
 
                memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN);
112
 
                dp += SUBFOLDER_DIR_NAME_LEN;
113
 
 
114
 
                *(dp++) = '/';
115
 
 
116
 
                /* Skip consecutive slashes.  */
117
 
                while (*newp == '/')
118
 
                        newp++;
119
 
 
120
 
                p = newp;
121
 
        }
122
 
 
123
 
        return ppath;
124
 
}
125
 
 
126
 
static gboolean
127
 
find_folders_recursive (const gchar *physical_path, const gchar *path,
128
 
                        EPathFindFoldersCallback callback, gpointer data)
129
 
{
130
 
        GDir *dir;
131
 
        gchar *subfolder_directory_path;
132
 
        gboolean ok;
133
 
 
134
 
        if (*path) {
135
 
                if (!callback (physical_path, path, data))
136
 
                        return FALSE;
137
 
 
138
 
                subfolder_directory_path = g_strdup_printf ("%s/%s", physical_path, SUBFOLDER_DIR_NAME);
139
 
        } else {
140
 
                /* On the top level, we have no folders and,
141
 
                 * consequently, no subfolder directory.
142
 
                 */
143
 
 
144
 
                subfolder_directory_path = g_strdup (physical_path);
145
 
        }
146
 
 
147
 
        /* Now scan the subfolders and load them. */
148
 
        dir = g_dir_open (subfolder_directory_path, 0, NULL);
149
 
        if (dir == NULL) {
150
 
                g_free (subfolder_directory_path);
151
 
                return TRUE;
152
 
        }
153
 
 
154
 
        ok = TRUE;
155
 
        while (ok) {
156
 
                struct stat file_stat;
157
 
                const gchar *dirent;
158
 
                gchar *file_path;
159
 
                gchar *new_path;
160
 
 
161
 
                dirent = g_dir_read_name (dir);
162
 
                if (dirent == NULL)
163
 
                        break;
164
 
 
165
 
                file_path = g_strdup_printf ("%s/%s", subfolder_directory_path,
166
 
                                             dirent);
167
 
 
168
 
                if (g_stat (file_path, &file_stat) < 0 ||
169
 
                    ! S_ISDIR (file_stat.st_mode)) {
170
 
                        g_free (file_path);
171
 
                        continue;
172
 
                }
173
 
 
174
 
                new_path = g_strdup_printf ("%s/%s", path, dirent);
175
 
 
176
 
                ok = find_folders_recursive (file_path, new_path, callback, data);
177
 
 
178
 
                g_free (file_path);
179
 
                g_free (new_path);
180
 
        }
181
 
 
182
 
        g_dir_close (dir);
183
 
        g_free (subfolder_directory_path);
184
 
 
185
 
        return ok;
186
 
}
187
 
 
188
 
/**
189
 
 * e_path_find_folders:
190
 
 * @prefix: directory to start from
191
 
 * @callback: Callback to invoke on each folder
192
 
 * @data: Data for @callback
193
 
 *
194
 
 * Walks the folder tree starting at @prefix and calls @callback
195
 
 * on each folder.
196
 
 *
197
 
 * Return value: %TRUE on success, %FALSE if an error occurs at any point
198
 
 **/
199
 
gboolean
200
 
e_path_find_folders (const gchar *prefix,
201
 
                     EPathFindFoldersCallback callback,
202
 
                     gpointer data)
203
 
{
204
 
        return find_folders_recursive (prefix, "", callback, data);
205
 
}
206
 
 
207
 
/**
208
 
 * e_path_rmdir:
209
 
 * @prefix: a prefix to prepend to the path, or %NULL
210
 
 * @path: the virtual path to convert to a filesystem path.
211
 
 *
212
 
 * This removes the directory pointed to by @prefix and @path
213
 
 * and attempts to remove its parent "subfolders" directory too
214
 
 * if it's empty.
215
 
 *
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.
219
 
 **/
220
 
gint
221
 
e_path_rmdir (const gchar *prefix, const gchar *vpath)
222
 
{
223
 
        gchar *physical_path, *p;
224
 
 
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);
229
 
                return -1;
230
 
        }
231
 
 
232
 
        /* Attempt to remove its parent "subfolders" directory,
233
 
         * ignoring errors since it might not be empty.
234
 
         */
235
 
 
236
 
        p = strrchr (physical_path, '/');
237
 
        if (p[1] == '\0') {
238
 
                g_free (physical_path);
239
 
                return 0;
240
 
        }
241
 
        *p = '\0';
242
 
        p = strrchr (physical_path, '/');
243
 
        if (!p || strcmp (p + 1, SUBFOLDER_DIR_NAME) != 0) {
244
 
                g_free (physical_path);
245
 
                return 0;
246
 
        }
247
 
 
248
 
        g_rmdir (physical_path);
249
 
        g_free (physical_path);
250
 
        return 0;
251
 
}