VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c@ 6450

Last change on this file since 6450 was 6054, checked in by vboxsync, 17 years ago

vboxvfs: implemented readfile()

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/** @file
2 *
3 * vboxvfs -- VirtualBox Guest Additions for Linux:
4 * Virtual File System for VirtualBox Shared Folders
5 *
6 * Module initialization/finalization
7 * File system registration/deregistration
8 * Superblock reading
9 * Few utility functions
10 */
11
12/*
13 * Copyright (C) 2006-2007 innotek GmbH
14 *
15 * This file is part of VirtualBox Open Source Edition (OSE), as
16 * available from http://www.virtualbox.org. This file is free software;
17 * you can redistribute it and/or modify it under the terms of the GNU
18 * General Public License (GPL) as published by the Free Software
19 * Foundation, in version 2 as it comes in the "COPYING" file of the
20 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
21 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
22 */
23
24/**
25 * @note Anyone wishing to make changes here might wish to take a look at
26 * http://www.atnf.csiro.au/people/rgooch/linux/vfs.txt
27 * which seems to be the closest there is to official documentation on
28 * writing filesystem drivers for Linux.
29 */
30
31/*
32 * Suppress the definition of wchar_t from stddef.h that occurs below.
33 * This makes (at least) RHEL3U5 happy.
34 */
35#if 0
36#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
37# define _WCHAR_T
38#endif
39#endif
40
41#include "vfsmod.h"
42
43// #define wchar_t linux_wchar_t
44
45#define xstr(s) str(s)
46#define str(s) #s
47
48MODULE_DESCRIPTION ("Host file system access VFS for VirtualBox");
49MODULE_AUTHOR ("innotek GmbH");
50MODULE_LICENSE ("GPL");
51#ifdef MODULE_VERSION
52MODULE_VERSION(VBOX_VERSION_STRING " (interface " xstr(VMMDEV_VERSION) ")");
53#endif
54
55/* globals */
56VBSFCLIENT client_handle;
57
58/* forward declarations */
59static struct super_operations sf_super_ops;
60
61// #include "utils.c"
62// #include "dirops.c"
63// #include "regops.c"
64
65/* allocate global info, try to map host share */
66static int
67sf_glob_alloc (struct vbsf_mount_info *info, struct sf_glob_info **sf_gp)
68{
69 int err, rc;
70 SHFLSTRING *str_name;
71 size_t name_len, str_len;
72 struct sf_glob_info *sf_g;
73
74 TRACE ();
75 sf_g = kmalloc (sizeof (*sf_g), GFP_KERNEL);
76 if (!sf_g) {
77 err = -ENOMEM;
78 LogRelFunc(("could not allocate memory for global info\n"));
79 goto fail0;
80 }
81
82 info->name[sizeof (info->name) - 1] = 0;
83 info->nls_name[sizeof (info->nls_name) - 1] = 0;
84
85 name_len = strlen (info->name);
86 if (name_len > 0xfffe) {
87 err = -ENAMETOOLONG;
88 LogFunc(("map name too big\n"));
89 goto fail1;
90 }
91
92 str_len = offsetof (SHFLSTRING, String.utf8) + name_len + 1;
93 str_name = kmalloc (str_len, GFP_KERNEL);
94 if (!str_name) {
95 err = -ENOMEM;
96 LogRelFunc(("could not allocate memory for host name\n"));
97 goto fail1;
98 }
99
100 str_name->u16Length = name_len;
101 str_name->u16Size = name_len + 1;
102 memcpy (str_name->String.utf8, info->name, name_len + 1);
103
104 if (info->nls_name[0] && strcmp (info->nls_name, "utf8")) {
105 sf_g->nls = load_nls (info->nls_name);
106 if (!sf_g->nls) {
107 err = -EINVAL;
108 LogFunc(("failed to load nls %s\n", info->nls_name));
109 goto fail1;
110 }
111 }
112 else {
113 sf_g->nls = NULL;
114 }
115
116 rc = vboxCallMapFolder (&client_handle, str_name, &sf_g->map);
117 kfree (str_name);
118
119 if (VBOX_FAILURE (rc)) {
120 err = -EPROTO;
121 LogFunc(("vboxCallMapFolder failed rc=%d\n", rc));
122 goto fail2;
123 }
124
125 sf_g->ttl = info->ttl;
126 sf_g->uid = info->uid;
127 sf_g->gid = info->gid;
128
129 *sf_gp = sf_g;
130 return 0;
131
132 fail2:
133 if (sf_g->nls) {
134 unload_nls (sf_g->nls);
135 }
136 fail1:
137 kfree (sf_g);
138 fail0:
139 return err;
140}
141
142/* unmap the share and free global info [sf_g] */
143static void
144sf_glob_free (struct sf_glob_info *sf_g)
145{
146 int rc;
147
148 TRACE ();
149 rc = vboxCallUnmapFolder (&client_handle, &sf_g->map);
150 if (VBOX_FAILURE (rc)) {
151 LogFunc(("vboxCallUnmapFolder failed rc=%d\n", rc));
152 }
153
154 if (sf_g->nls) {
155 unload_nls (sf_g->nls);
156 }
157 kfree (sf_g);
158}
159
160/* this is called (by sf_read_super_[24|26] when vfs mounts the fs and
161 wants to read super_block.
162
163 calls [sf_glob_alloc] to map the folder and allocate global
164 information structure.
165
166 initializes [sb], initializes root inode and dentry.
167
168 should respect [flags] */
169static int
170sf_read_super_aux (struct super_block *sb, void *data, int flags)
171{
172 int err;
173 struct dentry *droot;
174 struct inode *iroot;
175 struct sf_inode_info *sf_i;
176 struct sf_glob_info *sf_g;
177 RTFSOBJINFO fsinfo;
178 struct vbsf_mount_info *info;
179
180 TRACE ();
181 if (!data) {
182 LogFunc(("no mount info specified\n"));
183 return -EINVAL;
184 }
185
186 info = data;
187
188 if (flags & MS_REMOUNT) {
189 LogFunc(("remounting is not supported\n"));
190 return -ENOSYS;
191 }
192
193 err = sf_glob_alloc (info, &sf_g);
194 if (err) {
195 goto fail0;
196 }
197
198 sf_i = kmalloc (sizeof (*sf_i), GFP_KERNEL);
199 if (!sf_i) {
200 err = -ENOMEM;
201 LogRelFunc (("could not allocate memory for root inode info\n"));
202 goto fail1;
203 }
204
205 sf_i->path = kmalloc (sizeof (SHFLSTRING) + 1, GFP_KERNEL);
206 if (!sf_i->path) {
207 err = -ENOMEM;
208 LogRelFunc (("could not allocate memory for root inode path\n"));
209 goto fail2;
210 }
211
212 sf_i->path->u16Length = 1;
213 sf_i->path->u16Size = 2;
214 sf_i->path->String.utf8[0] = '/';
215 sf_i->path->String.utf8[1] = 0;
216
217 err = sf_stat (__func__, sf_g, sf_i->path, &fsinfo, 0);
218 if (err) {
219 LogFunc(("could not stat root of share\n"));
220 goto fail3;
221 }
222
223 sb->s_magic = 0xface;
224 sb->s_blocksize = 1024;
225 sb->s_op = &sf_super_ops;
226
227 iroot = iget (sb, 0);
228 if (!iroot) {
229 err = -ENOMEM; /* XXX */
230 LogFunc(("could not get root inode\n"));
231 goto fail3;
232 }
233
234 sf_init_inode (sf_g, iroot, &fsinfo);
235 SET_INODE_INFO (iroot, sf_i);
236
237 droot = d_alloc_root (iroot);
238 if (!droot) {
239 err = -ENOMEM; /* XXX */
240 LogFunc(("d_alloc_root failed\n"));
241 goto fail4;
242 }
243
244 sb->s_root = droot;
245 SET_GLOB_INFO (sb, sf_g);
246 return 0;
247
248 fail4:
249 iput (iroot);
250 fail3:
251 kfree (sf_i->path);
252 fail2:
253 kfree (sf_i);
254 fail1:
255 sf_glob_free (sf_g);
256 fail0:
257 return err;
258}
259
260#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
261static struct super_block *
262sf_read_super_24 (struct super_block *sb, void *data, int flags)
263{
264 int err;
265
266 TRACE ();
267 err = sf_read_super_aux (sb, data, flags);
268 if (err) {
269 return NULL;
270 }
271
272 return sb;
273}
274#endif
275
276/* this is called when vfs is about to destroy the [inode]. all
277 resources associated with this [inode] must be cleared here */
278static void
279sf_clear_inode (struct inode *inode)
280{
281 struct sf_inode_info *sf_i;
282
283 TRACE ();
284 sf_i = GET_INODE_INFO (inode);
285 if (!sf_i) {
286 return;
287 }
288
289 BUG_ON (!sf_i->path);
290 kfree (sf_i->path);
291 kfree (sf_i);
292 SET_INODE_INFO (inode, NULL);
293}
294
295/* this is called by vfs when it wants to populate [inode] with data.
296 the only thing that is known about inode at this point is its index
297 hence we can't do anything here, and let lookup/whatever with the
298 job to properly fill then [inode] */
299static void
300sf_read_inode (struct inode *inode)
301{
302}
303
304/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
305 the folder and free [sf_g] */
306static void
307sf_put_super (struct super_block *sb)
308{
309 struct sf_glob_info *sf_g;
310
311 sf_g = GET_GLOB_INFO (sb);
312 BUG_ON (!sf_g);
313 sf_glob_free (sf_g);
314}
315
316#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 18)
317static int
318sf_statfs (struct super_block *sb, STRUCT_STATFS *stat)
319{
320 return sf_get_volume_info(sb, stat);
321}
322#else
323static int
324sf_statfs (struct dentry *dentry, STRUCT_STATFS *stat)
325{
326 struct super_block *sb = dentry->d_inode->i_sb;
327 return sf_get_volume_info(sb, stat);
328}
329#endif
330
331static int
332sf_remount_fs (struct super_block *sb, int *flags, char *data)
333{
334 TRACE ();
335 return -ENOSYS;
336}
337
338static struct super_operations sf_super_ops = {
339 .clear_inode = sf_clear_inode,
340 .read_inode = sf_read_inode,
341 .put_super = sf_put_super,
342 .statfs = sf_statfs,
343 .remount_fs = sf_remount_fs
344};
345
346#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
347static DECLARE_FSTYPE (vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
348#else
349static int
350sf_read_super_26 (struct super_block *sb, void *data, int flags)
351{
352 int err;
353
354 TRACE ();
355 err = sf_read_super_aux (sb, data, flags);
356 if (err) {
357 printk (KERN_DEBUG "sf_read_super_aux err=%d\n", err);
358 }
359 return err;
360}
361
362#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 18)
363static struct super_block *
364sf_get_sb (struct file_system_type *fs_type, int flags,
365 const char *dev_name, void *data)
366{
367 TRACE ();
368 return get_sb_nodev (fs_type, flags, data, sf_read_super_26);
369}
370#else
371static int
372sf_get_sb (struct file_system_type *fs_type, int flags,
373 const char *dev_name, void *data, struct vfsmount *mnt)
374{
375 TRACE ();
376 return get_sb_nodev (fs_type, flags, data, sf_read_super_26, mnt);
377}
378#endif
379
380static struct file_system_type vboxsf_fs_type = {
381 .owner = THIS_MODULE,
382 .name = "vboxsf",
383 .get_sb = sf_get_sb,
384 .kill_sb = kill_anon_super
385};
386#endif
387
388extern int CMC_API
389vboxadd_cmc_ctl_guest_filter_mask (uint32_t or_mask, uint32_t not_mask);
390
391/* Module initialization/finalization handlers */
392static int __init
393init (void)
394{
395 int rcVBox;
396 int rcRet = 0;
397 int err;
398
399 TRACE ();
400
401 if (sizeof (struct vbsf_mount_info) > PAGE_SIZE) {
402 printk (KERN_ERR
403 "Mount information structure is too large %u\n"
404 "Must be less than or equal to %lu\n",
405 sizeof (struct vbsf_mount_info),
406 PAGE_SIZE);
407 return -EINVAL;
408 }
409
410 err = register_filesystem (&vboxsf_fs_type);
411 if (err) {
412 LogFunc(("register_filesystem err=%d\n", err));
413 return err;
414 }
415
416 if (vboxadd_cmc_ctl_guest_filter_mask (VMMDEV_EVENT_HGCM, 0)) {
417 rcRet = -EINVAL;
418 goto fail0;
419 }
420
421 rcVBox = vboxInit ();
422 if (VBOX_FAILURE (rcVBox)) {
423 LogRelFunc (("vboxInit failed, rc=%d\n", rcVBox));
424 rcRet = -EPROTO;
425 goto fail0;
426 }
427
428 rcVBox = vboxConnect (&client_handle);
429 if (VBOX_FAILURE (rcVBox)) {
430 LogRelFunc (("vboxConnect failed, rc=%d\n", rcVBox));
431 rcRet = -EPROTO;
432 goto fail1;
433 }
434
435 rcVBox = vboxCallSetUtf8 (&client_handle);
436 if (VBOX_FAILURE (rcVBox)) {
437 LogRelFunc (("vboxCallSetUtf8 failed, rc=%d\n", rcVBox));
438 rcRet = -EPROTO;
439 goto fail2;
440 }
441
442 printk(KERN_DEBUG
443 "vboxvfs: Successfully loaded version " VBOX_VERSION_STRING
444 " (interface " xstr(VMMDEV_VERSION) ")\n");
445
446 return 0;
447
448 fail2:
449 vboxDisconnect (&client_handle);
450 fail1:
451 vboxUninit ();
452 fail0:
453 vboxadd_cmc_ctl_guest_filter_mask (0, VMMDEV_EVENT_HGCM);
454 unregister_filesystem (&vboxsf_fs_type);
455 return rcRet;
456}
457
458static void __exit
459fini (void)
460{
461 TRACE ();
462
463 vboxDisconnect (&client_handle);
464 vboxUninit ();
465 vboxadd_cmc_ctl_guest_filter_mask (0, VMMDEV_EVENT_HGCM);
466 unregister_filesystem (&vboxsf_fs_type);
467}
468
469module_init (init);
470module_exit (fini);
471
472/* C++ hack */
473int __gxx_personality_v0 = 0xdeadbeef;
474
475#if 0
476/* long long hacks (as far as i can see, gcc emits the refs to those
477 symbols, notwithstanding the fact that those aren't referenced
478 anywhere in the module) */
479void __divdi3 (void)
480{
481 elog ("called from %p\n", __builtin_return_address (0));
482 BUG ();
483}
484
485void __moddi3 (void)
486{
487 elog ("called from %p\n", __builtin_return_address (0));
488 BUG ();
489}
490#endif /* 0 */
491
492/*
493 * Local Variables:
494 * c-mode: linux
495 * indent-tabs-mode: nil
496 * c-basic-offset: 8
497 * End:
498 */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette