~ubuntu-branches/ubuntu/oneiric/gconf/oneiric-proposed

« back to all changes in this revision

Viewing changes to backends/dir-utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Takuo KITAME
  • Date: 2002-03-17 01:51:39 UTC
  • Revision ID: james.westby@ubuntu.com-20020317015139-z4f8fdg1hoe049g0
Tags: upstream-1.0.9
ImportĀ upstreamĀ versionĀ 1.0.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * GConf BerkeleyDB back-end
 
3
 *
 
4
 * Copyright (C) 2000 Sun Microsystems Inc
 
5
 * Contributed to the GConf project.
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Library General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Library General Public
 
18
 * License along with this library; if not, write to the
 
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
 * Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include <sys/stat.h>
 
24
#include <sys/types.h>
 
25
#include <fcntl.h>
 
26
#include <errno.h>
 
27
#include <dirent.h>
 
28
 
 
29
#include <gconf/gconf-backend.h>
 
30
#include <gconf/gconf-internals.h>
 
31
#include <gconf/gconf.h>
 
32
 
 
33
/* mode_to_to_mode: copied from xml-dir.c - needs to be a common utility */
 
34
guint
 
35
mode_t_to_mode(mode_t orig)
 
36
{
 
37
  guint mode = 0;
 
38
 
 
39
  if (orig & S_IRUSR)
 
40
    mode |= 0400;
 
41
 
 
42
  if (orig & S_IWUSR)
 
43
    mode |= 0200;
 
44
 
 
45
  if (orig & S_IXUSR)
 
46
    mode |= 0100;
 
47
 
 
48
  if (orig & S_IRGRP)
 
49
    mode |= 0040;
 
50
 
 
51
  if (orig & S_IWGRP)
 
52
    mode |= 0020;
 
53
 
 
54
  if (orig & S_IXGRP)
 
55
    mode |= 0010;
 
56
 
 
57
  if (orig & S_IROTH)
 
58
    mode |= 0004;
 
59
 
 
60
  if (orig & S_IWOTH)
 
61
    mode |= 0002;
 
62
 
 
63
  if (orig & S_IXOTH)
 
64
    mode |= 0001;
 
65
  
 
66
  return mode;
 
67
}
 
68
 
 
69
static void
 
70
free_list_element (gpointer data, gpointer user_data)
 
71
{
 
72
  g_free (data);
 
73
}
 
74
 
 
75
/* g_free()s each element's data, then free's the list */
 
76
void
 
77
_gconf_slist_free_all (GSList * list)
 
78
{
 
79
  if (!list)
 
80
    return;
 
81
  g_slist_foreach (list, free_list_element, NULL);
 
82
  g_slist_free (list);
 
83
}
 
84
 
 
85
/* NOTE: body of _gconf_get_root_dir() is taken directly from initial code in
 
86
   xml-backend.c:resolve_address() */
 
87
 
 
88
/* parses root directory of a file-based GConf database and checks
 
89
 * directory existence/writeability/locking
 
90
 */
 
91
char *
 
92
_gconf_get_root_dir (const char *address, guint * pflags,
 
93
                     const gchar * dbtype, GError ** err)
 
94
{
 
95
  gchar *root_dir;
 
96
  guint len;
 
97
  guint dir_mode = 0700;
 
98
  guint file_mode = 0600;
 
99
  gint flags = 0;
 
100
  GConfLock *lock = NULL;
 
101
 
 
102
  root_dir = gconf_address_resource (address);
 
103
 
 
104
  if (root_dir == NULL)
 
105
    {
 
106
      gconf_set_error (err, GCONF_ERROR_BAD_ADDRESS,
 
107
                       _
 
108
                       ("Couldn't find the %s root directory in the address `%s'"),
 
109
                       dbtype, address);
 
110
      return NULL;
 
111
    }
 
112
 
 
113
  /* Chop trailing '/' to canonicalize */
 
114
  len = strlen (root_dir);
 
115
 
 
116
  if (root_dir[len - 1] == '/')
 
117
    root_dir[len - 1] = '\0';
 
118
 
 
119
  if (mkdir (root_dir, dir_mode) < 0)
 
120
    {
 
121
      if (errno != EEXIST)
 
122
        {
 
123
          gconf_set_error (err, GCONF_ERROR_FAILED,
 
124
                           _("Could not make directory `%s': %s"),
 
125
                           (gchar *) root_dir, strerror (errno));
 
126
          g_free (root_dir);
 
127
          return NULL;
 
128
        }
 
129
      else
 
130
        {
 
131
          /* Already exists, base our dir_mode on it */
 
132
          struct stat statbuf;
 
133
          if (stat (root_dir, &statbuf) == 0)
 
134
            {
 
135
              dir_mode = mode_t_to_mode (statbuf.st_mode);
 
136
              /* dir_mode without search bits */
 
137
              file_mode = dir_mode & (~0111);
 
138
            }
 
139
        }
 
140
    }
 
141
 
 
142
  {
 
143
    /* See if we're writeable */
 
144
    gboolean writeable = FALSE;
 
145
    int fd;
 
146
    gchar *testfile;
 
147
 
 
148
    testfile = g_strconcat (root_dir, "/.testing.writeability", NULL);
 
149
 
 
150
    fd = open (testfile, O_CREAT | O_WRONLY, S_IRWXU);
 
151
 
 
152
    if (fd >= 0)
 
153
      {
 
154
        writeable = TRUE;
 
155
        close (fd);
 
156
      }
 
157
 
 
158
    unlink (testfile);
 
159
 
 
160
    g_free (testfile);
 
161
 
 
162
    if (writeable)
 
163
      flags |= GCONF_SOURCE_ALL_WRITEABLE;
 
164
 
 
165
    /* We only do locking if it's writeable,
 
166
       which is sort of broken but close enough
 
167
     */
 
168
    if (writeable)
 
169
      {
 
170
        gchar *lockdir;
 
171
 
 
172
        lockdir = gconf_concat_dir_and_key (root_dir, "%gconf-backend.lock");
 
173
 
 
174
        lock = gconf_get_lock (lockdir, err);
 
175
 
 
176
        if (lock != NULL)
 
177
          gconf_log (GCL_DEBUG, "Acquired %s lock directory `%s'", dbtype,
 
178
                     lockdir);
 
179
 
 
180
        g_free (lockdir);
 
181
 
 
182
        if (lock == NULL)
 
183
          {
 
184
            g_free (root_dir);
 
185
            return NULL;
 
186
          }
 
187
      }
 
188
  }
 
189
 
 
190
  {
 
191
    /* see if we're readable */
 
192
    gboolean readable = FALSE;
 
193
    DIR *d;
 
194
 
 
195
    d = opendir (root_dir);
 
196
 
 
197
    if (d != NULL)
 
198
      {
 
199
        readable = TRUE;
 
200
        closedir (d);
 
201
      }
 
202
 
 
203
    if (readable)
 
204
      flags |= GCONF_SOURCE_ALL_READABLE;
 
205
  }
 
206
 
 
207
  if (!(flags & GCONF_SOURCE_ALL_READABLE) &&
 
208
      !(flags & GCONF_SOURCE_ALL_WRITEABLE))
 
209
    {
 
210
      gconf_set_error (err, GCONF_ERROR_BAD_ADDRESS,
 
211
                       _
 
212
                       ("Can't read from or write to the %s root directory in the address `%s'"),
 
213
                       dbtype, address);
 
214
      g_free (root_dir);
 
215
      return NULL;
 
216
    }
 
217
  *pflags = flags;
 
218
 
 
219
  return root_dir;
 
220
}