1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * bonobo-storage-fs.c: Sample file-system based Storage implementation
5 * This is just a sample file-system based Storage implementation.
6 * it is only used for debugging purposes
9 * Miguel de Icaza (miguel@gnu.org)
10 * Michael Meeks (michael@ximian.com)
12 * Copyright 2001, Ximian, Inc
16 #include "bonobo-storage-fs.h"
21 #include <sys/types.h>
26 #include <libgnomevfs/gnome-vfs-mime.h>
27 #include <bonobo/bonobo-storage.h>
29 #include "bonobo-stream-fs.h"
32 concat_dir_and_file (const char *dir, const char *file)
34 g_return_val_if_fail (dir != NULL, NULL);
35 g_return_val_if_fail (file != NULL, NULL);
37 /* If the directory name doesn't have a / on the end, we need
38 to add one so we get a proper path to the file */
39 if (dir[0] != '\0' && dir [strlen(dir) - 1] != '/')
40 return g_strconcat (dir, "/", file, NULL);
42 return g_strconcat (dir, file, NULL);
45 static BonoboObjectClass *bonobo_storage_fs_parent_class;
48 bonobo_storage_fs_finalize (GObject *object)
50 BonoboStorageFS *storage_fs = BONOBO_STORAGE_FS (object);
52 g_free (storage_fs->path);
53 storage_fs->path = NULL;
55 G_OBJECT_CLASS (bonobo_storage_fs_parent_class)->finalize (object);
58 static Bonobo_StorageInfo*
59 fs_get_info (PortableServer_Servant storage,
60 const CORBA_char *path,
61 const Bonobo_StorageInfoFields mask,
62 CORBA_Environment *ev)
64 BonoboStorageFS *storage_fs = BONOBO_STORAGE_FS (
65 bonobo_object (storage));
66 Bonobo_StorageInfo *si;
69 gboolean dangling = FALSE;
71 if (mask & ~(Bonobo_FIELD_CONTENT_TYPE | Bonobo_FIELD_SIZE |
73 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
74 ex_Bonobo_Storage_NotSupported, NULL);
75 return CORBA_OBJECT_NIL;
78 full = concat_dir_and_file (storage_fs->path, path);
79 if (stat (full, &st) == -1) {
80 if (lstat (full, &st) == -1)
86 si = Bonobo_StorageInfo__alloc ();
88 si->size = st.st_size;
89 si->name = CORBA_string_dup (path);
91 if (S_ISDIR (st.st_mode)) {
92 si->type = Bonobo_STORAGE_TYPE_DIRECTORY;
93 si->content_type = CORBA_string_dup ("x-directory/normal");
95 si->type = Bonobo_STORAGE_TYPE_REGULAR;
98 CORBA_string_dup ("x-symlink/dangling");
102 gnome_vfs_mime_type_from_name (full));
115 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
116 ex_Bonobo_Storage_NoPermission,
118 else if (errno == ENOENT)
119 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
120 ex_Bonobo_Storage_NotFound,
123 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
124 ex_Bonobo_Storage_IOError, NULL);
126 return CORBA_OBJECT_NIL;
130 fs_set_info (PortableServer_Servant storage,
131 const CORBA_char *path,
132 const Bonobo_StorageInfo *info,
133 const Bonobo_StorageInfoFields mask,
134 CORBA_Environment *ev)
136 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
137 ex_Bonobo_Storage_NotSupported,
142 fs_open_stream (PortableServer_Servant storage,
143 const CORBA_char *path,
144 Bonobo_Storage_OpenMode mode,
145 CORBA_Environment *ev)
147 BonoboStorageFS *storage_fs = BONOBO_STORAGE_FS (
148 bonobo_object (storage));
149 BonoboObject *stream;
152 full = concat_dir_and_file (storage_fs->path, path);
153 stream = BONOBO_OBJECT (
154 bonobo_stream_fs_open (full, mode, 0644, ev));
157 return CORBA_Object_duplicate (
158 BONOBO_OBJREF (stream), ev);
161 static Bonobo_Storage
162 fs_open_storage (PortableServer_Servant storage,
163 const CORBA_char *path,
164 Bonobo_Storage_OpenMode mode,
165 CORBA_Environment *ev)
167 BonoboStorageFS *storage_fs = BONOBO_STORAGE_FS (
168 bonobo_object (storage));
169 BonoboObject *new_storage;
172 full = concat_dir_and_file (storage_fs->path, path);
173 new_storage = BONOBO_OBJECT (
174 bonobo_storage_fs_open (full, mode, 0644, ev));
177 return CORBA_Object_duplicate (
178 BONOBO_OBJREF (new_storage), ev);
182 fs_copy_to (PortableServer_Servant storage,
184 CORBA_Environment *ev)
186 BonoboStorageFS *storage_fs = BONOBO_STORAGE_FS (
187 bonobo_object (storage));
189 bonobo_storage_copy_to (
190 BONOBO_OBJREF (storage_fs), dest, ev);
194 fs_rename (PortableServer_Servant storage,
195 const CORBA_char *path,
196 const CORBA_char *new_path,
197 CORBA_Environment *ev)
199 BonoboStorageFS *storage_fs = BONOBO_STORAGE_FS (
200 bonobo_object (storage));
201 char *full_old, *full_new;
203 full_old = concat_dir_and_file (storage_fs->path, path);
204 full_new = concat_dir_and_file (storage_fs->path, new_path);
206 if (rename (full_old, full_new) == -1) {
208 if ((errno == EACCES) || (errno == EPERM) || (errno == EROFS))
209 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
210 ex_Bonobo_Storage_NoPermission,
212 else if (errno == ENOENT)
213 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
214 ex_Bonobo_Storage_NotFound,
216 else if ((errno == EEXIST) || (errno == ENOTEMPTY))
217 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
218 ex_Bonobo_Storage_NameExists,
221 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
222 ex_Bonobo_Storage_IOError,
231 fs_commit (PortableServer_Servant storage,
232 CORBA_Environment *ev)
234 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
235 ex_Bonobo_Stream_NotSupported, NULL);
239 fs_revert (PortableServer_Servant storage,
240 CORBA_Environment *ev)
242 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
243 ex_Bonobo_Stream_NotSupported, NULL);
246 static Bonobo_Storage_DirectoryList *
247 fs_list_contents (PortableServer_Servant storage,
248 const CORBA_char *path,
249 Bonobo_StorageInfoFields mask,
250 CORBA_Environment *ev)
252 BonoboStorageFS *storage_fs = BONOBO_STORAGE_FS (
253 bonobo_object (storage));
254 Bonobo_Storage_DirectoryList *list = NULL;
255 Bonobo_StorageInfo *buf;
259 gint i, max, v, num_entries = 0;
262 if (mask & ~(Bonobo_FIELD_CONTENT_TYPE | Bonobo_FIELD_SIZE |
263 Bonobo_FIELD_TYPE)) {
264 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
265 ex_Bonobo_Storage_NotSupported, NULL);
266 return CORBA_OBJECT_NIL;
269 if (!(dir = opendir (storage_fs->path)))
270 goto list_contents_except;
272 for (max = 0; readdir (dir); max++)
277 buf = CORBA_sequence_Bonobo_StorageInfo_allocbuf (max);
278 list = Bonobo_Storage_DirectoryList__alloc();
280 CORBA_sequence_set_release (list, TRUE);
282 for (i = 0; (de = readdir (dir)) && (i < max); i++) {
284 if ((de->d_name[0] == '.' && de->d_name[1] == '\0') ||
285 (de->d_name[0] == '.' && de->d_name[1] == '.'
286 && de->d_name[2] == '\0')) {
288 continue; /* Ignore . and .. */
291 buf [i].name = CORBA_string_dup (de->d_name);
293 buf [i].content_type = NULL;
295 full = concat_dir_and_file (storage_fs->path, de->d_name);
296 v = stat (full, &st);
300 * The stat failed -- two common cases are where
301 * the file was removed between the call to readdir
302 * and the iteration, and where the file is a dangling
305 if (errno == ENOENT || errno == ELOOP) {
306 v = lstat (full, &st);
308 /* FIXME - x-symlink/dangling is odd */
309 buf [i].size = st.st_size;
310 buf [i].type = Bonobo_STORAGE_TYPE_REGULAR;
311 buf [i].content_type =
312 CORBA_string_dup ("x-symlink/dangling");
319 /* Unless it's something grave, just skip the file */
320 if (errno != ENOMEM && errno != EFAULT && errno != ENOTDIR) {
326 goto list_contents_except;
329 buf [i].size = st.st_size;
331 if (S_ISDIR (st.st_mode)) {
332 buf [i].type = Bonobo_STORAGE_TYPE_DIRECTORY;
333 buf [i].content_type =
334 CORBA_string_dup ("x-directory/normal");
336 buf [i].type = Bonobo_STORAGE_TYPE_REGULAR;
337 buf [i].content_type =
339 gnome_vfs_mime_type_from_name (full));
347 list->_length = num_entries;
353 list_contents_except:
365 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
366 ex_Bonobo_Storage_NotFound,
368 else if (errno == ENOTDIR)
369 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
370 ex_Bonobo_Storage_NotStorage,
373 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
374 ex_Bonobo_Storage_IOError, NULL);
376 return CORBA_OBJECT_NIL;
380 fs_erase (PortableServer_Servant storage,
381 const CORBA_char *path,
382 CORBA_Environment *ev)
384 BonoboStorageFS *storage_fs = BONOBO_STORAGE_FS (
385 bonobo_object (storage));
388 full = concat_dir_and_file (storage_fs->path, path);
390 if (remove (full) == -1) {
393 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
394 ex_Bonobo_Storage_NotFound,
396 else if (errno == ENOTEMPTY || errno == EEXIST)
397 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
398 ex_Bonobo_Storage_NotEmpty,
400 else if (errno == EACCES || errno == EPERM)
401 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
402 ex_Bonobo_Storage_NoPermission,
405 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
406 ex_Bonobo_Storage_IOError, NULL);
413 bonobo_storage_fs_class_init (BonoboStorageFSClass *klass)
415 GObjectClass *object_class = (GObjectClass *) klass;
417 POA_Bonobo_Storage__epv *epv = &klass->epv;
419 bonobo_storage_fs_parent_class =
420 g_type_class_peek_parent (klass);
422 epv->getInfo = fs_get_info;
423 epv->setInfo = fs_set_info;
424 epv->openStream = fs_open_stream;
425 epv->openStorage = fs_open_storage;
426 epv->copyTo = fs_copy_to;
427 epv->rename = fs_rename;
428 epv->commit = fs_commit;
429 epv->revert = fs_revert;
430 epv->listContents = fs_list_contents;
431 epv->erase = fs_erase;
433 object_class->finalize = bonobo_storage_fs_finalize;
438 bonobo_storage_fs_init (GObject *object)
443 BONOBO_TYPE_FUNC_FULL (BonoboStorageFS,
445 bonobo_object_get_type (),
449 * bonobo_storage_fs_open:
450 * @path: path to existing directory that represents the storage
451 * @flags: open flags.
452 * @mode: mode used if @flags containst Bonobo_Storage_CREATE for the storage.
454 * Returns a BonoboStorage object that represents the storage at @path
457 bonobo_storage_fs_open (const char *path, gint flags,
458 gint mode, CORBA_Environment *ev)
460 BonoboStorageFS *storage_fs;
463 g_return_val_if_fail (path != NULL, NULL);
464 g_return_val_if_fail (ev != NULL, NULL);
466 /* Most storages are files */
469 if ((flags & Bonobo_Storage_CREATE) &&
470 (mkdir (path, mode) == -1) && (errno != EEXIST)) {
473 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
474 ex_Bonobo_Storage_NoPermission,
477 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
478 ex_Bonobo_Storage_IOError, NULL);
482 if (stat (path, &st) == -1) {
485 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
486 ex_Bonobo_Storage_NotFound,
489 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
490 ex_Bonobo_Storage_IOError,
495 if (!S_ISDIR (st.st_mode)) {
496 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
497 ex_Bonobo_Storage_NotStorage, NULL);
501 storage_fs = g_object_new (bonobo_storage_fs_get_type (), NULL);
502 storage_fs->path = g_strdup (path);