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-fs.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /**
3  * bonobo-stream-fs.c: Sample file-system based Stream implementation
4  *
5  * This is just a sample file-system based Stream implementation.
6  * it is only used for debugging purposes
7  *
8  * Authors:
9  *   Miguel de Icaza (miguel@gnu.org)
10  *   Michael Meeks   (michael@ximian.com)
11  *
12  * Copyright 2001, Ximian, Inc
13  */
14 #include <config.h>
15 #include "bonobo-stream-fs.h"
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <errno.h>
21 #include <libgnomevfs/gnome-vfs-mime.h>
22
23 struct _BonoboStreamFSPrivate {
24         gchar *mime_type;
25 };
26
27 static BonoboObjectClass *bonobo_stream_fs_parent_class;
28
29 static gint
30 bonobo_mode_to_fs (Bonobo_Storage_OpenMode mode)
31 {
32         gint fs_mode = 0;
33
34         if (mode & Bonobo_Storage_READ)
35                 fs_mode |= O_RDONLY;
36         if (mode & Bonobo_Storage_WRITE)
37                 fs_mode |= O_RDWR;
38         if (mode & Bonobo_Storage_CREATE)
39                 fs_mode |= O_CREAT | O_RDWR;
40         if (mode & Bonobo_Storage_FAILIFEXIST)
41                 fs_mode |= O_EXCL;
42
43         return fs_mode;
44 }
45
46 static Bonobo_StorageInfo*
47 fs_get_info (PortableServer_Servant         stream,
48              const Bonobo_StorageInfoFields mask,
49              CORBA_Environment             *ev)
50 {
51         BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (
52                 bonobo_object (stream));
53         Bonobo_StorageInfo *si;
54         struct stat st;
55
56         if (mask & ~(Bonobo_FIELD_CONTENT_TYPE | Bonobo_FIELD_SIZE |
57                      Bonobo_FIELD_TYPE)) {
58                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
59                                      ex_Bonobo_Storage_NotSupported, NULL);
60                 return CORBA_OBJECT_NIL;
61         }
62
63         if (fstat (stream_fs->fd, &st) == -1)
64                 goto get_info_except;
65                 
66         si = Bonobo_StorageInfo__alloc ();
67
68         si->size = st.st_size;
69         si->type = Bonobo_STORAGE_TYPE_REGULAR;
70         si->name = CORBA_string_dup ("");
71         si->content_type = CORBA_string_dup (stream_fs->priv->mime_type);
72
73         return si;
74
75  get_info_except:
76
77         if (errno == EACCES) 
78                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
79                                      ex_Bonobo_Stream_NoPermission, NULL);
80         else 
81                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
82                                      ex_Bonobo_Stream_IOError, NULL);
83         
84
85         return CORBA_OBJECT_NIL;
86 }
87
88 static void
89 fs_set_info (PortableServer_Servant         stream,
90              const Bonobo_StorageInfo      *info,
91              const Bonobo_StorageInfoFields mask,
92              CORBA_Environment             *ev)
93 {
94         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
95                              ex_Bonobo_Stream_NotSupported, NULL);
96 }
97
98 static void
99 fs_write (PortableServer_Servant     stream,
100           const Bonobo_Stream_iobuf *buffer,
101           CORBA_Environment         *ev)
102 {
103         BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (
104                 bonobo_object (stream));
105
106         errno = EINTR;
107         while ((write (stream_fs->fd, buffer->_buffer, buffer->_length) == -1)
108                && (errno == EINTR));
109
110         if (errno == EINTR) return;
111
112         if ((errno == EBADF) || (errno == EINVAL))
113                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
114                                      ex_Bonobo_Stream_NoPermission, NULL);
115         else 
116                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
117                                      ex_Bonobo_Stream_IOError, NULL);
118 }
119
120 static void
121 fs_read (PortableServer_Servant stream,
122          CORBA_long             count,
123          Bonobo_Stream_iobuf  **buffer,
124          CORBA_Environment     *ev)
125 {
126         BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (
127                 bonobo_object (stream));
128         CORBA_octet *data;
129         int bytes_read;
130         
131         if (count < 0) {
132                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
133                                      ex_Bonobo_Stream_IOError, NULL);
134                 return;
135         }
136
137         *buffer = Bonobo_Stream_iobuf__alloc ();
138         CORBA_sequence_set_release (*buffer, TRUE);
139         data = CORBA_sequence_CORBA_octet_allocbuf (count);
140         (*buffer)->_buffer = data;
141         (*buffer)->_length = 0;
142
143         do {
144                 bytes_read = read (stream_fs->fd, data, count);
145         } while ((bytes_read == -1) && (errno == EINTR));
146
147
148         if (bytes_read == -1) {
149                 CORBA_free (*buffer);
150                 *buffer = NULL;
151
152                 if (errno == EACCES) 
153                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
154                                              ex_Bonobo_Stream_NoPermission, 
155                                              NULL);
156                 else 
157                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
158                                              ex_Bonobo_Stream_IOError, NULL);
159         } else
160                 (*buffer)->_length = bytes_read;
161 }
162
163 static CORBA_long
164 fs_seek (PortableServer_Servant stream,
165          CORBA_long             offset, 
166          Bonobo_Stream_SeekType whence,
167          CORBA_Environment     *ev)
168 {
169         BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (
170                 bonobo_object (stream));
171         int fs_whence;
172         CORBA_long pos;
173
174         if (whence == Bonobo_Stream_SeekCur)
175                 fs_whence = SEEK_CUR;
176         else if (whence == Bonobo_Stream_SeekEnd)
177                 fs_whence = SEEK_END;
178         else
179                 fs_whence = SEEK_SET;
180
181         if ((pos = lseek (stream_fs->fd, offset, fs_whence)) == -1) {
182
183                 if (errno == ESPIPE) 
184                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
185                                              ex_Bonobo_Stream_NotSupported, 
186                                              NULL);
187                 else
188                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
189                                              ex_Bonobo_Stream_IOError, NULL);
190                 return 0;
191         }
192
193         return pos;
194 }
195
196 static void
197 fs_truncate (PortableServer_Servant stream,
198              const CORBA_long       new_size, 
199              CORBA_Environment     *ev)
200 {
201         BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (
202                 bonobo_object (stream));
203
204         if (ftruncate (stream_fs->fd, new_size) == 0)
205                 return;
206
207         if (errno == EACCES)
208                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
209                                      ex_Bonobo_Stream_NoPermission, NULL);
210         else 
211                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
212                                      ex_Bonobo_Stream_IOError, NULL);
213 }
214
215 static void
216 fs_commit (PortableServer_Servant stream,
217            CORBA_Environment     *ev)
218 {
219         CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
220                              ex_Bonobo_Stream_NotSupported, NULL);
221 }
222
223 static void
224 fs_revert (PortableServer_Servant stream,
225            CORBA_Environment     *ev)
226 {
227         CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
228                              ex_Bonobo_Stream_NotSupported, NULL);
229 }
230
231 static void
232 fs_destroy (BonoboObject *object)
233 {
234         BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (object);
235         
236         if (stream_fs->fd >= 0 &&
237             close (stream_fs->fd))
238                 g_warning ("Close failed");
239         stream_fs->fd = -1;
240
241         if (stream_fs->path)
242                 g_free (stream_fs->path);
243         stream_fs->path = NULL;
244
245         if (stream_fs->priv->mime_type)
246                 g_free (stream_fs->priv->mime_type);
247         stream_fs->priv->mime_type = NULL;
248
249         bonobo_stream_fs_parent_class->destroy (object);
250 }
251
252 static void
253 fs_finalize (GObject *object)
254 {
255         BonoboStreamFS *stream_fs = BONOBO_STREAM_FS (object);
256         
257         if (stream_fs->priv)
258                 g_free (stream_fs->priv);
259         stream_fs->priv = NULL;
260
261         bonobo_stream_fs_parent_class->parent_class.finalize (object);
262 }
263
264 static void
265 bonobo_stream_fs_class_init (BonoboStreamFSClass *klass)
266 {
267         GObjectClass    *oclass = (GObjectClass *) klass;
268         POA_Bonobo_Stream__epv *epv = &klass->epv;
269         
270         bonobo_stream_fs_parent_class = 
271                 g_type_class_peek_parent (klass);
272
273         epv->getInfo  = fs_get_info;
274         epv->setInfo  = fs_set_info;
275         epv->write    = fs_write;
276         epv->read     = fs_read;
277         epv->seek     = fs_seek;
278         epv->truncate = fs_truncate;
279         epv->commit   = fs_commit;
280         epv->revert   = fs_revert;
281
282         oclass->finalize = fs_finalize;
283         ((BonoboObjectClass *)oclass)->destroy = fs_destroy;
284 }
285
286 static void
287 bonobo_stream_fs_init (BonoboStreamFS *stream_fs)
288 {
289         stream_fs->priv = g_new0 (BonoboStreamFSPrivate,1);
290         stream_fs->priv->mime_type = NULL;
291 }
292
293 /**
294  * bonobo_stream_fs_get_type:
295  *
296  * Returns the GType for the BonoboStreamFS class.
297  */
298 GType
299 bonobo_stream_fs_get_type (void)
300 {
301         static GType type = 0;
302
303         if (!type) {
304                 GTypeInfo info = {
305                         sizeof (BonoboStreamFSClass),
306                         (GBaseInitFunc) NULL,
307                         (GBaseFinalizeFunc) NULL,
308                         (GClassInitFunc) bonobo_stream_fs_class_init,
309                         NULL, /* class_finalize */
310                         NULL, /* class_data */
311                         sizeof (BonoboStreamFS),
312                         0, /* n_preallocs */
313                         (GInstanceInitFunc) bonobo_stream_fs_init
314                 };
315
316                 type = bonobo_type_unique (
317                         BONOBO_OBJECT_TYPE,
318                         POA_Bonobo_Stream__init, NULL,
319                         G_STRUCT_OFFSET (BonoboStreamFSClass, epv),
320                         &info, "BonoboStreamFS");
321         }
322
323         return type;
324 }
325
326 static BonoboStreamFS *
327 bonobo_stream_create (int fd, const char *path)
328 {
329         BonoboStreamFS *stream_fs;
330
331         if (!(stream_fs = g_object_new (bonobo_stream_fs_get_type (), NULL)))
332                 return NULL;
333         
334         stream_fs->fd = fd;
335         stream_fs->priv->mime_type = g_strdup
336                 (gnome_vfs_get_file_mime_type (path, NULL, FALSE));
337
338         return stream_fs;
339 }
340
341
342 /**
343  * bonobo_stream_fs_open:
344  * @path: The path to the file to be opened.
345  * @flags: The flags with which the file should be opened.
346  *
347  * Creates a new BonoboStream object for the filename specified by
348  * @path.  
349  */
350 BonoboStreamFS *
351 bonobo_stream_fs_open (const char *path, gint flags, gint mode,
352                        CORBA_Environment *ev)
353 {
354         BonoboStreamFS *stream;
355         struct stat st;
356         int v, fd;
357         gint fs_flags;
358
359         if (!path || !ev) {
360                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
361                                      ex_Bonobo_Storage_IOError, NULL);
362                 return NULL;
363         }
364
365         if (((v = stat (path, &st)) == -1) && 
366             !(flags & Bonobo_Storage_CREATE)) {
367                 
368                 if ((errno == ENOENT) || (errno == ENOTDIR))
369                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
370                                              ex_Bonobo_Storage_NotFound, 
371                                              NULL);
372                 else if (errno == EACCES)
373                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
374                                              ex_Bonobo_Storage_NoPermission, 
375                                              NULL);
376                 else 
377                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
378                                              ex_Bonobo_Storage_IOError, NULL);
379                 return NULL;
380         }
381
382         if ((v != -1) && S_ISDIR(st.st_mode)) {
383                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
384                                      ex_Bonobo_Storage_NotStream, 
385                                      NULL);
386                 return NULL;
387         }
388
389
390         fs_flags = bonobo_mode_to_fs (flags);
391  
392         if ((fd = open (path, fs_flags, mode)) == -1) {
393
394                 if ((errno == ENOENT) || (errno == ENOTDIR))
395                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
396                                              ex_Bonobo_Storage_NotFound, 
397                                              NULL);
398                 else if (errno == EACCES)
399                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
400                                              ex_Bonobo_Storage_NoPermission, 
401                                              NULL);
402                 else if (errno == EEXIST)
403                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
404                                              ex_Bonobo_Storage_NameExists, 
405                                              NULL);
406                 else
407                         CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
408                                              ex_Bonobo_Storage_IOError, NULL);
409                 return NULL;
410         }
411
412         if (!(stream = bonobo_stream_create (fd, path)))
413                 CORBA_exception_set (ev, CORBA_USER_EXCEPTION, 
414                                      ex_Bonobo_Storage_IOError, NULL);
415
416         return stream;
417 }