/** @copydoc fuse_operations::write */ static int vboxfuseOp_write(const char *pszPath, const char *pbBuf, size_t cbBuf, off_t offFile, struct fuse_file_info *pInfo) { /* paranoia */ AssertReturn((int)cbBuf >= 0, -EINVAL); AssertReturn((unsigned)cbBuf == cbBuf, -EINVAL); AssertReturn(offFile >= 0, -EINVAL); AssertReturn((off_t)(offFile + cbBuf) >= offFile, -EINVAL); PVBOXFUSENODE pNode = (PVBOXFUSENODE)(uintptr_t)pInfo->fh; AssertPtr(pNode); switch (pNode->enmType) { case VBOXFUSETYPE_DIRECTORY: return -ENOTSUP; case VBOXFUSETYPE_FLAT_IMAGE: { PVBOXFUSEFLATIMAGE pFlatImage = (PVBOXFUSEFLATIMAGE)(uintptr_t)pInfo->fh; LogFlow(("vboxfuseOp_write: offFile=%#llx cbBuf=%#zx pszPath=\"%s\"\n", (uint64_t)offFile, cbBuf, pszPath)); vboxfuseNodeLock(&pFlatImage->Node); int rc; if ((off_t)(offFile + cbBuf) < offFile) rc = -EINVAL; else if (offFile >= pFlatImage->Node.cbPrimary) rc = 0; else if (!cbBuf) rc = 0; else { /* Adjust for EOF. */ if ((off_t)(offFile + cbBuf) >= pFlatImage->Node.cbPrimary) cbBuf = pFlatImage->Node.cbPrimary - offFile; /* * Aligned write? */ int rc2; if ( !(offFile & VBOXFUSE_MIN_SIZE_MASK_OFF) && !(cbBuf & VBOXFUSE_MIN_SIZE_MASK_OFF)) rc2 = VDWrite(pFlatImage->pDisk, offFile, pbBuf, cbBuf); else { /* * Unaligned write - lots of extra work. */ uint8_t abBlock[VBOXFUSE_MIN_SIZE]; if (((offFile + cbBuf) & VBOXFUSE_MIN_SIZE_MASK_BLK) == (offFile & VBOXFUSE_MIN_SIZE_MASK_BLK)) { /* a single partial block. */ rc2 = VDRead(pFlatImage->pDisk, offFile & VBOXFUSE_MIN_SIZE_MASK_BLK, abBlock, VBOXFUSE_MIN_SIZE); if (RT_SUCCESS(rc2)) { memcpy(&abBlock[offFile & VBOXFUSE_MIN_SIZE_MASK_OFF], pbBuf, cbBuf); /* Update the block */ rc2 = VDWrite(pFlatImage->pDisk, offFile & VBOXFUSE_MIN_SIZE_MASK_BLK, abBlock, VBOXFUSE_MIN_SIZE); } } else { /* read unaligned head. */ rc2 = VINF_SUCCESS; if (offFile & VBOXFUSE_MIN_SIZE_MASK_OFF) { rc2 = VDRead(pFlatImage->pDisk, offFile & VBOXFUSE_MIN_SIZE_MASK_BLK, abBlock, VBOXFUSE_MIN_SIZE); if (RT_SUCCESS(rc2)) { size_t cbCopy = VBOXFUSE_MIN_SIZE - (offFile & VBOXFUSE_MIN_SIZE_MASK_OFF); memcpy(&abBlock[offFile & VBOXFUSE_MIN_SIZE_MASK_OFF], pbBuf, cbCopy); pbBuf += cbCopy; offFile += cbCopy; cbBuf -= cbCopy; rc2 = VDWrite(pFlatImage->pDisk, offFile & VBOXFUSE_MIN_SIZE_MASK_BLK, abBlock, VBOXFUSE_MIN_SIZE); } } /* write the middle. */ Assert(!(offFile & VBOXFUSE_MIN_SIZE_MASK_OFF)); if (cbBuf >= VBOXFUSE_MIN_SIZE && RT_SUCCESS(rc2)) { size_t cbWrite = cbBuf & VBOXFUSE_MIN_SIZE_MASK_BLK; rc2 = VDWrite(pFlatImage->pDisk, offFile, pbBuf, cbWrite); if (RT_SUCCESS(rc2)) { pbBuf += cbWrite; offFile += cbWrite; cbBuf -= cbWrite; } } /* unaligned tail write. */ Assert(cbBuf < VBOXFUSE_MIN_SIZE); Assert(!(offFile & VBOXFUSE_MIN_SIZE_MASK_OFF)); if (cbBuf && RT_SUCCESS(rc2)) { rc2 = VDRead(pFlatImage->pDisk, offFile, abBlock, VBOXFUSE_MIN_SIZE); if (RT_SUCCESS(rc2)) { memcpy(&abBlock[0], pbBuf, cbBuf); rc2 = VDWrite(pFlatImage->pDisk, offFile, abBlock, VBOXFUSE_MIN_SIZE); } } } } /* convert the return code */ if (RT_SUCCESS(rc2)) rc = cbBuf; else rc = -RTErrConvertToErrno(rc2); } vboxfuseNodeUnlock(&pFlatImage->Node); return rc; } case VBOXFUSETYPE_CONTROL_PIPE: return -ENOTSUP; default: AssertMsgFailed(("%s\n", pszPath)); return -EDOOFUS; } }
/** * Module event handler. * * @param pMod The module structure. * @param enmEventType The event type (modeventtype_t). * @param pvArg Module argument. NULL. * * @return 0 on success, errno.h status code on failure. */ static int VBoxDrvFreeBSDModuleEvent(struct module *pMod, int enmEventType, void *pvArg) { int rc; switch (enmEventType) { case MOD_LOAD: rc = VBoxDrvFreeBSDLoad(); break; case MOD_UNLOAD: mtx_unlock(&Giant); rc = VBoxDrvFreeBSDUnload(); mtx_lock(&Giant); break; case MOD_SHUTDOWN: case MOD_QUIESCE: default: return EOPNOTSUPP; } if (RT_SUCCESS(rc)) return 0; return RTErrConvertToErrno(rc); }
static int vgdrvFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd) #endif { int rc; PVBOXGUESTSESSION pSession; LogFlow(("vgdrvFreeBSDOpen:\n")); /* * Try grab it (we don't grab the giant, remember). */ if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, (void *)0x42, NULL)) return EBUSY; /* * Create a new session. */ rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession); if (RT_SUCCESS(rc)) { if (ASMAtomicCmpXchgPtr(&pDev->si_drv1, pSession, (void *)0x42)) { Log(("vgdrvFreeBSDOpen: success - g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf())); ASMAtomicIncU32(&cUsers); return 0; } VGDrvCommonCloseSession(&g_DevExt, pSession); } LogRel(("vgdrvFreeBSDOpen: failed. rc=%d\n", rc)); return RTErrConvertToErrno(rc); }
/** * * @returns 0 on success, errno on failure. * EBUSY if the device is used by someone else. * @param pDev The device node. * @param fOpen The open flags. * @param pTd The thread. * @param iDevType ??? */ static int vboxdrvFreeBSDOpenCommon(struct cdev *pDev, int fOpen, int iDevtype, struct thread *pTd, bool fUnrestricted) { PSUPDRVSESSION pSession; int rc; /* * Let's be a bit picky about the flags... */ if (fOpen != (FREAD | FWRITE /*=O_RDWR*/)) { Log(("VBoxDrvFreeBSDOpen: fOpen=%#x expected %#x\n", fOpen, O_RDWR)); return EINVAL; } /* * Create a new session. */ rc = supdrvCreateSession(&g_VBoxDrvFreeBSDDevExt, true /* fUser */, fUnrestricted, &pSession); if (RT_SUCCESS(rc)) { /** @todo get (r)uid and (r)gid. pSession->Uid = stuff; pSession->Gid = stuff; */ devfs_set_cdevpriv(pSession, VBoxDrvFreeBSDDtr); Log(("VBoxDrvFreeBSDOpen: pSession=%p\n", pSession)); ASMAtomicIncU32(&g_cUsers); return 0; } return RTErrConvertToErrno(rc); }
/** * Errno conversion wrapper around vboxfuseTreeLookup(). * * @returns 0 on success, negated errno on failure. * @param pszPath The path to the file. * @param ppNode Where to return the node. */ static int vboxfuseTreeLookupErrno(const char *pszPath, PVBOXFUSENODE *ppNode) { int rc = vboxfuseTreeLookup(pszPath, ppNode); if (RT_SUCCESS(rc)) return 0; return -RTErrConvertToErrno(rc); }
int sf_get_volume_info(struct super_block *sb, STRUCT_STATFS *stat) { struct sf_glob_info *sf_g; SHFLVOLINFO SHFLVolumeInfo; uint32_t cbBuffer; int rc; sf_g = GET_GLOB_INFO(sb); cbBuffer = sizeof(SHFLVolumeInfo); rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, &cbBuffer, (PSHFLDIRINFO)&SHFLVolumeInfo); if (RT_FAILURE(rc)) return -RTErrConvertToErrno(rc); stat->f_type = NFS_SUPER_MAGIC; /* XXX vboxsf type? */ stat->f_bsize = SHFLVolumeInfo.ulBytesPerAllocationUnit; stat->f_blocks = SHFLVolumeInfo.ullTotalAllocationBytes / SHFLVolumeInfo.ulBytesPerAllocationUnit; stat->f_bfree = SHFLVolumeInfo.ullAvailableAllocationBytes / SHFLVolumeInfo.ulBytesPerAllocationUnit; stat->f_bavail = SHFLVolumeInfo.ullAvailableAllocationBytes / SHFLVolumeInfo.ulBytesPerAllocationUnit; stat->f_files = 1000; stat->f_ffree = 1000; /* don't return 0 here since the guest may think * that it is not possible to create any more files */ stat->f_fsid.val[0] = 0; stat->f_fsid.val[1] = 0; stat->f_namelen = 255; return 0; }
/** * Initialize module. * * @returns appropriate status code. */ static int __init VBoxNetAdpLinuxInit(void) { int rc; /* * Initialize IPRT. */ rc = RTR0Init(0); if (RT_SUCCESS(rc)) { Log(("VBoxNetAdpLinuxInit\n")); rc = vboxNetAdpInit(); if (RT_SUCCESS(rc)) { rc = misc_register(&g_CtlDev); if (rc) { printk(KERN_ERR "VBoxNetAdp: Can't register " VBOXNETADP_CTL_DEV_NAME " device! rc=%d\n", rc); return rc; } LogRel(("VBoxNetAdp: Successfully started.\n")); return 0; } else LogRel(("VBoxNetAdp: failed to register vboxnet0 device (rc=%d)\n", rc)); } else LogRel(("VBoxNetAdp: failed to initialize IPRT (rc=%d)\n", rc)); return -RTErrConvertToErrno(rc); }
/** * Kernel entry points */ int _init(void) { LogFunc((DEVICE_NAME ":_init\n")); /* * Prevent module autounloading. */ modctl_t *pModCtl = mod_getctl(&g_VBoxNetAdpSolarisModLinkage); if (pModCtl) pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD; else LogRel((DEVICE_NAME ":failed to disable autounloading!\n")); /* * Initialize IPRT. */ int rc = RTR0Init(0); if (RT_SUCCESS(rc)) { rc = mod_install(&g_VBoxNetAdpSolarisModLinkage); if (!rc) return rc; LogRel((DEVICE_NAME ":mod_install failed. rc=%d\n", rc)); RTR0Term(); } else LogRel((DEVICE_NAME ":failed to initialize IPRT (rc=%d)\n", rc)); return RTErrConvertToErrno(rc); }
/** * Rename a regular file / directory. * * @param old_parent inode of the old parent directory * @param old_dentry old directory cache entry * @param new_parent inode of the new parent directory * @param new_dentry new directory cache entry * @returns 0 on success, Linux error code otherwise */ static int sf_rename(struct inode *old_parent, struct dentry *old_dentry, struct inode *new_parent, struct dentry *new_dentry) { int err = 0, rc = VINF_SUCCESS; struct sf_glob_info *sf_g = GET_GLOB_INFO(old_parent->i_sb); TRACE(); if (sf_g != GET_GLOB_INFO(new_parent->i_sb)) { LogFunc(("rename with different roots\n")); err = -EINVAL; } else { struct sf_inode_info *sf_old_i = GET_INODE_INFO(old_parent); struct sf_inode_info *sf_new_i = GET_INODE_INFO(new_parent); /* As we save the relative path inside the inode structure, we need to change this if the rename is successful. */ struct sf_inode_info *sf_file_i = GET_INODE_INFO(old_dentry->d_inode); SHFLSTRING *old_path; SHFLSTRING *new_path; BUG_ON(!sf_old_i); BUG_ON(!sf_new_i); BUG_ON(!sf_file_i); old_path = sf_file_i->path; err = sf_path_from_dentry(__func__, sf_g, sf_new_i, new_dentry, &new_path); if (err) LogFunc(("failed to create new path\n")); else { int fDir = ((old_dentry->d_inode->i_mode & S_IFDIR) != 0); rc = vboxCallRename(&client_handle, &sf_g->map, old_path, new_path, fDir ? 0 : SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS); if (RT_SUCCESS(rc)) { kfree(old_path); sf_new_i->force_restat = 1; sf_old_i->force_restat = 1; /* XXX: needed? */ /* Set the new relative path in the inode. */ sf_file_i->path = new_path; } else { LogFunc(("vboxCallRename failed rc=%Rrc\n", rc)); err = -RTErrConvertToErrno(rc); kfree(new_path); } } } return err; }
/** * Module event handler, called from netgraph subsystem. */ static int vboxnetflt_modevent(struct module *pMod, int enmEventType, void *pvArg) { int rc; Log(("VBoxNetFltFreeBSDModuleEvent\n")); switch (enmEventType) { case MOD_LOAD: rc = RTR0Init(0); if (RT_FAILURE(rc)) { printf("RTR0Init failed %d\n", rc); return RTErrConvertToErrno(rc); } memset(&g_VBoxNetFltGlobals, 0, sizeof(VBOXNETFLTGLOBALS)); rc = vboxNetFltInitGlobalsAndIdc(&g_VBoxNetFltGlobals); if (RT_FAILURE(rc)) { printf("vboxNetFltInitGlobalsAndIdc failed %d\n", rc); return RTErrConvertToErrno(rc); } /* No MODULE_VERSION in ng_ether so we can't MODULE_DEPEND it */ kern_kldload(curthread, "ng_ether", NULL); break; case MOD_UNLOAD: rc = vboxNetFltTryDeleteIdcAndGlobals(&g_VBoxNetFltGlobals); memset(&g_VBoxNetFltGlobals, 0, sizeof(VBOXNETFLTGLOBALS)); RTR0Term(); break; case MOD_SHUTDOWN: case MOD_QUIESCE: default: return EOPNOTSUPP; } if (RT_SUCCESS(rc)) return 0; return RTErrConvertToErrno(rc); }
/** @copydoc fuse_operations::symlink */ static int vboxfuseOp_symlink(const char *pszDst, const char *pszPath) { /* * "Interface" for mounting a image. */ int rc = vboxfuseFlatImageCreate(pszPath, pszDst, NULL); if (RT_SUCCESS(rc)) { Log(("vboxfuseOp_symlink: \"%s\" => \"%s\" SUCCESS!\n", pszPath, pszDst)); return 0; } LogFlow(("vboxfuseOp_symlink: \"%s\" => \"%s\" rc=%Rrc\n", pszPath, pszDst, rc)); return -RTErrConvertToErrno(rc); }
static int VBoxDrvFreeBSDOpen(struct cdev *pDev, int fOpen, struct thread *pTd, int iFd) #endif { PSUPDRVSESSION pSession; int rc; #if __FreeBSD_version < 800062 Log(("VBoxDrvFreeBSDOpen: fOpen=%#x iUnit=%d\n", fOpen, minor2unit(minor(pDev)))); #else Log(("VBoxDrvFreeBSDOpen: fOpen=%#x iUnit=%d\n", fOpen, minor(dev2udev(pDev)))); #endif /* * Let's be a bit picky about the flags... */ if (fOpen != (FREAD|FWRITE /*=O_RDWR*/)) { Log(("VBoxDrvFreeBSDOpen: fOpen=%#x expected %#x\n", fOpen, O_RDWR)); return EINVAL; } /* * Try grab it (we don't grab the giant, remember). */ if (!ASMAtomicCmpXchgPtr(&pDev->si_drv1, (void *)0x42, NULL)) return EBUSY; /* * Create a new session. */ rc = supdrvCreateSession(&g_VBoxDrvFreeBSDDevExt, true /* fUser */, &pSession); if (RT_SUCCESS(rc)) { /** @todo get (r)uid and (r)gid. pSession->Uid = stuff; pSession->Gid = stuff; */ if (ASMAtomicCmpXchgPtr(&pDev->si_drv1, pSession, (void *)0x42)) { ASMAtomicIncU32(&g_cUsers); return 0; } OSDBGPRINT(("VBoxDrvFreeBSDOpen: si_drv1=%p, expected 0x42!\n", pDev->si_drv1)); supdrvCloseSession(&g_VBoxDrvFreeBSDDevExt, pSession); } return RTErrConvertToErrno(rc); }
status_t VBoxGuestDeskbarView::_Init(BMessage *archive) { BString toolTipText; toolTipText << VBOX_PRODUCT << " Guest Additions "; toolTipText << VBOX_VERSION_MAJOR << "." << VBOX_VERSION_MINOR << "." << VBOX_VERSION_BUILD; toolTipText << "r" << VBOX_SVN_REV; SetToolTip(toolTipText.String()); image_info info; if (our_image(info) != B_OK) return B_ERROR; BFile file(info.name, B_READ_ONLY); if (file.InitCheck() < B_OK) return B_ERROR; BResources resources(&file); if (resources.InitCheck() < B_OK) return B_ERROR; const void *data = NULL; size_t size; //data = resources.LoadResource(B_VECTOR_ICON_TYPE, // kNetworkStatusNoDevice + i, &size); data = resources.LoadResource('data', 400, &size); if (data != NULL) { BMemoryIO mem(data, size); fIcon = BTranslationUtils::GetBitmap(&mem); } int rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE); if (RT_SUCCESS(rc)) { rc = VbglR3Init(); if (RT_SUCCESS(rc)) { fClipboardService = new VBoxClipboardService(); fDisplayService = new VBoxDisplayService(); } else LogRel(("VBoxGuestDeskbarView::_init VbglR3Init failed. rc=%d\n", rc)); } else LogRel(("VBoxGuestDeskbarView::_init RTR3InitDll failed. rc=%d\n", rc)); return RTErrConvertToErrno(rc); }
/** * Remove a regular file / directory. * * @param parent inode of the directory * @param dentry directory cache entry * @param fDirectory true if directory, false otherwise * @returns 0 on success, Linux error code otherwise */ static int sf_unlink_aux(struct inode *parent, struct dentry *dentry, int fDirectory) { int rc, err; struct sf_glob_info *sf_g = GET_GLOB_INFO(parent->i_sb); struct sf_inode_info *sf_i = GET_INODE_INFO(parent); SHFLSTRING *path; uint32_t fFlags; TRACE(); BUG_ON(!sf_g); err = sf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path); if (err) goto fail0; fFlags = fDirectory ? SHFL_REMOVE_DIR : SHFL_REMOVE_FILE; if ( dentry && dentry->d_inode && ((dentry->d_inode->i_mode & S_IFLNK) == S_IFLNK)) fFlags |= SHFL_REMOVE_SYMLINK; rc = vboxCallRemove(&client_handle, &sf_g->map, path, fFlags); if (RT_FAILURE(rc)) { LogFunc(("(%d): vboxCallRemove(%s) failed rc=%Rrc\n", fDirectory, path->String.utf8, rc)); err = -RTErrConvertToErrno(rc); goto fail1; } /* directory access/change time changed */ sf_i->force_restat = 1; /* directory content changed */ sf_i->force_reread = 1; err = 0; fail1: kfree(path); fail0: return err; }
/** * Converts a VBox status code to a linux error code. * * @returns corresponding negative linux error code. * @param rc supdrv error code (SUPDRV_ERR_* defines). */ static int vboxguestLinuxConvertToNegErrno(int rc) { if ( rc > -1000 && rc < 1000) return -RTErrConvertToErrno(rc); switch (rc) { case VERR_HGCM_SERVICE_NOT_FOUND: return -ESRCH; case VINF_HGCM_CLIENT_REJECTED: return 0; case VERR_HGCM_INVALID_CMD_ADDRESS: return -EFAULT; case VINF_HGCM_ASYNC_EXECUTE: return 0; case VERR_HGCM_INTERNAL: return -EPROTO; case VERR_HGCM_INVALID_CLIENT_ID: return -EINVAL; case VINF_HGCM_SAVE_STATE: return 0; /* No reason to return this to a guest */ // case VERR_HGCM_SERVICE_EXISTS: return -EEXIST; default: AssertMsgFailed(("Unhandled error code %Rrc\n", rc)); return -EPROTO; } }
/** * Driver open hook. * * @param name The name of the device as returned by publish_devices. * @param flags Open flags. * @param cookie Where to store the session pointer. * * @return Haiku status code. */ static status_t vgdrvHaikuOpen(const char *name, uint32 flags, void **cookie) { int rc; PVBOXGUESTSESSION pSession; LogFlow((DRIVER_NAME ":vgdrvHaikuOpen\n")); /* * Create a new session. */ rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession); if (RT_SUCCESS(rc)) { Log((DRIVER_NAME ":vgdrvHaikuOpen success: g_DevExt=%p pSession=%p rc=%d pid=%d\n",&g_DevExt, pSession, rc,(int)RTProcSelf())); ASMAtomicIncU32(&cUsers); *cookie = pSession; return B_OK; } LogRel((DRIVER_NAME ":vgdrvHaikuOpen: failed. rc=%d\n", rc)); return RTErrConvertToErrno(rc); }
/** * Kernel entry points */ int _init(void) { LogFlowFunc((VIRTIOLOGNAME ":_init\n")); /* * Prevent module autounloading. */ modctl_t *pModCtl = mod_getctl(&g_VirtioNetModLinkage); if (pModCtl) pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD; else LogRel((VIRTIOLOGNAME ":failed to disable autounloading!\n")); /* * Initialize IPRT. */ int rc = RTR0Init(0); if (RT_SUCCESS(rc)) { /* * Initialize Solaris specific globals here. */ mac_init_ops(&g_VirtioNetDevOps, DEVICE_NAME); rc = mod_install(&g_VirtioNetModLinkage); if (!rc) return rc; LogRel((VIRTIOLOGNAME ":mod_install failed. rc=%d\n", rc)); mac_fini_ops(&g_VirtioNetDevOps); RTR0Term(); return rc; } else LogRel((VIRTIOLOGNAME ":failed to initialize IPRT (rc=%d)\n", rc)); return RTErrConvertToErrno(rc); }
/** * Open a regular file. * * @param inode the inode * @param file the file * @returns 0 on success, Linux error code otherwise */ static int sf_reg_open(struct inode *inode, struct file *file) { int rc, rc_linux = 0; struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb); struct sf_inode_info *sf_i = GET_INODE_INFO(inode); struct sf_reg_info *sf_r; SHFLCREATEPARMS params; TRACE(); BUG_ON(!sf_g); BUG_ON(!sf_i); LogFunc(("open %s\n", sf_i->path->String.utf8)); sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL); if (!sf_r) { LogRelFunc(("could not allocate reg info\n")); return -ENOMEM; } /* Already open? */ if (sf_i->handle != SHFL_HANDLE_NIL) { /* * This inode was created with sf_create_aux(). Check the CreateFlags: * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure * about the access flags (SHFL_CF_ACCESS_*). */ sf_i->force_restat = 1; sf_r->handle = sf_i->handle; sf_i->handle = SHFL_HANDLE_NIL; sf_i->file = file; file->private_data = sf_r; return 0; } RT_ZERO(params); params.Handle = SHFL_HANDLE_NIL; /* We check the value of params.Handle afterwards to find out if * the call succeeded or failed, as the API does not seem to cleanly * distinguish error and informational messages. * * Furthermore, we must set params.Handle to SHFL_HANDLE_NIL to * make the shared folders host service use our fMode parameter */ if (file->f_flags & O_CREAT) { LogFunc(("O_CREAT set\n")); params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW; /* We ignore O_EXCL, as the Linux kernel seems to call create beforehand itself, so O_EXCL should always fail. */ if (file->f_flags & O_TRUNC) { LogFunc(("O_TRUNC set\n")); params.CreateFlags |= ( SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACCESS_WRITE); } else params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS; } else { params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW; if (file->f_flags & O_TRUNC) { LogFunc(("O_TRUNC set\n")); params.CreateFlags |= ( SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACCESS_WRITE); } } if (!(params.CreateFlags & SHFL_CF_ACCESS_READWRITE)) { switch (file->f_flags & O_ACCMODE) { case O_RDONLY: params.CreateFlags |= SHFL_CF_ACCESS_READ; break; case O_WRONLY: params.CreateFlags |= SHFL_CF_ACCESS_WRITE; break; case O_RDWR: params.CreateFlags |= SHFL_CF_ACCESS_READWRITE; break; default: BUG (); } } if (file->f_flags & O_APPEND) { LogFunc(("O_APPEND set\n")); params.CreateFlags |= SHFL_CF_ACCESS_APPEND; } params.Info.Attr.fMode = inode->i_mode; LogFunc(("sf_reg_open: calling vboxCallCreate, file %s, flags=%#x, %#x\n", sf_i->path->String.utf8 , file->f_flags, params.CreateFlags)); rc = vboxCallCreate(&client_handle, &sf_g->map, sf_i->path, ¶ms); if (RT_FAILURE(rc)) { LogFunc(("vboxCallCreate failed flags=%d,%#x rc=%Rrc\n", file->f_flags, params.CreateFlags, rc)); kfree(sf_r); return -RTErrConvertToErrno(rc); } if (SHFL_HANDLE_NIL == params.Handle) { switch (params.Result) { case SHFL_PATH_NOT_FOUND: case SHFL_FILE_NOT_FOUND: rc_linux = -ENOENT; break; case SHFL_FILE_EXISTS: rc_linux = -EEXIST; break; default: break; } } sf_i->force_restat = 1; sf_r->handle = params.Handle; sf_i->file = file; file->private_data = sf_r; return rc_linux; }
/** * Kernel entry points */ int _init(void) { LogFlowFunc((DEVICE_NAME ":_init\n")); /* * Prevent module autounloading. */ modctl_t *pModCtl = mod_getctl(&g_VBoxDrvSolarisModLinkage); if (pModCtl) pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD; else LogRel((DEVICE_NAME ":failed to disable autounloading!\n")); /* * Initialize IPRT R0 driver, which internally calls OS-specific r0 init. */ int rc = RTR0Init(0); if (RT_SUCCESS(rc)) { /* * Initialize the device extension */ rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION)); if (RT_SUCCESS(rc)) { /* * Initialize the session hash table. */ memset(g_apSessionHashTab, 0, sizeof(g_apSessionHashTab)); rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvSol"); if (RT_SUCCESS(rc)) { rc = ddi_soft_state_init(&g_pVBoxDrvSolarisState, sizeof(vbox_devstate_t), 8); if (!rc) { rc = mod_install(&g_VBoxDrvSolarisModLinkage); if (!rc) return rc; /* success */ ddi_soft_state_fini(&g_pVBoxDrvSolarisState); LogRel((DEVICE_NAME ":mod_install failed! rc=%d\n", rc)); } else LogRel((DEVICE_NAME ":failed to initialize soft state.\n")); RTSpinlockDestroy(g_Spinlock); g_Spinlock = NIL_RTSPINLOCK; } else { LogRel((DEVICE_NAME ":VBoxDrvSolarisAttach: RTSpinlockCreate failed\n")); rc = RTErrConvertToErrno(rc); } supdrvDeleteDevExt(&g_DevExt); } else { LogRel((DEVICE_NAME ":VBoxDrvSolarisAttach: supdrvInitDevExt failed\n")); rc = RTErrConvertToErrno(rc); } RTR0TermForced(); } else { LogRel((DEVICE_NAME ":VBoxDrvSolarisAttach: failed to init R0Drv\n")); rc = RTErrConvertToErrno(rc); } memset(&g_DevExt, 0, sizeof(g_DevExt)); return rc; }
int sf_dir_read_all(struct sf_glob_info *sf_g, struct sf_inode_info *sf_i, struct sf_dir_info *sf_d, SHFLHANDLE handle) { int err; SHFLSTRING *mask; struct sf_dir_buf *b; TRACE(); err = sf_make_path(__func__, sf_i, "*", 1, &mask); if (err) goto fail0; for (;;) { int rc; void *buf; uint32_t cbSize; uint32_t cEntries; b = sf_get_empty_dir_buf(sf_d); if (!b) { b = sf_dir_buf_alloc(); if (!b) { err = -ENOMEM; LogRelFunc(("could not alloc directory buffer\n")); goto fail1; } list_add(&b->head, &sf_d->info_list); } buf = b->buf; cbSize = b->cbFree; rc = VbglR0SfDirInfo(&client_handle, &sf_g->map, handle, mask, 0, 0, &cbSize, buf, &cEntries); switch (rc) { case VINF_SUCCESS: /* fallthrough */ case VERR_NO_MORE_FILES: break; case VERR_NO_TRANSLATION: LogFunc(("host could not translate entry\n")); /* XXX */ break; default: err = -RTErrConvertToErrno(rc); LogFunc(("VbglR0SfDirInfo failed rc=%Rrc\n", rc)); goto fail1; } b->cEntries += cEntries; b->cbFree -= cbSize; b->cbUsed += cbSize; if (RT_FAILURE(rc)) break; } err = 0; fail1: kfree(mask); fail0: return err; }
int sf_setattr(struct dentry *dentry, struct iattr *iattr) { struct sf_glob_info *sf_g; struct sf_inode_info *sf_i; SHFLCREATEPARMS params; SHFLFSOBJINFO info; uint32_t cbBuffer; int rc, err; TRACE(); sf_g = GET_GLOB_INFO(dentry->d_inode->i_sb); sf_i = GET_INODE_INFO(dentry->d_inode); err = 0; RT_ZERO(params); params.Handle = SHFL_HANDLE_NIL; params.CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_ATTR_WRITE; /* this is at least required for Posix hosts */ if (iattr->ia_valid & ATTR_SIZE) params.CreateFlags |= SHFL_CF_ACCESS_WRITE; rc = VbglR0SfCreate(&client_handle, &sf_g->map, sf_i->path, ¶ms); if (RT_FAILURE(rc)) { LogFunc(("VbglR0SfCreate(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); err = -RTErrConvertToErrno(rc); goto fail2; } if (params.Result != SHFL_FILE_EXISTS) { LogFunc(("file %s does not exist\n", sf_i->path->String.utf8)); err = -ENOENT; goto fail1; } /* Setting the file size and setting the other attributes has to be * handled separately, see implementation of vbsfSetFSInfo() in * vbsf.cpp */ if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) { #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? RTFS_UNIX_##r : 0) RT_ZERO(info); if (iattr->ia_valid & ATTR_MODE) { info.Attr.fMode = mode_set(ISUID); info.Attr.fMode |= mode_set(ISGID); info.Attr.fMode |= mode_set(IRUSR); info.Attr.fMode |= mode_set(IWUSR); info.Attr.fMode |= mode_set(IXUSR); info.Attr.fMode |= mode_set(IRGRP); info.Attr.fMode |= mode_set(IWGRP); info.Attr.fMode |= mode_set(IXGRP); info.Attr.fMode |= mode_set(IROTH); info.Attr.fMode |= mode_set(IWOTH); info.Attr.fMode |= mode_set(IXOTH); if (iattr->ia_mode & S_IFDIR) info.Attr.fMode |= RTFS_TYPE_DIRECTORY; else info.Attr.fMode |= RTFS_TYPE_FILE; } if (iattr->ia_valid & ATTR_ATIME) sf_timespec_from_ftime(&info.AccessTime, &iattr->ia_atime); if (iattr->ia_valid & ATTR_MTIME) sf_timespec_from_ftime(&info.ModificationTime, &iattr->ia_mtime); /* ignore ctime (inode change time) as it can't be set from userland anyway */ cbBuffer = sizeof(info); rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, params.Handle, SHFL_INFO_SET | SHFL_INFO_FILE, &cbBuffer, (PSHFLDIRINFO)&info); if (RT_FAILURE(rc)) { LogFunc(("VbglR0SfFsInfo(%s, FILE) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); err = -RTErrConvertToErrno(rc); goto fail1; } } if (iattr->ia_valid & ATTR_SIZE) { RT_ZERO(info); info.cbObject = iattr->ia_size; cbBuffer = sizeof(info); rc = VbglR0SfFsInfo(&client_handle, &sf_g->map, params.Handle, SHFL_INFO_SET | SHFL_INFO_SIZE, &cbBuffer, (PSHFLDIRINFO)&info); if (RT_FAILURE(rc)) { LogFunc(("VbglR0SfFsInfo(%s, SIZE) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); err = -RTErrConvertToErrno(rc); goto fail1; } } rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle); if (RT_FAILURE(rc)) LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); return sf_inode_revalidate(dentry); fail1: rc = VbglR0SfClose(&client_handle, &sf_g->map, params.Handle); if (RT_FAILURE(rc)) LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); fail2: return err; }
static ssize_t rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode, const char *pszBasePath, char *pszBuf, size_t cchBuf) { /* * Check assumptions made by the code below. */ size_t const cchBasePath = strlen(pszBasePath); AssertReturnStmt(cchBasePath < RTPATH_MAX - 10U, errno = ENAMETOOLONG, -1); ssize_t rcRet; PRTDIR pDir; int rc = RTDirOpen(&pDir, pszBasePath); if (RT_SUCCESS(rc)) { char szPath[RTPATH_MAX]; /** @todo 4K per recursion - can easily be optimized away by passing it along pszBasePath and only remember the length. */ memcpy(szPath, pszBasePath, cchBasePath + 1); for (;;) { RTDIRENTRYEX Entry; rc = RTDirReadEx(pDir, &Entry, NULL, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK); if (RT_FAILURE(rc)) { errno = rc == VERR_NO_MORE_FILES ? ENOENT : rc == VERR_BUFFER_OVERFLOW ? EOVERFLOW : EIO; rcRet = -1; break; } if (RTFS_IS_SYMLINK(Entry.Info.Attr.fMode)) continue; /* Do the matching. */ if ( Entry.Info.Attr.u.Unix.Device == DevNum && (Entry.Info.Attr.fMode & RTFS_TYPE_MASK) == fMode) { rcRet = rtLinuxConstructPath(pszBuf, cchBuf, pszBasePath, "%s", Entry.szName); break; } /* Recurse into subdirectories. */ if (!RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)) continue; if (Entry.szName[0] == '.') continue; szPath[cchBasePath] = '\0'; rc = RTPathAppend(szPath, sizeof(szPath) - 1, Entry.szName); /* -1: for slash */ if (RT_FAILURE(rc)) { errno = ENAMETOOLONG; rcRet = -1; break; } strcat(&szPath[cchBasePath], "/"); rcRet = rtLinuxFindDevicePathRecursive(DevNum, fMode, szPath, pszBuf, cchBuf); if (rcRet >= 0 || errno != ENOENT) break; } RTDirClose(pDir); } else { rcRet = -1; errno = RTErrConvertToErrno(rc); } return rcRet; }
static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y) { struct vbox_private *vbox = crtc->dev->dev_private; struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc); struct drm_gem_object *obj; struct vbox_bo *bo; int ret, rc; struct ttm_bo_kmap_obj uobj_map; u8 *src; u8 *dst = NULL; size_t cbData, cbMask; bool src_isiomem; if (!handle) { /* Hide cursor. */ VBoxHGSMIUpdatePointerShape(&vbox->Ctx, 0, 0, 0, 0, 0, NULL, 0); return 0; } if ( width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT || width == 0 || hot_x > width || height == 0 || hot_y > height) return -EINVAL; obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); if (obj) { bo = gem_to_vbox_bo(obj); ret = vbox_bo_reserve(bo, false); if (!ret) { /* The mask must be calculated based on the alpha channel, one bit * per ARGB word, and must be 32-bit padded. */ cbMask = ((width + 7) / 8 * height + 3) & ~3; cbData = width * height * 4 + cbMask; dst = kmalloc(cbData, GFP_KERNEL); if (dst) { ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &uobj_map); if (!ret) { src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem); if (!src_isiomem) { uint32_t fFlags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE | VBOX_MOUSE_POINTER_ALPHA; copy_cursor_image(src, dst, width, height, cbMask); rc = VBoxHGSMIUpdatePointerShape(&vbox->Ctx, fFlags, hot_x, hot_y, width, height, dst, cbData); ret = RTErrConvertToErrno(rc); } else DRM_ERROR("src cursor bo should be in main memory\n"); ttm_bo_kunmap(&uobj_map); } kfree(dst); } vbox_bo_unreserve(bo); } drm_gem_object_unreference_unlocked(obj); } else { DRM_ERROR("Cannot find cursor object %x for crtc\n", handle); ret = -ENOENT; } return ret; }
/** * Initialize module. * * @returns appropriate status code. */ static int __init VBoxPciLinuxInit(void) { int rc; /* * Initialize IPRT. */ rc = RTR0Init(0); if (RT_FAILURE(rc)) goto error; LogRel(("VBoxPciLinuxInit\n")); RT_ZERO(g_VBoxPciGlobals); rc = vboxPciInit(&g_VBoxPciGlobals); if (RT_FAILURE(rc)) { LogRel(("cannot do VBoxPciInit: %Rc\n", rc)); goto error; } #if defined(CONFIG_PCI_STUB) /* nothing to do, pci_stub module part of the kernel */ g_VBoxPciGlobals.fPciStubModuleAvail = true; #elif defined(CONFIG_PCI_STUB_MODULE) if (request_module(PCI_STUB_MODULE) == 0) { # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) /* find_module() is static before Linux 2.6.30 */ g_VBoxPciGlobals.pciStubModule = find_module(PCI_STUB_MODULE_NAME); if (g_VBoxPciGlobals.pciStubModule) { if (try_module_get(g_VBoxPciGlobals.pciStubModule)) g_VBoxPciGlobals.fPciStubModuleAvail = true; } else printk(KERN_INFO "vboxpci: find_module %s failed\n", PCI_STUB_MODULE); # endif } else printk(KERN_INFO "vboxpci: cannot load %s\n", PCI_STUB_MODULE); #else printk(KERN_INFO "vboxpci: %s module not available, cannot detach PCI devices\n", PCI_STUB_MODULE); #endif #ifdef VBOX_WITH_IOMMU if (iommu_found()) printk(KERN_INFO "vboxpci: IOMMU found\n"); else printk(KERN_INFO "vboxpci: IOMMU not found (not registered)\n"); #else printk(KERN_INFO "vboxpci: IOMMU not found (not compiled)\n"); #endif return 0; error: return -RTErrConvertToErrno(rc); }
/** * Driver ioctl, an alternate entry point for this character driver. * * @param Dev Device number * @param Cmd Operation identifier * @param pArg Arguments from user to driver * @param Mode Information bitfield (read/write, address space etc.) * @param pCred User credentials * @param pVal Return value for calling process. * * @return corresponding solaris error code. */ static int VBoxGuestSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArg, int Mode, cred_t *pCred, int *pVal) { LogFlow((DEVICE_NAME ":VBoxGuestSolarisIOCtl\n")); /* * Get the session from the soft state item. */ vboxguest_state_t *pState = ddi_get_soft_state(g_pVBoxGuestSolarisState, getminor(Dev)); if (!pState) { LogRel((DEVICE_NAME "::IOCtl: no state data for %d\n", getminor(Dev))); return EINVAL; } PVBOXGUESTSESSION pSession = pState->pSession; if (!pSession) { LogRel((DEVICE_NAME "::IOCtl: no session data for %d\n", getminor(Dev))); return EINVAL; } /* * Read and validate the request wrapper. */ VBGLBIGREQ ReqWrap; if (IOCPARM_LEN(Cmd) != sizeof(ReqWrap)) { LogRel((DEVICE_NAME "::IOCtl: bad request %#x size=%d expected=%d\n", Cmd, IOCPARM_LEN(Cmd), sizeof(ReqWrap))); return ENOTTY; } int rc = ddi_copyin((void *)pArg, &ReqWrap, sizeof(ReqWrap), Mode); if (RT_UNLIKELY(rc)) { LogRel((DEVICE_NAME "::IOCtl: ddi_copyin failed to read header pArg=%p Cmd=%d. rc=%#x.\n", pArg, Cmd, rc)); return EINVAL; } if (ReqWrap.u32Magic != VBGLBIGREQ_MAGIC) { LogRel((DEVICE_NAME "::IOCtl: bad magic %#x; pArg=%p Cmd=%#x.\n", ReqWrap.u32Magic, pArg, Cmd)); return EINVAL; } if (RT_UNLIKELY(ReqWrap.cbData > _1M*16)) { LogRel((DEVICE_NAME "::IOCtl: bad size %#x; pArg=%p Cmd=%#x.\n", ReqWrap.cbData, pArg, Cmd)); return EINVAL; } /* * Read the request payload if any; requests like VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS have no data payload. */ void *pvBuf = NULL; if (RT_LIKELY(ReqWrap.cbData > 0)) { pvBuf = RTMemTmpAlloc(ReqWrap.cbData); if (RT_UNLIKELY(!pvBuf)) { LogRel((DEVICE_NAME "::IOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap.cbData)); return ENOMEM; } rc = ddi_copyin((void *)(uintptr_t)ReqWrap.pvDataR3, pvBuf, ReqWrap.cbData, Mode); if (RT_UNLIKELY(rc)) { RTMemTmpFree(pvBuf); LogRel((DEVICE_NAME "::IOCtl: ddi_copyin failed; pvBuf=%p pArg=%p Cmd=%d. rc=%d\n", pvBuf, pArg, Cmd, rc)); return EFAULT; } if (RT_UNLIKELY(!VALID_PTR(pvBuf))) { RTMemTmpFree(pvBuf); LogRel((DEVICE_NAME "::IOCtl: pvBuf invalid pointer %p\n", pvBuf)); return EINVAL; } } Log((DEVICE_NAME "::IOCtl: pSession=%p pid=%d.\n", pSession, (int)RTProcSelf())); /* * Process the IOCtl. */ size_t cbDataReturned = 0; rc = VBoxGuestCommonIOCtl(Cmd, &g_DevExt, pSession, pvBuf, ReqWrap.cbData, &cbDataReturned); if (RT_SUCCESS(rc)) { rc = 0; if (RT_UNLIKELY(cbDataReturned > ReqWrap.cbData)) { LogRel((DEVICE_NAME "::IOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap.cbData)); cbDataReturned = ReqWrap.cbData; } if (cbDataReturned > 0) { rc = ddi_copyout(pvBuf, (void *)(uintptr_t)ReqWrap.pvDataR3, cbDataReturned, Mode); if (RT_UNLIKELY(rc)) { LogRel((DEVICE_NAME "::IOCtl: ddi_copyout failed; pvBuf=%p pArg=%p cbDataReturned=%u Cmd=%d. rc=%d\n", pvBuf, pArg, cbDataReturned, Cmd, rc)); rc = EFAULT; } } } else { /* * We Log() instead of LogRel() here because VBOXGUEST_IOCTL_WAITEVENT can return VERR_TIMEOUT, * VBOXGUEST_IOCTL_CANCEL_ALL_EVENTS can return VERR_INTERRUPTED and possibly more in the future; * which are not really failures that require logging. */ Log((DEVICE_NAME "::IOCtl: VBoxGuestCommonIOCtl failed. Cmd=%#x rc=%d\n", Cmd, rc)); rc = RTErrConvertToErrno(rc); } *pVal = rc; if (pvBuf) RTMemTmpFree(pvBuf); return rc; }
/** * Kernel entry points */ int _init(void) { #if 0 /* No IPRT logging before RTR0Init() is done! */ LogFlowFunc(("vboxdrv:_init\n")); #endif /* * Prevent module autounloading. */ modctl_t *pModCtl = mod_getctl(&g_VBoxDrvSolarisModLinkage); if (pModCtl) pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD; else cmn_err(CE_NOTE, "vboxdrv: failed to disable autounloading!\n"); /* * Initialize IPRT R0 driver, which internally calls OS-specific r0 init. */ int rc = RTR0Init(0); if (RT_SUCCESS(rc)) { /* * Initialize the device extension */ rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION)); if (RT_SUCCESS(rc)) { cmn_err(CE_CONT, "!tsc::mode %s @ tentative %lu Hz\n", SUPGetGIPModeName(g_DevExt.pGip), g_DevExt.pGip->u64CpuHz); /* * Initialize the session hash table. */ memset(g_apSessionHashTab, 0, sizeof(g_apSessionHashTab)); rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvSol"); if (RT_SUCCESS(rc)) { rc = ddi_soft_state_init(&g_pVBoxDrvSolarisState, sizeof(vbox_devstate_t), 8); if (!rc) { rc = mod_install(&g_VBoxDrvSolarisModLinkage); if (!rc) return rc; /* success */ ddi_soft_state_fini(&g_pVBoxDrvSolarisState); LogRel(("vboxdrv: mod_install failed! rc=%d\n", rc)); } else LogRel(("vboxdrv: failed to initialize soft state.\n")); RTSpinlockDestroy(g_Spinlock); g_Spinlock = NIL_RTSPINLOCK; } else { LogRel(("VBoxDrvSolarisAttach: RTSpinlockCreate failed\n")); rc = RTErrConvertToErrno(rc); } supdrvDeleteDevExt(&g_DevExt); } else { LogRel(("VBoxDrvSolarisAttach: supdrvInitDevExt failed\n")); rc = EINVAL; } RTR0TermForced(); } else { LogRel(("VBoxDrvSolarisAttach: failed to init R0Drv\n")); rc = RTErrConvertToErrno(rc); } memset(&g_DevExt, 0, sizeof(g_DevExt)); return rc; }