VirtualBox

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

Last change on this file since 3661 was 2980, checked in by vboxsync, 18 years ago

InnoTek -> innotek: actual code changes (headers follow).

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