ftp://ftp.redhat.com/pub/redhat/linux/rawhide/SRPMS/SRPMS/gnome-vfs2-2.3.8-1.src.rpm
[gnome-vfs-httpcaptive.git] / monikers / bonobo-stream-vfs.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /**
3  * gnome-stream-vfs.c: Gnome VFS based stream implementation
4  *
5  * Author:
6  *   Michael Meeks <michael@helixcode.com>
7  *
8  * Copyright 2001, Ximian, Inc.
9  */
10
11 #include <config.h>
12 #include "bonobo-stream-vfs.h"
13
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <libgnomevfs/gnome-vfs-ops.h>
17 #include <stdio.h>
18 #include <sys/stat.h>
19
20 static BonoboObjectClass *bonobo_stream_vfs_parent_class;
21
22 void
23 bonobo_stream_vfs_storageinfo_from_file_info (Bonobo_StorageInfo *si,
24                                               GnomeVFSFileInfo   *fi)
25 {
26         g_return_if_fail (si != NULL);
27         g_return_if_fail (fi != NULL);
28
29         si->name = CORBA_string_dup (fi->name);
30
31         if (fi->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)
32                 si->size = fi->size;
33         else
34                 si->size = 0;
35
36         if (fi->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE &&
37             fi->type == GNOME_VFS_FILE_TYPE_DIRECTORY)
38                 si->type = Bonobo_STORAGE_TYPE_DIRECTORY;
39         else
40                 si->type = Bonobo_STORAGE_TYPE_REGULAR;
41
42         if (fi->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE &&
43             fi->mime_type)
44                 si->content_type = CORBA_string_dup (fi->mime_type);
45         else
46                 si->content_type = CORBA_string_dup ("");
47 }
48
49 static Bonobo_StorageInfo *
50 vfs_get_info (PortableServer_Servant          stream,
51               const Bonobo_StorageInfoFields  mask,
52               CORBA_Environment              *ev)
53 {
54         BonoboStreamVfs    *sfs = BONOBO_STREAM_VFS (
55                 bonobo_object (stream));
56         Bonobo_StorageInfo *si;
57         GnomeVFSFileInfo   *fi;
58         GnomeVFSResult      result;
59
60         if (mask & ~(Bonobo_FIELD_CONTENT_TYPE | Bonobo_FIELD_SIZE |
61                      Bonobo_FIELD_TYPE)) {
62                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
63                                      ex_Bonobo_Storage_NotSupported, NULL);
64                 return CORBA_OBJECT_NIL;
65         }
66
67         fi = gnome_vfs_file_info_new ();
68         result = gnome_vfs_get_file_info_from_handle (
69                 sfs->handle, fi,
70                 (mask & Bonobo_FIELD_CONTENT_TYPE) ?
71                 GNOME_VFS_FILE_INFO_GET_MIME_TYPE :
72                 GNOME_VFS_FILE_INFO_DEFAULT);
73
74         if (result != GNOME_VFS_OK) {
75                 if (result == GNOME_VFS_ERROR_ACCESS_DENIED)
76                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
77                                              ex_Bonobo_Stream_NoPermission, NULL);
78                 else
79                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
80                                              ex_Bonobo_Stream_IOError, NULL);
81                 return NULL;
82         }
83
84         si = Bonobo_StorageInfo__alloc ();
85
86         bonobo_stream_vfs_storageinfo_from_file_info (si, fi);
87
88         gnome_vfs_file_info_unref (fi);
89
90         return si;
91 }
92
93 static void
94 vfs_set_info (PortableServer_Servant          stream,
95               const Bonobo_StorageInfo       *info,
96               const Bonobo_StorageInfoFields  mask,
97               CORBA_Environment              *ev)
98 {
99         g_warning ("FIXME: set_info: a curious and not yet implemented API");
100         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
101                              ex_Bonobo_Stream_NotSupported, NULL);
102 }
103
104 static void
105 vfs_write (PortableServer_Servant     stream,
106            const Bonobo_Stream_iobuf *buffer,
107            CORBA_Environment         *ev)
108 {
109         BonoboStreamVfs *sfs = BONOBO_STREAM_VFS (
110                 bonobo_object (stream));
111         GnomeVFSResult   result;
112         GnomeVFSFileSize bytes_written;
113
114         do {
115                 result = gnome_vfs_write (sfs->handle, buffer->_buffer,
116                                           buffer->_length, &bytes_written);
117         } while (bytes_written < 1 && result == GNOME_VFS_ERROR_INTERRUPTED);
118
119         if (result != GNOME_VFS_OK)
120                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
121                                      ex_Bonobo_Stream_IOError, NULL);
122 }
123
124 static void
125 vfs_read (PortableServer_Servant stream,
126           CORBA_long             count,
127           Bonobo_Stream_iobuf  **buffer,
128           CORBA_Environment     *ev)
129 {
130         BonoboStreamVfs *sfs = BONOBO_STREAM_VFS (
131                 bonobo_object (stream));
132         GnomeVFSResult   result;
133         GnomeVFSFileSize bytes_read;
134         CORBA_octet     *data;
135
136         *buffer = Bonobo_Stream_iobuf__alloc ();
137         CORBA_sequence_set_release (*buffer, TRUE);
138
139         data = CORBA_sequence_CORBA_octet_allocbuf (count);
140
141         do {
142                 result = gnome_vfs_read (sfs->handle, data,
143                                          count, &bytes_read);
144         } while (bytes_read < 1 && result == GNOME_VFS_ERROR_INTERRUPTED);
145
146         if (result == GNOME_VFS_ERROR_EOF) {
147                 (*buffer)->_length = 0;
148                 (*buffer)->_buffer = NULL;
149                 CORBA_free (data);
150         } else if (result != GNOME_VFS_OK) {
151                 CORBA_free (data);
152                 CORBA_free (*buffer);
153                 *buffer = NULL;
154                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
155                                      ex_Bonobo_Stream_IOError, NULL);
156         } else {
157                 (*buffer)->_buffer = data;
158                 (*buffer)->_length = bytes_read;
159         }
160 }
161
162 static CORBA_long
163 vfs_seek (PortableServer_Servant stream,
164           CORBA_long             offset,
165           Bonobo_Stream_SeekType whence,
166           CORBA_Environment     *ev)
167 {
168         BonoboStreamVfs     *sfs = BONOBO_STREAM_VFS (
169                 bonobo_object (stream));
170         GnomeVFSSeekPosition pos;
171         GnomeVFSResult       result;
172         GnomeVFSFileOffset   where;
173         
174         switch (whence) {
175         case Bonobo_Stream_SeekCur:
176                 pos = GNOME_VFS_SEEK_CURRENT;
177                 break;
178         case Bonobo_Stream_SeekEnd:
179                 pos = GNOME_VFS_SEEK_END;
180                 break;
181         case Bonobo_Stream_SeekSet:
182                 pos = GNOME_VFS_SEEK_START;
183                 break;
184         default:
185                 g_warning ("Seek whence %d unknown; fall back to SEEK_SET",
186                            whence);
187                 pos = GNOME_VFS_SEEK_START;
188                 break;
189         }
190         
191         result = gnome_vfs_seek (sfs->handle, pos, offset);
192
193         if (result != GNOME_VFS_OK) {
194                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
195                                      ex_Bonobo_Stream_IOError, NULL);
196                 return -1;
197         }
198        
199         result = gnome_vfs_tell (sfs->handle, &where);
200         
201         if (result != GNOME_VFS_OK) {
202                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
203                                      ex_Bonobo_Stream_IOError, NULL);
204                 return -1;
205         }
206
207         return where;
208 }
209
210 static void
211 vfs_truncate (PortableServer_Servant stream,
212               const CORBA_long       new_size, 
213               CORBA_Environment     *ev)
214 {
215         BonoboStreamVfs *sfs = BONOBO_STREAM_VFS (
216                 bonobo_object (stream));
217         GnomeVFSResult result;
218
219         result = gnome_vfs_truncate_handle (sfs->handle, new_size);
220         if (result == GNOME_VFS_OK)
221                 return;
222
223         CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
224                              ex_Bonobo_Stream_NoPermission, NULL);
225 }
226
227 static void
228 vfs_commit (PortableServer_Servant stream,
229             CORBA_Environment     *ev)
230 {
231         CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
232                              ex_Bonobo_Stream_NotSupported, NULL);
233 }
234
235 static void
236 vfs_revert (PortableServer_Servant stream,
237             CORBA_Environment     *ev)
238 {
239         CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
240                              ex_Bonobo_Stream_NotSupported, NULL);
241 }
242         
243 static void
244 vfs_destroy (BonoboObject *object)
245 {
246         BonoboStreamVfs *sfs = BONOBO_STREAM_VFS (object);
247
248         if (sfs->handle)
249                 if (gnome_vfs_close (sfs->handle) != GNOME_VFS_OK)
250                         g_warning ("VFS Close failed");
251
252         sfs->handle = NULL;
253
254         bonobo_stream_vfs_parent_class->destroy (object);
255 }
256
257 static void
258 bonobo_stream_vfs_class_init (BonoboStreamVfsClass *klass)
259 {
260         POA_Bonobo_Stream__epv *epv = &klass->epv;
261         
262         bonobo_stream_vfs_parent_class = 
263                 g_type_class_peek_parent (klass);
264
265         epv->getInfo  = vfs_get_info;
266         epv->setInfo  = vfs_set_info;
267         epv->write    = vfs_write;
268         epv->read     = vfs_read;
269         epv->seek     = vfs_seek;
270         epv->truncate = vfs_truncate;
271         epv->commit   = vfs_commit;
272         epv->revert   = vfs_revert;
273
274         ((BonoboObjectClass *)klass)->destroy = vfs_destroy;
275 }
276
277 /**
278  * bonobo_stream_vfs_get_type:
279  *
280  * Returns the GtkType for the BonoboStreamVfs class.
281  */
282 GType
283 bonobo_stream_vfs_get_type (void)
284 {
285         static GType type = 0;
286
287         if (!type) {
288                 GTypeInfo info = {
289                         sizeof (BonoboStreamVfsClass),
290                         (GBaseInitFunc) NULL,
291                         (GBaseFinalizeFunc) NULL,
292                         (GClassInitFunc) bonobo_stream_vfs_class_init,
293                         NULL, /* class_finalize */
294                         NULL, /* class_data */
295                         sizeof (BonoboStreamVfs),
296                         0, /* n_preallocs */
297                         (GInstanceInitFunc) NULL
298                 };
299
300                 type = bonobo_type_unique (
301                         BONOBO_OBJECT_TYPE,
302                         POA_Bonobo_Stream__init, NULL,
303                         G_STRUCT_OFFSET (BonoboStreamVfsClass, epv),
304                         &info, "BonoboStreamVFS");
305         }
306
307         return type;
308 }
309
310 /**
311  * bonobo_stream_vfs_open:
312  * @path: The path to the file to be opened.
313  * @mode: The mode with which the file should be opened.
314  *
315  * Creates a new BonoboStream object for the filename specified by
316  * @path.  
317  */
318 BonoboStreamVfs *
319 bonobo_stream_vfs_open (const char *path, Bonobo_Storage_OpenMode mode, 
320                         CORBA_Environment *ev)
321 {
322         GnomeVFSResult   result;
323         GnomeVFSHandle  *handle;
324         GnomeVFSOpenMode vfs_mode = GNOME_VFS_OPEN_NONE;
325         BonoboStreamVfs *stream_vfs;
326
327         g_return_val_if_fail (path != NULL, NULL);
328
329         if (mode == Bonobo_Storage_READ)
330                 vfs_mode |= GNOME_VFS_OPEN_READ;
331
332         else if (mode == Bonobo_Storage_WRITE)
333                 vfs_mode |= GNOME_VFS_OPEN_WRITE;
334         
335         else {
336                 g_warning ("Unhandled open mode %d", mode);
337                 return NULL;
338         }
339         
340         result = gnome_vfs_open (&handle, path, vfs_mode);
341         if (vfs_mode & GNOME_VFS_OPEN_WRITE &&
342             result == GNOME_VFS_ERROR_NOT_FOUND)
343                 result = gnome_vfs_create (&handle, path, vfs_mode,
344                                            FALSE, S_IRUSR | S_IWUSR);
345         
346         if (result != GNOME_VFS_OK)
347                 return NULL;
348
349         stream_vfs = g_object_new (bonobo_stream_vfs_get_type (), NULL);
350         if (!stream_vfs)
351                 return NULL;
352         
353         stream_vfs->handle = handle;
354
355         return stream_vfs;
356 }