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"
27 #include <captive/client-vfs.h>
28 #include <captive/options.h>
29 #include <captive/macros.h>
34 gboolean captivefs_vfs_validate(struct captivefs_vfs *captivefs_vfs)
36 g_return_val_if_fail(captivefs_vfs!=NULL,FALSE);
39 g_assert(captivefs_vfs->inits>0);
40 g_assert(captivefs_vfs->mounts>=0);
41 g_assert(captivefs_vfs->mounts<=captivefs_vfs->inits);
42 if (!captivefs_vfs->captive_vfs_object) {
43 GnomeVFSResult errvfsresult;
45 if (captivefs_vfs->parent_pid==getpid()) {
50 errvfsresult=captive_vfs_new(&captivefs_vfs->captive_vfs_object,&captivefs_vfs->options);
52 if (errvfsresult!=GNOME_VFS_OK) {
54 g_return_val_if_reached(FALSE);
57 if (!CAPTIVE_VFS_IS_OBJECT(captivefs_vfs->captive_vfs_object)) {
59 g_return_val_if_reached(FALSE);
68 * Here we allocate a structure to hold all the file system local info
69 * (localfs_local). This structure will then be passed as a parameter to
70 * the other functions.
71 * global_ctx holds info about another structure that can be shared between all
72 * instances of the filesystem. If the pointer is NULL, then this is the
73 * first instance and the structure should be allocated.
74 * ! You must implement locking/usage-count/deallocation logic when using
75 * a global context. (locking is omited here)
76 * ! Most filesystems don't need a global context so you can safely ignore the
77 * global_ctx parameter.
79 struct captivefs_vfs *captivefs_init
80 (struct list_head *cfg,struct dir_cache *cache,const struct credentials *cred,struct captivefs_vfs **global_ctx)
82 struct captivefs_vfs *captivefs_vfs;
83 const struct poptOption *cpopt;
89 g_return_val_if_fail(global_ctx!=NULL,NULL);
91 /* Do not: g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_init");
92 * as we do not yet have 'VFS_DEBUG_MESSAGES(captive_vfs_object)' set.
93 * Generally we make all g_log() conditional here as we do not want to mess
94 * with overriden GLog handlers of libcaptive itself.
98 if ((captivefs_vfs=*global_ctx)) {
99 g_assert(captivefs_vfs->inits>0);
100 /* We do not support multiple LUFS threads if they could not be cross-locked. */
101 g_return_val_if_fail(g_thread_supported(),NULL);
102 captivefs_vfs->inits++;
103 G_UNLOCK(libcaptive);
104 return captivefs_vfs;
106 G_UNLOCK(libcaptive);
108 if (!g_thread_supported())
109 g_thread_init(NULL); /* g_thread_init() fails on second initialization */
111 arg_array=g_ptr_array_new();
112 if (!(cgs=lu_opt_getchar(cfg,"MOUNT","fs")))
114 g_ptr_array_add(arg_array,(/* de-const */ char *)cgs);
115 for (cpopt=captive_popt;cpopt->argInfo || cpopt->longName;cpopt++) {
116 const gchar *dashdashname,*value;
118 if (!cpopt->longName)
120 dashdashname=captive_printf_alloca("--%s",cpopt->longName);
122 && !(value=lu_opt_getchar(cfg,"MOUNT",(/* de-const */ char *)dashdashname))
123 && !(value=lu_opt_getchar(cfg,"MOUNT",(/* de-const */ char *)cpopt->longName)))
125 g_ptr_array_add(arg_array,(/* de-const */ char *)captive_printf_alloca("%s=%s",dashdashname,value));
127 g_ptr_array_add(arg_array,NULL);
128 g_assert(arg_array->len>=2);
129 g_assert(arg_array->pdata[arg_array->len-2]!=NULL);
130 g_assert(arg_array->pdata[arg_array->len-1]==NULL);
132 /* Initialize GObject subsystem of GLib. */
135 captive_new(captivefs_vfs);
136 captivefs_vfs->captive_vfs_object=NULL;
137 captivefs_vfs->parent_pid=getpid();
138 captivefs_vfs->global_ctx=global_ctx;
139 *global_ctx=captivefs_vfs;
140 captivefs_vfs->inits=1;
141 captivefs_vfs->mounts=0;
143 captive_options_init(&captivefs_vfs->options);
144 captive_options=&captivefs_vfs->options; /* for parsing by 'CAPTIVE_POPT_INCLUDE' */
146 context=poptGetContext(
148 arg_array->len-1, /* argc */
149 (const char **)arg_array->pdata, /* argv */
150 captive_popt, /* options */
151 POPT_CONTEXT_POSIXMEHARDER); /* flags; && !POPT_CONTEXT_KEEP_FIRST */
152 g_ptr_array_free(arg_array,
153 FALSE); /* free_seg */
155 g_warning("%s: argument recognization args_error","captivefs_init");
156 goto fail_free_options;
158 errint=poptReadDefaultConfig(context,
161 g_warning("%s: argument recognization args_error","captivefs_init");
162 goto fail_free_options;
164 errint=poptGetNextOpt(context);
166 g_warning("%s: some non-callbacked argument reached","captivefs_init");
167 goto fail_free_options;
169 cgs=poptPeekArg(context);
171 g_warning("%s: some non-option argument reached","captivefs_init");
172 goto fail_free_options;
175 captive_options=NULL; /* already parsed by 'CAPTIVE_POPT_INCLUDE' */
177 if (captivefs_vfs->options.debug_messages)
178 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_init");
180 /* image_iochannel */
181 if ((cgs=lu_opt_getchar(cfg,"MOUNT","image"))) {
182 g_assert(captivefs_vfs->options.image_iochannel==NULL);
183 if (!(captivefs_vfs->options.image_iochannel=g_io_channel_new_file(
185 (captivefs_vfs->options.rwmode==CAPTIVE_OPTION_RWMODE_RW ? "r+" : "r"), /* mode */
186 NULL))) { /* error */
187 g_warning(_("%s: image_iochannel open failed"),"captivefs_init");
188 goto fail_free_options;
192 return captivefs_vfs;
195 captive_options_free(&captivefs_vfs->options);
202 * Check the global context count and free it if necessary.
203 * Deallocate memory and free all resources.
205 void captivefs_free(struct captivefs_vfs *captivefs_vfs)
207 g_return_if_fail(captivefs_vfs_validate(captivefs_vfs));
208 g_return_if_fail(captivefs_vfs->inits>0);
210 if (captivefs_vfs->options.debug_messages)
211 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_free");
213 if (--captivefs_vfs->inits>0) {
214 g_assert(captivefs_vfs_validate(captivefs_vfs));
217 g_assert(captivefs_vfs->mounts==0);
219 *captivefs_vfs->global_ctx=NULL;
220 G_UNLOCK(libcaptive);
222 g_assert(G_OBJECT(captivefs_vfs->captive_vfs_object)->ref_count==1);
225 g_object_unref(captivefs_vfs->captive_vfs_object);
226 G_UNLOCK(libcaptive);
228 g_io_channel_unref(captivefs_vfs->options.image_iochannel);
229 captive_options_free(&captivefs_vfs->options);
230 g_free(captivefs_vfs);
234 /* Mount the file system.
235 * Called when a mount operation is performed.
236 * Initialize specific connections, login, etc.
239 * By default, LUFS may attempt multiple connections at once. If your
240 * filesystem doesn't support this, you need to specificy -c 1 on the
241 * lufsmount command line or connections=1 in the mount options.
242 * See ftpfs for an example of how to read configuration options
243 * from a configuration file if you want to, for example, be able to set
246 int captivefs_mount(struct captivefs_vfs *captivefs_vfs)
248 /* We may be called from the parent. */
249 g_return_val_if_fail(captivefs_vfs!=NULL,FALSE);
250 captivefs_vfs_validate(captivefs_vfs); /* It may return FALSE. */
252 if (captivefs_vfs->options.debug_messages)
253 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_mount");
255 captivefs_vfs->mounts++;
257 captivefs_vfs_validate(captivefs_vfs); /* It may return FALSE. */
259 return 1; /* NEVER return 0 */
263 /* Unmount the file system
264 * Called when the file system is unmounted.
266 void captivefs_umount(struct captivefs_vfs *captivefs_vfs)
268 g_return_if_fail(captivefs_vfs_validate(captivefs_vfs));
269 g_return_if_fail(captivefs_vfs->mounts>0);
271 if (captivefs_vfs->options.debug_messages)
272 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"captivefs_umount");
274 captivefs_vfs->mounts--;
276 g_assert(captivefs_vfs_validate(captivefs_vfs));