2 * lufs interface module vfs objects implementation for libcaptive
3 * Copyright (C) 2003 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 "captivefs-vfs.h" /* self */
23 #include <glib/gmessages.h>
24 #include "captivefs-misc.h"
28 #include <captive/client-vfs.h>
29 #include <captive/options.h>
30 #include <captive/macros.h>
33 #include <lufs/proto.h>
36 gboolean captivefs_vfs_validate(struct captivefs_vfs *captivefs_vfs)
38 g_return_val_if_fail(captivefs_vfs!=NULL,FALSE);
41 g_assert(captivefs_vfs->inits>0);
42 g_assert(captivefs_vfs->mounts>=0);
43 g_assert(captivefs_vfs->mounts<=captivefs_vfs->inits);
44 if (!captivefs_vfs->captive_vfs_object) {
45 GnomeVFSResult errvfsresult;
47 if (captivefs_vfs->parent_pid==getpid()) {
52 errvfsresult=captive_vfs_new(&captivefs_vfs->captive_vfs_object,&captivefs_vfs->options);
54 if (errvfsresult!=GNOME_VFS_OK) {
56 g_return_val_if_reached(FALSE);
59 if (!CAPTIVE_VFS_IS_OBJECT(captivefs_vfs->captive_vfs_object)) {
61 g_return_val_if_reached(FALSE);
70 * Here we allocate a structure to hold all the file system local info
71 * (localfs_local). This structure will then be passed as a parameter to
72 * the other functions.
73 * global_ctx holds info about another structure that can be shared between all
74 * instances of the filesystem. If the pointer is NULL, then this is the
75 * first instance and the structure should be allocated.
76 * ! You must implement locking/usage-count/deallocation logic when using
77 * a global context. (locking is omited here)
78 * ! Most filesystems don't need a global context so you can safely ignore the
79 * global_ctx parameter.
81 struct captivefs_vfs *captivefs_init
82 (struct list_head *cfg,struct dir_cache *cache,const struct credentials *cred,struct captivefs_vfs **global_ctx)
84 struct captivefs_vfs *captivefs_vfs;
86 gchar *gs,*captive_options_string;
88 g_return_val_if_fail(global_ctx!=NULL,NULL);
90 /* Do not: g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_init");
91 * as we do not yet have 'VFS_DEBUG_MESSAGES(captive_vfs_object)' set.
92 * Generally we make all g_log() conditional here as we do not want to mess
93 * with overriden GLog handlers of libcaptive itself.
97 if ((captivefs_vfs=*global_ctx)) {
98 g_assert(captivefs_vfs->inits>0);
99 /* We do not support multiple LUFS threads if they could not be cross-locked. */
100 g_return_val_if_fail(g_thread_supported(),NULL);
101 captivefs_vfs->inits++;
102 G_UNLOCK(libcaptive);
103 if (captivefs_vfs->options.debug_messages)
104 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_init");
105 return captivefs_vfs;
107 G_UNLOCK(libcaptive);
109 /* Initialize i18n for proper nl_langinfo(CODESET) for _g_locale_charset_raw() for g_filename_from_utf8(). */
110 setlocale(LC_ALL,"");
112 if (!g_thread_supported())
113 g_thread_init(NULL); /* g_thread_init() fails on second initialization */
115 /* Initialize GObject subsystem of GLib. */
118 captive_new(captivefs_vfs);
119 captivefs_vfs->captive_vfs_object=NULL;
120 captivefs_vfs->private=FALSE;
121 captivefs_vfs->parent_pid=getpid();
122 captivefs_vfs->global_ctx=global_ctx;
123 *global_ctx=captivefs_vfs;
124 captivefs_vfs->inits=1;
125 captivefs_vfs->mounts=0;
127 captive_options_init(&captivefs_vfs->options);
129 if ((cgs=lu_opt_getchar(cfg,"MOUNT","captive_options"))) {
130 captive_options_string=(/* de-const */gchar *)captive_strdup_alloca(cgs);
131 /* Convert ';' to ' ' to prevent its parsing by LUFS to keep its ordering
132 * to let the options be overridable by user (such as 'ro').
134 for (gs=captive_options_string;(gs=strchr(gs,';'));gs++)
136 if (!captive_options_parse(
137 &captivefs_vfs->options, /* options */
138 captive_options_string)) /* captive_args */
139 goto fail_free_options;
141 if (lu_opt_getchar(cfg,"MOUNT","private"))
142 captivefs_vfs->private=TRUE;
144 if (captivefs_vfs->options.debug_messages)
145 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_init");
147 /* image_iochannel */
148 if ((cgs=lu_opt_getchar(cfg,"MOUNT","image"))) {
149 g_assert(captivefs_vfs->options.image_iochannel==NULL);
150 if (!(captivefs_vfs->options.image_iochannel=g_io_channel_new_file(
152 (captivefs_vfs->options.rwmode==CAPTIVE_OPTION_RWMODE_RW ? "r+" : "r"), /* mode */
153 NULL))) { /* error */
154 g_warning(_("%s: image_iochannel open failed"),"captivefs_init");
155 goto fail_free_options;
159 return captivefs_vfs;
162 captive_options_free(&captivefs_vfs->options);
169 * Check the global context count and free it if necessary.
170 * Deallocate memory and free all resources.
172 void captivefs_free(struct captivefs_vfs *captivefs_vfs)
174 g_return_if_fail(captivefs_vfs_validate(captivefs_vfs));
175 g_return_if_fail(captivefs_vfs->inits>0);
177 if (captivefs_vfs->options.debug_messages)
178 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_free");
180 if (--captivefs_vfs->inits>0) {
181 g_assert(captivefs_vfs_validate(captivefs_vfs));
184 g_assert(captivefs_vfs->mounts==0);
186 *captivefs_vfs->global_ctx=NULL;
187 G_UNLOCK(libcaptive);
189 g_assert(G_OBJECT(captivefs_vfs->captive_vfs_object)->ref_count==1);
192 g_object_unref(captivefs_vfs->captive_vfs_object);
193 G_UNLOCK(libcaptive);
195 /* Do not: g_io_channel_unref(captivefs_vfs->options.image_iochannel);
196 * as it will be unreferenced by captive_options_free().
198 captive_options_free(&captivefs_vfs->options);
199 g_free(captivefs_vfs);
203 /* Mount the file system.
204 * Called when a mount operation is performed.
205 * Initialize specific connections, login, etc.
208 * By default, LUFS may attempt multiple connections at once. If your
209 * filesystem doesn't support this, you need to specificy -c 1 on the
210 * lufsmount command line or connections=1 in the mount options.
211 * See ftpfs for an example of how to read configuration options
212 * from a configuration file if you want to, for example, be able to set
215 int captivefs_mount(struct captivefs_vfs *captivefs_vfs)
217 /* We may be called from the parent. */
218 g_return_val_if_fail(captivefs_vfs!=NULL,FALSE);
219 captivefs_vfs_validate(captivefs_vfs); /* It may return FALSE. */
221 if (captivefs_vfs->options.debug_messages)
222 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_mount");
224 captivefs_vfs->mounts++;
226 captivefs_vfs_validate(captivefs_vfs); /* It may return FALSE. */
228 return 1; /* NEVER return 0 */
232 /* Unmount the file system
233 * Called when the file system is unmounted.
235 void captivefs_umount(struct captivefs_vfs *captivefs_vfs)
237 g_return_if_fail(captivefs_vfs_validate(captivefs_vfs));
238 g_return_if_fail(captivefs_vfs->mounts>0);
240 if (captivefs_vfs->options.debug_messages)
241 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_umount");
243 captivefs_vfs->mounts--;
245 g_assert(captivefs_vfs_validate(captivefs_vfs));
249 #ifdef HAVE_STRUCT_LUFS_SBATTR
250 int captivefs_statfs(struct captivefs_vfs *captivefs_vfs,struct lufs_sbattr *sbattr)
252 CaptiveVfsVolumeInfo captive_volume_info;
253 GnomeVFSResult errvfsresult;
255 g_return_val_if_fail(captivefs_vfs_validate(captivefs_vfs),-1);
256 g_return_val_if_fail(sbattr!=NULL,-1);
258 if (captivefs_vfs->options.debug_messages)
259 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_statfs");
262 errvfsresult=captive_vfs_volume_info_get(captivefs_vfs->captive_vfs_object,&captive_volume_info);
263 G_UNLOCK(libcaptive);
264 if (errvfsresult!=GNOME_VFS_OK)
267 sbattr->sb_bytes=captive_volume_info.bytes;
268 sbattr->sb_bytes_free=captive_volume_info.bytes_free;
269 sbattr->sb_bytes_available=captive_volume_info.bytes_available;
270 /* 'sbattr->sb_files' not known - left unchanged. */
271 /* 'sbattr->sb_ffree' not known - left unchanged. */
275 #endif /* HAVE_STRUCT_LUFS_SBATTR */