VirtualBox

source: vbox/trunk/src/VBox/Additions/solaris/SharedFolders/vboxvfs_vfsops.c@ 10067

最後變更 在這個檔案從10067是 10067,由 vboxsync 提交於 16 年 前

Solaris vboxvfs: root vnode.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keyword 設為 Id
  • 屬性 svn:keywords 設為 Id
檔案大小: 18.7 KB
 
1/* $Id: vboxvfs_vfsops.c 10067 2008-07-01 11:07:51Z vboxsync $ */
2/** @file
3 * VirtualBox File System Driver for Solaris Guests. VFS operations.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
8 *
9 * Sun Microsystems, Inc. confidential
10 * All rights reserved
11 */
12
13
14/*******************************************************************************
15* Header Files *
16*******************************************************************************/
17#include <sys/types.h>
18#include <sys/mntent.h>
19#include <sys/param.h>
20#include <sys/modctl.h>
21#include <sys/mount.h>
22#include <sys/policy.h>
23#include <sys/ddi.h>
24#include <sys/sunddi.h>
25#include "vboxvfs.h"
26
27#if defined(DEBUG_ramshankar) && !defined(LOG_ENABLED)
28# define LOG_ENABLED
29# define LOG_TO_BACKDOOR
30#endif
31#include <VBox/log.h>
32#include <iprt/string.h>
33#include <iprt/mem.h>
34#include <iprt/err.h>
35
36
37/*******************************************************************************
38* Defined Constants And Macros *
39*******************************************************************************/
40/** Mount Options */
41#define MNTOPT_VBOXVFS_UID "uid"
42#define MNTOPT_VBOXVFS_GID "gid"
43
44
45/*******************************************************************************
46* Internal Functions *
47*******************************************************************************/
48static int VBoxVFS_Init(int fType, char *pszName);
49static int VBoxVFS_Mount(vfs_t *pVFS, vnode_t *pVNode, struct mounta *pMount, cred_t *pCred);
50static int VBoxVFS_Unmount(vfs_t *pVFS, int fFlags, cred_t *pCred);
51static int VBoxVFS_Root(vfs_t *pVFS, vnode_t **ppVNode);
52static int VBoxVFS_Statfs(register vfs_t *pVFS, struct statvfs64 *pStat);
53static int VBoxVFS_VGet(vfs_t *pVFS, vnode_t **ppVNode, struct fid *pFid);
54static void VBoxVFS_FreeVFS(vfs_t *pVFS);
55
56static int vboxvfs_CheckMountPerm(vfs_t *pVFS, struct mounta *pMount, vnode_t *pVNodeSpec, cred_t *pCred);
57static int vboxvfs_GetIntOpt(vfs_t *pVFS, char *pszOpt, int *pValue);
58
59
60/*******************************************************************************
61* Structures and Typedefs *
62*******************************************************************************/
63/**
64 * mntopts_t: mount options table array
65 */
66static mntopt_t g_VBoxVFSMountOptions[] =
67{
68 /* Option Name Cancel Opt. Default Arg Flags Data */
69 { MNTOPT_VBOXVFS_UID, NULL, NULL, MO_HASVALUE, NULL },
70 { MNTOPT_VBOXVFS_GID, NULL, NULL, MO_HASVALUE, NULL }
71};
72
73/**
74 * mntopts_t: mount options table prototype
75 */
76static mntopts_t g_VBoxVFSMountTableProt =
77{
78 sizeof(g_VBoxVFSMountOptions) / sizeof(mntopt_t),
79 g_VBoxVFSMountOptions
80};
81
82/**
83 * vfsdef_t: driver specific mount options
84 */
85static vfsdef_t g_VBoxVFSDef =
86{
87 VFSDEF_VERSION,
88 DEVICE_NAME,
89 VBoxVFS_Init,
90 VSW_HASPROTO,
91 &g_VBoxVFSMountTableProt
92};
93
94/**
95 * modlfs: loadable file system
96 */
97static struct modlfs g_VBoxVFSLoadMod =
98{
99 &mod_fsops, /* extern from kernel */
100 DEVICE_DESC,
101 &g_VBoxVFSDef
102};
103
104/**
105 * modlinkage: export install/remove/info to the kernel
106 */
107static struct modlinkage g_VBoxVFSModLinkage =
108{
109 MODREV_1, /* loadable module system revision */
110 &g_VBoxVFSLoadMod,
111 NULL /* terminate array of linkage structures */
112};
113
114/**
115 * state info. for vboxvfs
116 */
117typedef struct
118{
119 /** Device Info handle. */
120 dev_info_t *pDip;
121 /** Driver Mutex. */
122 kmutex_t Mtx;
123} vboxvfs_state_t;
124
125
126/*******************************************************************************
127* Global Variables *
128*******************************************************************************/
129/** Opaque pointer to list of states. */
130static void *g_pVBoxVFSState;
131/** GCC C++ hack. */
132unsigned __gxx_personality_v0 = 0xdecea5ed;
133/** Global connection to the client. */
134VBSFCLIENT g_VBoxVFSClient;
135/** Global VFS Operations pointer. */
136vfsops_t *g_pVBoxVFS_vfsops;
137/** The file system type identifier. */
138static int g_VBoxVFSType;
139
140
141/**
142 * Kernel entry points
143 */
144int _init(void)
145{
146 LogFlow((DEVICE_NAME ":_init\n"));
147
148 int rc = ddi_soft_state_init(&g_pVBoxVFSState, sizeof(vboxvfs_state_t), 1);
149 if (!rc)
150 {
151 rc = mod_install(&g_VBoxVFSModLinkage);
152 if (rc)
153 ddi_soft_state_fini(&g_pVBoxVFSState);
154 }
155 return rc;
156}
157
158
159int _fini(void)
160{
161 LogFlow((DEVICE_NAME ":_fini\n"));
162
163 int rc = mod_remove(&g_VBoxVFSModLinkage);
164 if (!rc)
165 ddi_soft_state_fini(&g_pVBoxVFSState);
166 return rc;
167}
168
169
170int _info(struct modinfo *pModInfo)
171{
172 LogFlow((DEVICE_NAME ":_info\n"));
173
174 return mod_info(&g_VBoxVFSModLinkage, pModInfo);
175}
176
177
178static int VBoxVFS_Init(int fType, char *pszName)
179{
180 int rc;
181
182 LogFlow((DEVICE_NAME ":VBoxVFS_Init\n"));
183
184 /* Initialize the R0 guest library. */
185 rc = vboxInit();
186 if (VBOX_SUCCESS(rc))
187 {
188 /* Connect to the host service. */
189 rc = vboxConnect(&g_VBoxVFSClient);
190 if (VBOX_SUCCESS(rc))
191 {
192 /* Use UTF-8 encoding. */
193 rc = vboxCallSetUtf8 (&g_VBoxVFSClient);
194 if (VBOX_SUCCESS(rc))
195 {
196 /* Fill up VFS user entry points. */
197 static const fs_operation_def_t s_VBoxVFS_vfsops_template[] =
198 {
199 VFSNAME_MOUNT, { .vfs_mount = VBoxVFS_Mount },
200 VFSNAME_UNMOUNT, { .vfs_unmount = VBoxVFS_Unmount },
201 VFSNAME_ROOT, { .vfs_root = VBoxVFS_Root },
202 VFSNAME_STATVFS, { .vfs_statvfs = VBoxVFS_Statfs },
203 VFSNAME_VGET, { .vfs_vget = VBoxVFS_VGet },
204 VFSNAME_FREEVFS, { .vfs_freevfs = VBoxVFS_FreeVFS },
205 NULL, NULL
206 };
207
208 rc = vfs_setfsops(fType, s_VBoxVFS_vfsops_template, &g_pVBoxVFS_vfsops);
209 if (!rc)
210 {
211 /* Set VNode operations. */
212 rc = vn_make_ops(pszName, g_VBoxVFS_vnodeops_template, &g_pVBoxVFS_vnodeops);
213 if (!rc)
214 {
215 g_VBoxVFSType = fType;
216 LogFlow((DEVICE_NAME ":Successfully loaded vboxvfs.\n"));
217 return 0;
218 }
219 else
220 LogRel((DEVICE_NAME ":vn_make_ops failed. rc=%d\n", rc));
221 }
222 else
223 LogRel((DEVICE_NAME ":vfs_setfsops failed. rc=%d\n", rc));
224 }
225 else
226 {
227 LogRel((DEVICE_NAME ":vboxCallSetUtf8 failed. rc=%d\n", rc));
228 rc = EPROTO;
229 }
230 vboxDisconnect(&g_VBoxVFSClient);
231 }
232 else
233 {
234 LogRel((DEVICE_NAME ":Failed to connect to host! rc=%d\n", rc));
235 rc = ENXIO;
236 }
237 vboxUninit();
238 }
239 else
240 {
241 LogRel((DEVICE_NAME ":Failed to initialize R0 lib. rc=%d\n", rc));
242 rc = ENXIO;
243 }
244 return rc;
245}
246
247static int VBoxVFS_Mount(vfs_t *pVFS, vnode_t *pVNode, struct mounta *pMount, cred_t *pCred)
248{
249 int rc = 0;
250 int Uid = 0;
251 int Gid = 0;
252 char *pszShare = NULL;
253 size_t cbShare = NULL;
254 pathname_t PathName;
255 vboxvfs_vnode_t *pVNodeRoot = NULL;
256 vnode_t *pVNodeSpec = NULL;
257 vnode_t *pVNodeDev = NULL;
258 dev_t Dev = 0;
259 SHFLSTRING *pShflShareName = NULL;
260 RTFSOBJINFO FSInfo;
261 size_t cbShflShareName = 0;
262 vboxvfs_globinfo_t *pVBoxVFSGlobalInfo = NULL;
263 int AddrSpace = (pMount->flags & MS_SYSSPACE) ? UIO_SYSSPACE : UIO_USERSPACE;
264#if 0
265 caddr_t pData;
266 size_t cbData;
267 vboxvfs_mountinfo_t Args;
268#endif
269
270 LogFlow((DEVICE_NAME ":VBoxVFS_Mount\n"));
271
272 /* Check user credentials for mounting in the specified target. */
273 rc = secpolicy_fs_mount(pCred, pVNode, pVFS);
274 if (rc)
275 {
276 LogRel((DEVICE_NAME ":VBoxVFS_Mount: secpolicy_fs_mount failed! invalid credentials.rc=%d\n", rc));
277 return EPERM;
278 }
279
280 /* We can mount to only directories. */
281 if (pVNode->v_type != VDIR)
282 return ENOTDIR;
283
284 /* We don't support remounting. */
285 if (pMount->flags & MS_REMOUNT)
286 return ENOTSUP;
287
288 mutex_enter(&pVNode->v_lock);
289 if ( !(pMount->flags & MS_REMOUNT)
290 && !(pMount->flags & MS_OVERLAY)
291 && (pVNode->v_count != -1 || (pVNode->v_flag & VROOT)))
292 {
293 LogRel((DEVICE_NAME ":VBoxVFS_Mount: device busy.\n"));
294 mutex_exit(&pVNode->v_lock);
295 return EBUSY;
296 }
297 mutex_exit(&pVNode->v_lock);
298
299 /* From what I understood the options are already parsed at a higher level */
300 if ( (pMount->flags & MS_DATA)
301 && pMount->datalen > 0)
302 {
303 LogRel((DEVICE_NAME ":VBoxVFS_Mount: unparsed options not supported.\n"));
304 return EINVAL;
305 }
306
307 /* Will be removed eventually... */
308#if 0
309 /* Retreive arguments. */
310 bzero(&Args, sizeof(Args));
311 cbData = pMount->datalen;
312 pData = pMount->data;
313 if ( (pMount->flags & MS_DATA)
314 && pData != NULL
315 && cbData > 0)
316 {
317 if (cbData > sizeof(Args))
318 {
319 LogRel((DEVICE_NAME: "VBoxVFS_Mount: argument length too long. expected=%d. received=%d\n", sizeof(Args), cbData));
320 return EINVAL;
321 }
322
323 /* Copy arguments; they can be in kernel or user space. */
324 rc = ddi_copyin(pData, &Args, cbData, (pMount->flags & MS_SYSSPACE) ? FKIOCTL : 0);
325 if (rc)
326 {
327 LogRel((DEVICE_NAME: "VBoxVFS_Mount: ddi_copyin failed to copy arguments.rc=%d\n", rc));
328 return EFAULT;
329 }
330 }
331 else
332 {
333 cbData = 0;
334 pData = NULL;
335 }
336#endif
337
338 /* Get UID argument (optional). */
339 rc = vboxvfs_GetIntOpt(pVFS, MNTOPT_VBOXVFS_UID, &Uid);
340 if (rc < 0)
341 {
342 LogRel((DEVICE_NAME ":VBoxVFS_Mount: invalid uid value.\n"));
343 return EINVAL;
344 }
345
346 /* Get GID argument (optional). */
347 rc = vboxvfs_GetIntOpt(pVFS, MNTOPT_VBOXVFS_GID, &Gid);
348 if (rc < 0)
349 {
350 LogRel((DEVICE_NAME ":VBoxVFS_Mount: invalid gid value.\n"));
351 return EINVAL;
352 }
353
354 /* Get special (sharename). */
355 rc = pn_get(pMount->spec, AddrSpace, &PathName);
356 if (!rc)
357 {
358 /* Get the vnode for the special file for storing the device identifier and path. */
359 rc = lookupname(PathName.pn_path, AddrSpace, FOLLOW, NULLVPP, &pVNodeSpec);
360 if (!rc)
361 {
362 /* Check if user has permission to use the special file for mounting. */
363 rc = vboxvfs_CheckMountPerm(pVFS, pMount, pVNodeSpec, pCred);
364 VN_RELE(pVNodeSpec);
365 if (!rc)
366 {
367 Dev = pVNodeSpec->v_rdev;
368 memcpy(pszShare, PathName.pn_path, strlen(PathName.pn_path));
369 cbShare = strlen(pszShare);
370 }
371 else
372 LogRel((DEVICE_NAME ":VBoxVFS_Mount: invalid permissions to mount %s.rc=%d\n", pszShare, rc));
373 rc = EPERM;
374 }
375 else
376 LogRel((DEVICE_NAME ":VBoxVFS_Mount: failed to lookup sharename.rc=%d\n", rc));
377 rc = EINVAL;
378 }
379 else
380 {
381 LogRel((DEVICE_NAME ":VBoxVFS_Mount: failed to get special file path.rc=%d\n", rc));
382 rc = EINVAL;
383 }
384 pn_free(&PathName);
385
386 if (!rc)
387 return rc;
388
389 /* Get VNode of the special file being mounted. */
390 pVNodeDev = makespecvp(Dev, VBLK);
391 if (!IS_SWAPVP(pVNodeDev))
392 {
393 /* Open the vnode for mounting. */
394 rc = VOP_OPEN(&pVNodeDev, (pVFS->vfs_flag & VFS_RDONLY) ? FREAD : FREAD | FWRITE, pCred, NULL);
395 if (rc)
396 {
397 LogRel((DEVICE_NAME ":VBoxVFS_Mount: failed to mount.\n"));
398 rc = EINVAL;
399 }
400 }
401 else
402 {
403 LogRel((DEVICE_NAME ":VBoxVFS_Mount: cannot mount from swap.\n"));
404 rc = EINVAL;
405 }
406 if (!rc)
407 {
408 VN_RELE(pVNodeDev);
409 return rc;
410 }
411
412 /* Allocate the global info. structure. */
413 pVBoxVFSGlobalInfo = RTMemAlloc(sizeof(*pVBoxVFSGlobalInfo));
414 if (!pVBoxVFSGlobalInfo)
415 {
416 LogRel((DEVICE_NAME ":VBoxVFS_Mount: RTMemAlloc failed to alloc %d bytes for global struct.\n", sizeof(*pVBoxVFSGlobalInfo)));
417 return ENOMEM;
418 }
419
420 cbShflShareName = offsetof(SHFLSTRING, String.utf8) + cbShare + 1;
421 pShflShareName = RTMemAllocZ(cbShflShareName);
422 if (!pShflShareName)
423 {
424 RTMemFree(pVBoxVFSGlobalInfo);
425 LogRel((DEVICE_NAME ":VBoxVFS_Mount: RTMemAllocZ failed to alloc %d bytes for ShFlShareName.\n", cbShflShareName));
426 return ENOMEM;
427 }
428
429 pShflShareName->u16Length = cbShflShareName;
430 pShflShareName->u16Size = cbShflShareName + 1;
431 memcpy (pShflShareName->String.utf8, pszShare, cbShare + 1);
432
433 rc = vboxCallMapFolder(&g_VBoxVFSClient, pShflShareName, &pVBoxVFSGlobalInfo->Map);
434 RTMemFree(pShflShareName);
435 if (VBOX_FAILURE (rc))
436 {
437 RTMemFree(pVBoxVFSGlobalInfo);
438 LogRel((DEVICE_NAME ":VBoxVFS_Mount: vboxCallMapFolder failed rc=%d\n", rc));
439 return EPROTO;
440 }
441
442 /* @todo mutex for protecting the structure. */
443 pVBoxVFSGlobalInfo->Uid = Uid;
444 pVBoxVFSGlobalInfo->Gid = Gid;
445 pVBoxVFSGlobalInfo->pVFS = pVFS;
446 pVBoxVFSGlobalInfo->pVNodeDev = pVNodeDev;
447 pVFS->vfs_data = pVBoxVFSGlobalInfo;
448 pVFS->vfs_fstype = g_VBoxVFSType;
449 pVFS->vfs_dev = Dev;
450 vfs_make_fsid(&pVFS->vfs_fsid, Dev, g_VBoxVFSType);
451
452 /* Allocate root vboxvfs_vnode_t object */
453 pVNodeRoot = RTMemAlloc(sizeof(*pVNodeRoot));
454 if (!pVNodeRoot)
455 {
456 LogRel((DEVICE_NAME ":VBoxVFS_Mount: RTMemAlloc failed to alloc %d bytes for root node.\n", sizeof(*pVNodeRoot)));
457 return ENOMEM;
458 }
459
460 /* Initialize the mutex */
461 mutex_init(&pVNodeRoot->MtxContents, "VNodeMtx", MUTEX_DEFAULT, NULL);
462
463 /* Allocate root path */
464 pVNodeRoot->pPath = RTMemAllocZ(sizeof(SHFLSTRING) + 1);
465 if (!pVNodeRoot->pPath)
466 {
467 LogRel((DEVICE_NAME ":VBoxVFS_Mount: RTMemAllocZ failed to alloc %d bytes for root path.\n", sizeof(SHFLSTRING) + 1));
468 return ENOMEM;
469 }
470
471 /* Initialize root path */
472 pVNodeRoot->pPath->u16Length = 1;
473 pVNodeRoot->pPath->u16Size = 2;
474 pVNodeRoot->pPath->String.utf8[0] = '/';
475 pVNodeRoot->pPath->String.utf8[1] = '\0';
476
477 /* Stat root node info from host */
478 rc = vboxvfs_Stat(__func__, pVBoxVFSGlobalInfo, pVNodeRoot->pPath, &FSInfo, B_FALSE);
479 if (rc)
480 {
481 LogRel((DEVICE_NAME ":VBoxVFS_Mount: vboxvfs_Stat failed rc(errno)=%d\n", rc));
482 return rc;
483 }
484
485 /* Initialize the root vboxvfs_node_t object */
486 vboxvfs_InitVNode(pVBoxVFSGlobalInfo, pVNodeRoot, &FSInfo);
487
488 return 0;
489}
490
491static int VBoxVFS_Unmount(vfs_t *pVFS, int fUnmount, cred_t *pCred)
492{
493 int rc;
494 vboxvfs_globinfo_t *pVBoxVFSGlobalInfo;
495
496 LogFlow((DEVICE_NAME ":VBoxVFS_Unmount.\n"));
497
498 /* Check if user can unmount. */
499 rc = secpolicy_fs_unmount(pCred, pVFS);
500 if (rc)
501 {
502 LogRel((DEVICE_NAME ":VBoxVFS_Unmount: insufficient privileges to unmount.rc=%d\n", rc));
503 return EPERM;
504 }
505
506 if (fUnmount & MS_FORCE)
507 pVFS->vfs_flag |= VFS_UNMOUNTED;
508
509 /* @todo implement ref-counting of active vnodes & check for busy state here. */
510 /* @todo mutex protection needed here */
511 pVBoxVFSGlobalInfo = VFS_TO_VBOXVFS(pVFS);
512
513 rc = vboxCallUnmapFolder(&g_VBoxVFSClient, &pVBoxVFSGlobalInfo->Map);
514 if (VBOX_FAILURE(rc))
515 LogRel((DEVICE_NAME ":VBoxVFS_Unmount: failed to unmap shared folder. rc=%d\n", rc));
516
517 VN_RELE(VBOXVN_TO_VN(pVBoxVFSGlobalInfo->pVNodeRoot));
518
519 RTMemFree(pVBoxVFSGlobalInfo);
520 pVFS->vfs_data = NULL;
521
522 return 0;
523}
524
525static int VBoxVFS_Root(vfs_t *pVFS, vnode_t **ppVNode)
526{
527 vboxvfs_globinfo_t *pVBoxVFSGlobalInfo = VFS_TO_VBOXVFS(pVFS);
528 *ppVNode = VBOXVN_TO_VN(pVBoxVFSGlobalInfo->pVNodeRoot);
529 VN_HOLD(*ppVNode);
530
531 return 0;
532}
533
534static int VBoxVFS_Statfs(register vfs_t *pVFS, struct statvfs64 *pStat)
535{
536 SHFLVOLINFO VolumeInfo;
537 uint32_t cbBuffer;
538 vboxvfs_globinfo_t *pVBoxVFSGlobalInfo;
539 dev32_t Dev32;
540 int rc;
541
542 pVBoxVFSGlobalInfo = VFS_TO_VBOXVFS(pVFS);
543 cbBuffer = sizeof(VolumeInfo);
544 rc = vboxCallFSInfo(&g_VBoxVFSClient, &pVBoxVFSGlobalInfo->Map, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbBuffer,
545 (PSHFLDIRINFO)&VolumeInfo);
546 if (VBOX_FAILURE(rc))
547 return RTErrConvertToErrno(rc);
548
549 bzero(pStat, sizeof(*pStat));
550 cmpldev(&Dev32, pVFS->vfs_dev);
551 pStat->f_fsid = Dev32;
552 pStat->f_flag = vf_to_stf(pVFS->vfs_flag);
553 pStat->f_bsize = VolumeInfo.ulBytesPerAllocationUnit;
554 pStat->f_frsize = VolumeInfo.ulBytesPerAllocationUnit;
555 pStat->f_bfree = VolumeInfo.ullAvailableAllocationBytes / VolumeInfo.ulBytesPerAllocationUnit;
556 pStat->f_bavail = VolumeInfo.ullAvailableAllocationBytes / VolumeInfo.ulBytesPerAllocationUnit;
557 pStat->f_blocks = VolumeInfo.ullTotalAllocationBytes / VolumeInfo.ulBytesPerAllocationUnit;
558 pStat->f_files = 1000;
559 pStat->f_ffree = 1000; /* don't return 0 here since the guest may think that it is not possible to create any more files */
560 pStat->f_namemax = 255; /* @todo is this correct?? */
561
562 strlcpy(pStat->f_basetype, vfssw[pVFS->vfs_fstype].vsw_name, sizeof(pStat->f_basetype));
563 strlcpy(pStat->f_fstr, DEVICE_NAME, sizeof(pStat->f_fstr));
564
565 return 0;
566}
567
568static int VBoxVFS_VGet(vfs_t *pVFS, vnode_t **ppVNode, struct fid *pFid)
569{
570 /* -- TODO -- */
571 return 0;
572}
573
574static void VBoxVFS_FreeVFS(vfs_t *pVFS)
575{
576 vboxDisconnect(&g_VBoxVFSClient);
577 vboxUninit();
578}
579
580static int vboxvfs_CheckMountPerm(vfs_t *pVFS, struct mounta *pMount, vnode_t *pVNodeSpec, cred_t *pCred)
581{
582 /* Check if user has the rights to mount the special file. */
583 int fOpen = FREAD | FWRITE;
584 int fAccess = VREAD | VWRITE;
585 int rc;
586
587 if (pVNodeSpec->v_type != VBLK)
588 return ENOTBLK;
589
590 if ( (pVFS->vfs_flag & VFS_RDONLY)
591 || (pMount->flags & MS_RDONLY))
592 {
593 fOpen = FREAD;
594 fAccess = VREAD;
595 }
596
597 rc = VOP_ACCESS(pVNodeSpec, fAccess, 0, pCred, NULL /* caller_context */);
598 if (!rc)
599 rc = secpolicy_spec_open(pCred, pVNodeSpec, fOpen);
600
601 return rc;
602}
603
604static int vboxvfs_GetIntOpt(vfs_t *pVFS, char *pszOpt, int *pValue)
605{
606 int rc;
607 long Val;
608 char *pchOpt = NULL;
609 char *pchEnd = NULL;
610
611 rc = vfs_optionisset(pVFS, pszOpt, &pchOpt);
612 if (rc)
613 {
614 rc = ddi_strtol(pchOpt, &pchEnd, 10 /* base */, &Val);
615 if ( !rc
616 && Val > INT_MIN
617 && Val < INT_MAX
618 && pchEnd == pchOpt + strlen(pchOpt))
619 {
620 *pValue = (int)Val;
621 return 0;
622 }
623 return -1;
624 }
625 return 1;
626}
627
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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