VirtualBox

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

Last change on this file since 76689 was 76689, checked in by vboxsync, 6 years ago

vfsmod.c: And seq_file.h. bugref:3544

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.4 KB
Line 
1/** @file
2 *
3 * vboxsf -- 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-2019 Oracle Corporation
14 *
15 * Permission is hereby granted, free of charge, to any person
16 * obtaining a copy of this software and associated documentation
17 * files (the "Software"), to deal in the Software without
18 * restriction, including without limitation the rights to use,
19 * copy, modify, merge, publish, distribute, sublicense, and/or sell
20 * copies of the Software, and to permit persons to whom the
21 * Software is furnished to do so, subject to the following
22 * conditions:
23 *
24 * The above copyright notice and this permission notice shall be
25 * included in all copies or substantial portions of the Software.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
29 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
31 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
32 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
34 * OTHER DEALINGS IN THE SOFTWARE.
35 */
36
37/**
38 * @note Anyone wishing to make changes here might wish to take a look at
39 * https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfs.txt
40 * which seems to be the closest there is to official documentation on
41 * writing filesystem drivers for Linux.
42 */
43
44#include "vfsmod.h"
45#include "version-generated.h"
46#include "revision-generated.h"
47#include "product-generated.h"
48#include "VBoxGuestR0LibInternal.h"
49#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
50# include <linux/mount.h>
51#endif
52#include <linux/seq_file.h>
53
54MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
55MODULE_AUTHOR(VBOX_VENDOR);
56MODULE_LICENSE("GPL and additional rights");
57#ifdef MODULE_ALIAS_FS
58MODULE_ALIAS_FS("vboxsf");
59#endif
60#ifdef MODULE_VERSION
61MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
62#endif
63
64/* globals */
65VBGLSFCLIENT client_handle;
66
67/* forward declarations */
68static struct super_operations sf_super_ops;
69
70/* allocate global info, try to map host share */
71static int sf_glob_alloc(struct vbsf_mount_info_new *info,
72 struct sf_glob_info **sf_gp)
73{
74 int err, rc;
75 SHFLSTRING *str_name;
76 size_t name_len, str_len;
77 struct sf_glob_info *sf_g;
78
79 TRACE();
80 sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
81 if (!sf_g) {
82 err = -ENOMEM;
83 LogRelFunc(("could not allocate memory for global info\n"));
84 goto fail0;
85 }
86
87 RT_ZERO(*sf_g);
88
89 if (info->nullchar != '\0'
90 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
91 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
92 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2) {
93 err = -EINVAL;
94 goto fail1;
95 }
96
97 info->name[sizeof(info->name) - 1] = 0;
98 info->nls_name[sizeof(info->nls_name) - 1] = 0;
99
100 name_len = strlen(info->name);
101 str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
102 str_name = kmalloc(str_len, GFP_KERNEL);
103 if (!str_name) {
104 err = -ENOMEM;
105 LogRelFunc(("could not allocate memory for host name\n"));
106 goto fail1;
107 }
108
109 str_name->u16Length = name_len;
110 str_name->u16Size = name_len + 1;
111 memcpy(str_name->String.utf8, info->name, name_len + 1);
112
113#define _IS_UTF8(_str) \
114 (strcmp(_str, "utf8") == 0)
115#define _IS_EMPTY(_str) \
116 (strcmp(_str, "") == 0)
117
118 /* Check if NLS charset is valid and not points to UTF8 table */
119 if (info->nls_name[0]) {
120 if (_IS_UTF8(info->nls_name))
121 sf_g->nls = NULL;
122 else {
123 sf_g->nls = load_nls(info->nls_name);
124 if (!sf_g->nls) {
125 err = -EINVAL;
126 LogFunc(("failed to load nls %s\n",
127 info->nls_name));
128 kfree(str_name);
129 goto fail1;
130 }
131 }
132 } else {
133#ifdef CONFIG_NLS_DEFAULT
134 /* If no NLS charset specified, try to load the default
135 * one if it's not points to UTF8. */
136 if (!_IS_UTF8(CONFIG_NLS_DEFAULT)
137 && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
138 sf_g->nls = load_nls_default();
139 else
140 sf_g->nls = NULL;
141#else
142 sf_g->nls = NULL;
143#endif
144
145#undef _IS_UTF8
146#undef _IS_EMPTY
147 }
148
149 rc = VbglR0SfMapFolder(&client_handle, str_name, &sf_g->map);
150 kfree(str_name);
151
152 if (RT_FAILURE(rc)) {
153 err = -EPROTO;
154 LogFunc(("VbglR0SfMapFolder failed rc=%d\n", rc));
155 goto fail2;
156 }
157
158 sf_g->ttl = info->ttl;
159 sf_g->uid = info->uid;
160 sf_g->gid = info->gid;
161
162 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, tag)) {
163 /* new fields */
164 sf_g->dmode = info->dmode;
165 sf_g->fmode = info->fmode;
166 sf_g->dmask = info->dmask;
167 sf_g->fmask = info->fmask;
168 } else {
169 sf_g->dmode = ~0;
170 sf_g->fmode = ~0;
171 }
172
173 if ((unsigned)info->length >= sizeof(struct vbsf_mount_info_new)) {
174 AssertCompile(sizeof(sf_g->tag) >= sizeof(info->tag));
175 memcpy(sf_g->tag, info->tag, sizeof(info->tag));
176 sf_g->tag[sizeof(sf_g->tag) - 1] = '\0';
177 } else {
178 sf_g->tag[0] = '\0';
179 }
180
181 *sf_gp = sf_g;
182 return 0;
183
184 fail2:
185 if (sf_g->nls)
186 unload_nls(sf_g->nls);
187
188 fail1:
189 kfree(sf_g);
190
191 fail0:
192 return err;
193}
194
195/* unmap the share and free global info [sf_g] */
196static void sf_glob_free(struct sf_glob_info *sf_g)
197{
198 int rc;
199
200 TRACE();
201 rc = VbglR0SfUnmapFolder(&client_handle, &sf_g->map);
202 if (RT_FAILURE(rc))
203 LogFunc(("VbglR0SfUnmapFolder failed rc=%d\n", rc));
204
205 if (sf_g->nls)
206 unload_nls(sf_g->nls);
207
208 kfree(sf_g);
209}
210
211/**
212 * This is called (by sf_read_super_[24|26] when vfs mounts the fs and
213 * wants to read super_block.
214 *
215 * calls [sf_glob_alloc] to map the folder and allocate global
216 * information structure.
217 *
218 * initializes [sb], initializes root inode and dentry.
219 *
220 * should respect [flags]
221 */
222static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
223{
224 int err;
225 struct dentry *droot;
226 struct inode *iroot;
227 struct sf_inode_info *sf_i;
228 struct sf_glob_info *sf_g;
229 SHFLFSOBJINFO fsinfo;
230 struct vbsf_mount_info_new *info;
231 bool fInodePut = true;
232
233 TRACE();
234 if (!data) {
235 LogFunc(("no mount info specified\n"));
236 return -EINVAL;
237 }
238
239 info = data;
240
241 if (flags & MS_REMOUNT) {
242 LogFunc(("remounting is not supported\n"));
243 return -ENOSYS;
244 }
245
246 err = sf_glob_alloc(info, &sf_g);
247 if (err)
248 goto fail0;
249
250 sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
251 if (!sf_i) {
252 err = -ENOMEM;
253 LogRelFunc(("could not allocate memory for root inode info\n"));
254 goto fail1;
255 }
256
257 sf_i->handle = SHFL_HANDLE_NIL;
258 sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
259 if (!sf_i->path) {
260 err = -ENOMEM;
261 LogRelFunc(("could not allocate memory for root inode path\n"));
262 goto fail2;
263 }
264
265 sf_i->path->u16Length = 1;
266 sf_i->path->u16Size = 2;
267 sf_i->path->String.utf8[0] = '/';
268 sf_i->path->String.utf8[1] = 0;
269 sf_i->force_reread = 0;
270
271 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
272 if (err) {
273 LogFunc(("could not stat root of share\n"));
274 goto fail3;
275 }
276
277 sb->s_magic = 0xface;
278 sb->s_blocksize = 1024;
279#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
280 /* Required for seek/sendfile.
281 *
282 * Must by less than or equal to INT64_MAX despite the fact that the
283 * declaration of this variable is unsigned long long. See determination
284 * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
285 * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
286 * page cache into account and is the suggested limit. */
287#if defined MAX_LFS_FILESIZE
288 sb->s_maxbytes = MAX_LFS_FILESIZE;
289#else
290 sb->s_maxbytes = 0x7fffffffffffffffULL;
291#endif
292#endif
293 sb->s_op = &sf_super_ops;
294
295#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
296 iroot = iget_locked(sb, 0);
297#else
298 iroot = iget(sb, 0);
299#endif
300 if (!iroot) {
301 err = -ENOMEM; /* XXX */
302 LogFunc(("could not get root inode\n"));
303 goto fail3;
304 }
305
306 if (sf_init_backing_dev(sf_g)) {
307 err = -EINVAL;
308 LogFunc(("could not init bdi\n"));
309#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
310 unlock_new_inode(iroot);
311#endif
312 goto fail4;
313 }
314
315 sf_init_inode(sf_g, iroot, &fsinfo);
316 SET_INODE_INFO(iroot, sf_i);
317
318#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
319 unlock_new_inode(iroot);
320#endif
321
322#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
323 droot = d_make_root(iroot);
324#else
325 droot = d_alloc_root(iroot);
326#endif
327 if (!droot) {
328 err = -ENOMEM; /* XXX */
329 LogFunc(("d_alloc_root failed\n"));
330#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
331 fInodePut = false;
332#endif
333 goto fail5;
334 }
335
336 sb->s_root = droot;
337 SET_GLOB_INFO(sb, sf_g);
338 return 0;
339
340 fail5:
341 sf_done_backing_dev(sf_g);
342
343 fail4:
344 if (fInodePut)
345 iput(iroot);
346
347 fail3:
348 kfree(sf_i->path);
349
350 fail2:
351 kfree(sf_i);
352
353 fail1:
354 sf_glob_free(sf_g);
355
356 fail0:
357 return err;
358}
359
360#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
361static struct super_block *sf_read_super_24(struct super_block *sb, void *data,
362 int flags)
363{
364 int err;
365
366 TRACE();
367 err = sf_read_super_aux(sb, data, flags);
368 if (err)
369 return NULL;
370
371 return sb;
372}
373#endif
374
375/* this is called when vfs is about to destroy the [inode]. all
376 resources associated with this [inode] must be cleared here */
377#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
378static void sf_clear_inode(struct inode *inode)
379{
380 struct sf_inode_info *sf_i;
381
382 TRACE();
383 sf_i = GET_INODE_INFO(inode);
384 if (!sf_i)
385 return;
386
387 BUG_ON(!sf_i->path);
388 kfree(sf_i->path);
389 kfree(sf_i);
390 SET_INODE_INFO(inode, NULL);
391}
392#else
393static void sf_evict_inode(struct inode *inode)
394{
395 struct sf_inode_info *sf_i;
396
397 TRACE();
398 truncate_inode_pages(&inode->i_data, 0);
399#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
400 clear_inode(inode);
401#else
402 end_writeback(inode);
403#endif
404
405 sf_i = GET_INODE_INFO(inode);
406 if (!sf_i)
407 return;
408
409 BUG_ON(!sf_i->path);
410 kfree(sf_i->path);
411 kfree(sf_i);
412 SET_INODE_INFO(inode, NULL);
413}
414#endif
415
416/* this is called by vfs when it wants to populate [inode] with data.
417 the only thing that is known about inode at this point is its index
418 hence we can't do anything here, and let lookup/whatever with the
419 job to properly fill then [inode] */
420#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
421static void sf_read_inode(struct inode *inode)
422{
423}
424#endif
425
426/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
427 the folder and free [sf_g] */
428static void sf_put_super(struct super_block *sb)
429{
430 struct sf_glob_info *sf_g;
431
432 sf_g = GET_GLOB_INFO(sb);
433 BUG_ON(!sf_g);
434 sf_done_backing_dev(sf_g);
435 sf_glob_free(sf_g);
436}
437
438#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
439static int sf_statfs(struct super_block *sb, STRUCT_STATFS * stat)
440{
441 return sf_get_volume_info(sb, stat);
442}
443#else
444static int sf_statfs(struct dentry *dentry, STRUCT_STATFS * stat)
445{
446 struct super_block *sb = dentry->d_inode->i_sb;
447 return sf_get_volume_info(sb, stat);
448}
449#endif
450
451static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
452{
453#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
454 struct sf_glob_info *sf_g;
455 struct sf_inode_info *sf_i;
456 struct inode *iroot;
457 SHFLFSOBJINFO fsinfo;
458 int err;
459
460 sf_g = GET_GLOB_INFO(sb);
461 BUG_ON(!sf_g);
462 if (data && data[0] != 0) {
463 struct vbsf_mount_info_new *info =
464 (struct vbsf_mount_info_new *)data;
465 if (info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
466 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
467 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
468 sf_g->uid = info->uid;
469 sf_g->gid = info->gid;
470 sf_g->ttl = info->ttl;
471 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, tag)) {
472 sf_g->dmode = info->dmode;
473 sf_g->fmode = info->fmode;
474 sf_g->dmask = info->dmask;
475 sf_g->fmask = info->fmask;
476 } else {
477 sf_g->dmode = ~0;
478 sf_g->fmode = ~0;
479 }
480 if ((unsigned)info->length >= sizeof(struct vbsf_mount_info_new)) {
481 AssertCompile(sizeof(sf_g->tag) >= sizeof(info->tag));
482 memcpy(sf_g->tag, info->tag, sizeof(info->tag));
483 sf_g->tag[sizeof(sf_g->tag) - 1] = '\0';
484 } else {
485 sf_g->tag[0] = '\0';
486 }
487 }
488 }
489
490 iroot = ilookup(sb, 0);
491 if (!iroot)
492 return -ENOSYS;
493
494 sf_i = GET_INODE_INFO(iroot);
495 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
496 BUG_ON(err != 0);
497 sf_init_inode(sf_g, iroot, &fsinfo);
498 /*unlock_new_inode(iroot); */
499 return 0;
500#else
501 return -ENOSYS;
502#endif
503}
504
505/** Show mount options. */
506#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
507static int sf_show_options(struct seq_file *m, struct vfsmount *mnt)
508#else
509static int sf_show_options(struct seq_file *m, struct dentry *root)
510#endif
511{
512#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
513 struct super_block *sb = mnt->mnt_sb;
514#else
515 struct super_block *sb = root->d_sb;
516#endif
517 struct sf_glob_info *sf_g = GET_GLOB_INFO(sb);
518 if (sf_g) {
519 seq_printf(m, ",uid=%u,gid=%u,ttl=%u,dmode=0%o,fmode=0%o,dmask=0%o,fmask=0%o",
520 sf_g->uid, sf_g->gid, sf_g->ttl, sf_g->dmode, sf_g->fmode, sf_g->dmask, sf_g->fmask);
521 if (sf_g->tag[0] != '\0') {
522 seq_puts(m, ",tag=");
523 seq_escape(m, sf_g->tag, " \t\n\\");
524 }
525 }
526
527 return 0;
528}
529
530/** @todo Implement show_options (forever) or maybe set s_options (2.6.25+).
531 * Necessary for the automounter tagging. */
532static struct super_operations sf_super_ops = {
533#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
534 .clear_inode = sf_clear_inode,
535#else
536 .evict_inode = sf_evict_inode,
537#endif
538#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
539 .read_inode = sf_read_inode,
540#endif
541 .put_super = sf_put_super,
542 .statfs = sf_statfs,
543 .remount_fs = sf_remount_fs,
544 .show_options = sf_show_options
545};
546
547#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
548static DECLARE_FSTYPE(vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
549#else
550static int sf_read_super_26(struct super_block *sb, void *data, int flags)
551{
552 int err;
553
554 TRACE();
555 err = sf_read_super_aux(sb, data, flags);
556 if (err)
557 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
558
559 return err;
560}
561
562#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
563static struct super_block *sf_get_sb(struct file_system_type *fs_type,
564 int flags, const char *dev_name,
565 void *data)
566{
567 TRACE();
568 return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
569}
570#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
571static int sf_get_sb(struct file_system_type *fs_type, int flags,
572 const char *dev_name, void *data, struct vfsmount *mnt)
573{
574 TRACE();
575 return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
576}
577#else
578static struct dentry *sf_mount(struct file_system_type *fs_type, int flags,
579 const char *dev_name, void *data)
580{
581 TRACE();
582 return mount_nodev(fs_type, flags, data, sf_read_super_26);
583}
584#endif
585
586static struct file_system_type vboxsf_fs_type = {
587 .owner = THIS_MODULE,
588 .name = "vboxsf",
589#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
590 .get_sb = sf_get_sb,
591#else
592 .mount = sf_mount,
593#endif
594 .kill_sb = kill_anon_super
595};
596#endif
597
598#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
599static int follow_symlinks = 0;
600module_param(follow_symlinks, int, 0);
601MODULE_PARM_DESC(follow_symlinks,
602 "Let host resolve symlinks rather than showing them");
603#endif
604
605/* Module initialization/finalization handlers */
606static int __init init(void)
607{
608 int rcVBox;
609 int rcRet = 0;
610 int err;
611
612 TRACE();
613
614 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
615 printk(KERN_ERR
616 "Mount information structure is too large %lu\n"
617 "Must be less than or equal to %lu\n",
618 (unsigned long)sizeof(struct vbsf_mount_info_new),
619 (unsigned long)PAGE_SIZE);
620 return -EINVAL;
621 }
622
623 err = register_filesystem(&vboxsf_fs_type);
624 if (err) {
625 LogFunc(("register_filesystem err=%d\n", err));
626 return err;
627 }
628
629 rcVBox = VbglR0HGCMInit();
630 if (RT_FAILURE(rcVBox)) {
631 LogRelFunc(("VbglR0HGCMInit failed, rc=%d\n", rcVBox));
632 rcRet = -EPROTO;
633 goto fail0;
634 }
635
636 rcVBox = VbglR0SfConnect(&client_handle);
637 if (RT_FAILURE(rcVBox)) {
638 LogRelFunc(("VbglR0SfConnect failed, rc=%d\n", rcVBox));
639 rcRet = -EPROTO;
640 goto fail1;
641 }
642
643 rcVBox = VbglR0SfSetUtf8(&client_handle);
644 if (RT_FAILURE(rcVBox)) {
645 LogRelFunc(("VbglR0SfSetUtf8 failed, rc=%d\n", rcVBox));
646 rcRet = -EPROTO;
647 goto fail2;
648 }
649#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
650 if (!follow_symlinks) {
651 rcVBox = VbglR0SfSetSymlinks(&client_handle);
652 if (RT_FAILURE(rcVBox)) {
653 printk(KERN_WARNING
654 "vboxsf: Host unable to show symlinks, rc=%d\n",
655 rcVBox);
656 }
657 }
658#endif
659
660 printk(KERN_DEBUG
661 "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
662 " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
663
664 return 0;
665
666 fail2:
667 VbglR0SfDisconnect(&client_handle);
668
669 fail1:
670 VbglR0HGCMTerminate();
671
672 fail0:
673 unregister_filesystem(&vboxsf_fs_type);
674 return rcRet;
675}
676
677static void __exit fini(void)
678{
679 TRACE();
680
681 VbglR0SfDisconnect(&client_handle);
682 VbglR0HGCMTerminate();
683 unregister_filesystem(&vboxsf_fs_type);
684}
685
686module_init(init);
687module_exit(fini);
688
689/* C++ hack */
690int __gxx_personality_v0 = 0xdeadbeef;
Note: See TracBrowser for help on using the repository browser.

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