2 * glib GIOChannel interface over gnome-vfs GnomeVFSURI for libcaptive
3 * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; exactly version 2 of June 1991 is required
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "captive/macros.h"
23 #include <libgnomevfs/gnome-vfs-method.h>
24 #include <libgnomevfs/gnome-vfs-ops.h>
25 #include <glib/gmessages.h>
26 #include "captive/client.h"
27 #include "gnome-vfs-module.h"
30 /* FIXME: fill 'err' */
32 struct captive_gnomevfs_giognomevfs {
34 GnomeVFSHandle *gnomevfshandle;
37 G_LOCK_DEFINE_STATIC(giochannel_funcs);
38 static GIOFuncs giochannel_funcs;
41 static gboolean validate_giognomevfs(struct captive_gnomevfs_giognomevfs *giognomevfs)
43 g_return_val_if_fail(giognomevfs!=NULL,FALSE);
44 g_return_val_if_fail(giognomevfs->gnomevfshandle!=NULL,FALSE);
50 static GIOStatus captive_gnomevfs_giognomevfs_io_read
51 (GIOChannel *channel,gchar *buf,gsize count,gsize *bytes_read,GError **err)
53 struct captive_gnomevfs_giognomevfs *giognomevfs=(struct captive_gnomevfs_giognomevfs *)channel;
54 GnomeVFSResult errvfsresult;
55 GnomeVFSFileSize bytes_read_local;
57 g_return_val_if_fail(validate_giognomevfs(giognomevfs),G_IO_STATUS_ERROR);
58 g_return_val_if_fail(buf!=NULL,G_IO_STATUS_ERROR);
59 g_return_val_if_fail(bytes_read!=NULL,G_IO_STATUS_ERROR);
61 errvfsresult=gnome_vfs_read(
62 giognomevfs->gnomevfshandle, /* handle */
65 &bytes_read_local); /* bytes_read */
66 g_return_val_if_fail((errvfsresult==GNOME_VFS_OK || errvfsresult==GNOME_VFS_ERROR_EOF),G_IO_STATUS_ERROR);
68 *bytes_read=bytes_read_local;
69 return (errvfsresult==GNOME_VFS_ERROR_EOF ? G_IO_STATUS_EOF : G_IO_STATUS_NORMAL);
73 static GIOStatus captive_gnomevfs_giognomevfs_io_write
74 (GIOChannel *channel,const gchar *buf,gsize count,gsize *bytes_written,GError **err)
76 struct captive_gnomevfs_giognomevfs *giognomevfs=(struct captive_gnomevfs_giognomevfs *)channel;
77 GnomeVFSResult errvfsresult;
78 GnomeVFSFileSize bytes_written_local;
80 g_return_val_if_fail(validate_giognomevfs(giognomevfs),G_IO_STATUS_ERROR);
81 g_return_val_if_fail(buf!=NULL,G_IO_STATUS_ERROR);
82 g_return_val_if_fail(bytes_written!=NULL,G_IO_STATUS_ERROR);
84 errvfsresult=gnome_vfs_write(
85 giognomevfs->gnomevfshandle, /* handle */
88 &bytes_written_local); /* bytes_written */
89 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,G_IO_STATUS_ERROR);
91 *bytes_written=bytes_written_local;
92 return G_IO_STATUS_NORMAL;
96 static GIOStatus captive_gnomevfs_giognomevfs_io_seek(GIOChannel *channel,gint64 offset,GSeekType type,GError **err)
98 struct captive_gnomevfs_giognomevfs *giognomevfs=(struct captive_gnomevfs_giognomevfs *)channel;
99 GnomeVFSSeekPosition whence;
100 GnomeVFSResult errvfsresult;
102 g_return_val_if_fail(validate_giognomevfs(giognomevfs),G_IO_STATUS_ERROR);
105 case G_SEEK_CUR: whence=GNOME_VFS_SEEK_CURRENT; break;
106 case G_SEEK_SET: whence=GNOME_VFS_SEEK_START; break;
107 case G_SEEK_END: whence=GNOME_VFS_SEEK_END; break;
108 default: g_return_val_if_reached(G_IO_STATUS_ERROR);
110 errvfsresult=gnome_vfs_seek(giognomevfs->gnomevfshandle,whence,offset);
111 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,G_IO_STATUS_ERROR);
113 return G_IO_STATUS_NORMAL;
117 static GIOStatus captive_gnomevfs_giognomevfs_io_close(GIOChannel *channel,GError **err)
119 struct captive_gnomevfs_giognomevfs *giognomevfs=(struct captive_gnomevfs_giognomevfs *)channel;
122 g_return_val_if_fail(validate_giognomevfs(giognomevfs),G_IO_STATUS_ERROR);
124 g_assert(captive_image_iochannel!=NULL);
126 errbool=captive_shutdown();
127 G_UNLOCK(libcaptive);
128 g_assert(errbool==TRUE);
129 g_assert(captive_image_iochannel==NULL);
131 gnome_vfs_close(giognomevfs->gnomevfshandle);
133 return G_IO_STATUS_NORMAL;
137 static GSource* captive_gnomevfs_giognomevfs_io_create_watch(GIOChannel *channel,GIOCondition condition)
139 struct captive_gnomevfs_giognomevfs *giognomevfs=(struct captive_gnomevfs_giognomevfs *)channel;
141 g_return_val_if_fail(validate_giognomevfs(giognomevfs),NULL);
143 g_return_val_if_reached(NULL); /* FIXME: NOT IMPLEMENTED YET */
147 static void captive_gnomevfs_giognomevfs_io_free(GIOChannel *channel)
149 struct captive_gnomevfs_giognomevfs *giognomevfs=(struct captive_gnomevfs_giognomevfs *)channel;
151 g_return_if_fail(validate_giognomevfs(giognomevfs));
157 static GIOStatus captive_gnomevfs_giognomevfs_io_set_flags(GIOChannel *channel,GIOFlags flags,GError **err)
159 struct captive_gnomevfs_giognomevfs *giognomevfs=(struct captive_gnomevfs_giognomevfs *)channel;
161 g_return_val_if_fail(validate_giognomevfs(giognomevfs),G_IO_STATUS_ERROR);
163 /* no G_IO_FLAG_APPEND and no G_IO_FLAG_NONBLOCK */
164 g_return_val_if_fail((flags&G_IO_FLAG_SET_MASK)==0,G_IO_STATUS_ERROR);
166 return G_IO_STATUS_NORMAL;
170 static GIOFlags captive_gnomevfs_giognomevfs_io_get_flags(GIOChannel *channel)
172 struct captive_gnomevfs_giognomevfs *giognomevfs=(struct captive_gnomevfs_giognomevfs *)channel;
174 g_return_val_if_fail(validate_giognomevfs(giognomevfs),0);
176 return 0; /* | !G_IO_FLAG_APPEND | !G_IO_FLAG_NONBLOCK */
180 GnomeVFSResult captive_gnomevfs_giognomevfs_new(struct captive_gnomevfs_giognomevfs **giognomevfsp,
181 const gchar *captive_args,GnomeVFSURI *uri)
183 GnomeVFSHandle *handle;
184 struct captive_gnomevfs_giognomevfs *giognomevfs;
185 GnomeVFSResult errvfsresult;
188 g_return_val_if_fail(giognomevfsp!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
189 g_return_val_if_fail(uri!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
191 /* Parse 'captive_args' to get at least 'captive_option_rwmode' option value (phase 1). */
193 errbool=captive_init(
194 captive_args, /* captive_args */
195 NULL); /* image_iochannel */
196 G_UNLOCK(libcaptive);
197 g_assert(errbool==FALSE);
199 errvfsresult=gnome_vfs_open_uri(&handle,uri,
201 | GNOME_VFS_OPEN_RANDOM /* mandatory; otherwise we will get truncation if GNOME_VFS_OPEN_WRITE */
202 | GNOME_VFS_OPEN_READ
203 | (captive_option_rwmode==CAPTIVE_OPTION_RWMODE_RW ? GNOME_VFS_OPEN_WRITE : 0));
204 g_return_val_if_fail(errvfsresult==GNOME_VFS_OK,errvfsresult);
206 G_LOCK(giochannel_funcs);
207 giochannel_funcs.io_read =captive_gnomevfs_giognomevfs_io_read;
208 giochannel_funcs.io_write =captive_gnomevfs_giognomevfs_io_write;
209 giochannel_funcs.io_seek =captive_gnomevfs_giognomevfs_io_seek;
210 giochannel_funcs.io_close =captive_gnomevfs_giognomevfs_io_close;
211 giochannel_funcs.io_create_watch=captive_gnomevfs_giognomevfs_io_create_watch;
212 giochannel_funcs.io_free =captive_gnomevfs_giognomevfs_io_free;
213 giochannel_funcs.io_set_flags =captive_gnomevfs_giognomevfs_io_set_flags;
214 giochannel_funcs.io_get_flags =captive_gnomevfs_giognomevfs_io_get_flags;
215 G_UNLOCK(giochannel_funcs);
217 captive_new(giognomevfs);
218 g_assert(G_STRUCT_OFFSET(struct captive_gnomevfs_giognomevfs,iochannel)==0); /* safely re-type-able */
219 g_io_channel_init(&giognomevfs->iochannel);
220 giognomevfs->iochannel.funcs=&giochannel_funcs;
221 giognomevfs->iochannel.is_seekable=TRUE;
222 giognomevfs->iochannel.is_readable=TRUE;
223 giognomevfs->iochannel.is_writeable=(captive_option_rwmode==CAPTIVE_OPTION_RWMODE_RW);
224 giognomevfs->iochannel.close_on_unref=TRUE; /* run g_io_channel_shutdown() flush on last unref */
225 giognomevfs->gnomevfshandle=handle;
227 /* Initialization for the real this time (phase 2). */
228 g_assert(captive_image_iochannel==NULL);
230 errbool=captive_init(
231 NULL, /* captive_args */
232 (GIOChannel *)giognomevfs); /* image_iochannel */
233 G_UNLOCK(libcaptive);
234 g_assert(errbool==TRUE);
235 /* It may not be 'giognomevfs' as it may be wrapped by 'captive_giochannel_blind'. */
236 g_assert(captive_image_iochannel!=NULL);
238 *giognomevfsp=giognomevfs;