diff options
| author | Felix Geyer <debfx-pkg@fobos.de> | 2010-03-26 10:38:21 +0100 |
|---|---|---|
| committer | Felix Geyer <debfx-pkg@fobos.de> | 2010-03-26 10:38:21 +0100 |
| commit | 0429962c55c464036f613d707f26b91f252584e7 (patch) | |
| tree | b359d4c41578b576d90240489a1ba273ab46a6b7 /src/VBox/Additions | |
| parent | 48be1cf480743cdc0e60dd1edc9677b4349a570d (diff) | |
| download | virtualbox-0429962c55c464036f613d707f26b91f252584e7.tar.gz | |
Imported Upstream version 3.1.6-dfsgupstream/3.1.6-dfsg
Diffstat (limited to 'src/VBox/Additions')
36 files changed, 3683 insertions, 229 deletions
diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c index 667441238..a5517fb9e 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c @@ -168,8 +168,6 @@ static uint16_t g_uIOPortBase; static caddr_t g_pMMIOBase; /** Size of the MMIO region. */ static off_t g_cbMMIO; -/** VMMDev Version. */ -static uint32_t g_u32Version; /** Pointer to the interrupt handle vector */ static ddi_intr_handle_t *g_pIntr; /** Number of actually allocated interrupt handles */ @@ -383,8 +381,9 @@ static int VBoxGuestSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd) ddi_regs_map_free(&g_PciIOHandle); ddi_regs_map_free(&g_PciMMIOHandle); ddi_remove_minor_node(pDip, NULL); - + VBoxGuestDeleteDevExt(&g_DevExt); RTR0Term(); + g_pDip = NULL; return DDI_SUCCESS; } @@ -611,43 +610,45 @@ static int VBoxGuestSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArg, int Mode, cr LogRel((DEVICE_NAME "::IOCtl: bad magic %#x; pArg=%p Cmd=%#x.\n", ReqWrap.u32Magic, pArg, Cmd)); return EINVAL; } - if (RT_UNLIKELY( ReqWrap.cbData == 0 - || ReqWrap.cbData > _1M*16)) + 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. + * Read the request payload if any; requests like VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS have no data payload. */ - void *pvBuf = RTMemTmpAlloc(ReqWrap.cbData); - if (RT_UNLIKELY(!pvBuf)) + void *pvBuf = NULL; + if (RT_LIKELY(ReqWrap.cbData > 0)) { - LogRel((DEVICE_NAME "::IOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap.cbData)); - return ENOMEM; - } + 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( ReqWrap.cbData != 0 - && !VALID_PTR(pvBuf))) - { - RTMemTmpFree(pvBuf); - LogRel((DEVICE_NAME "::IOCtl: pvBuf invalid pointer %p\n", pvBuf)); - return EINVAL; + 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; + size_t cbDataReturned = 0; rc = VBoxGuestCommonIOCtl(Cmd, &g_DevExt, pSession, pvBuf, ReqWrap.cbData, &cbDataReturned); if (RT_SUCCESS(rc)) { @@ -677,7 +678,8 @@ static int VBoxGuestSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArg, int Mode, cr rc = RTErrConvertToErrno(rc); } *pVal = rc; - RTMemTmpFree(pvBuf); + if (pvBuf) + RTMemTmpFree(pvBuf); return rc; } diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp b/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp index 22947287f..0515a8b2e 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp @@ -356,7 +356,7 @@ int VBoxGuestInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, rc = RTSpinlockCreate(&pDevExt->SessionSpinlock); if (RT_FAILURE(rc)) { - Log(("VBoxGuestInitDevExt: failed to spinlock, rc=%d!\n", rc)); + LogRel(("VBoxGuestInitDevExt: failed to spinlock, rc=%d!\n", rc)); if (pDevExt->EventSpinlock != NIL_RTSPINLOCK) RTSpinlockDestroy(pDevExt->EventSpinlock); return rc; @@ -393,18 +393,24 @@ int VBoxGuestInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, Log(("VBoxGuestInitDevExt: returns success\n")); return VINF_SUCCESS; } + else + LogRel(("VBoxGuestInitDevExt: VBoxGuestSetGuestCapabilities failed, rc=%Rrc\n", rc)); } + else + LogRel(("VBoxGuestInitDevExt: vboxGuestSetFilterMask failed, rc=%Rrc\n", rc)); } + else + LogRel(("VBoxGuestInitDevExt: vboxGuestInitReportGuestInfo failed, rc=%Rrc\n", rc)); - /* failure cleanup */ + VbglGRFree((VMMDevRequestHeader *)pDevExt->pIrqAckEvents); } else - Log(("VBoxGuestInitDevExt: VBoxGRAlloc failed, rc=%Rrc\n", rc)); + LogRel(("VBoxGuestInitDevExt: VBoxGRAlloc failed, rc=%Rrc\n", rc)); VbglTerminate(); } else - Log(("VBoxGuestInitDevExt: VbglInit failed, rc=%Rrc\n", rc)); + LogRel(("VBoxGuestInitDevExt: VbglInit failed, rc=%Rrc\n", rc)); rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2); rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2); @@ -448,7 +454,7 @@ void VBoxGuestDeleteDevExt(PVBOXGUESTDEVEXT pDevExt) { int rc2; Log(("VBoxGuestDeleteDevExt:\n")); - LogRel(("VBoxGuest: The additions driver is terminating.\n")); + Log(("VBoxGuest: The additions driver is terminating.\n")); /* * Unfix the guest mappings, filter all events and clear @@ -900,7 +906,7 @@ static int VBoxGuestCommonIOCtl_WaitEvent(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSE || rc == VERR_INTERRUPTED) { pInfo->u32Result = VBOXGUEST_WAITEVENT_INTERRUPTED; - rc == VERR_INTERRUPTED; + rc = VERR_INTERRUPTED; Log(("VBoxGuestCommonIOCtl: WAITEVENT: returns VERR_INTERRUPTED\n")); } else if (rc == VERR_TIMEOUT) @@ -953,7 +959,7 @@ static int VBoxGuestCommonIOCtl_CancelAllWaitEvents(PVBOXGUESTDEVEXT pDevExt, PV if ( pWait->pSession == pSession && pWait->fResEvents != UINT32_MAX) { - RTSEMEVENTMULTI hEvent; + RTSEMEVENTMULTI hEvent = pWait->Event; pWait->fResEvents = UINT32_MAX; RTSpinlockReleaseNoInts(pDevExt->EventSpinlock, &Tmp); /* HACK ALRET! This races wakeup + reuse! */ diff --git a/src/VBox/Additions/common/crOpenGL/Makefile.kmk b/src/VBox/Additions/common/crOpenGL/Makefile.kmk index bd64a824f..2bb5484aa 100644 --- a/src/VBox/Additions/common/crOpenGL/Makefile.kmk +++ b/src/VBox/Additions/common/crOpenGL/Makefile.kmk @@ -188,7 +188,10 @@ VBoxOGL_LIBS = \ $(PATH_LIB)/additions/VBoxOGLspuload$(VBOX_SUFF_LIB) if1of ($(KBUILD_TARGET),linux solaris) VBoxOGL_LIBS += \ - $(PATH_LIB)/libXcomposite.so + $(PATH_LIB)/libXcomposite.so \ + $(PATH_LIB)/libXdamage.so \ + $(PATH_LIB)/libXfixes.so \ + $(PATH_LIB)/libXext.so ifdef VBoxOGL_FAKEDRI VBoxOGL_LIBS += \ dl diff --git a/src/VBox/Additions/common/crOpenGL/context.c b/src/VBox/Additions/common/crOpenGL/context.c index 36a28cffe..c375e797f 100644 --- a/src/VBox/Additions/common/crOpenGL/context.c +++ b/src/VBox/Additions/common/crOpenGL/context.c @@ -31,6 +31,10 @@ #include "cr_environment.h" #include "stub.h" +typedef struct { + WindowInfo *window; + GLboolean windowInUse; +} CtxCheckCurrentDrawableParams_t; /** * This function should be called from MakeCurrent(). It'll detect if @@ -215,6 +219,7 @@ stubGetWindowInfo( Display *dpy, GLXDrawable drawable ) winInfo->type = UNDECIDED; winInfo->spuWindow = -1; winInfo->mapped = -1; /* don't know */ + winInfo->pOwner = NULL; #ifndef WINDOWS crHashtableAdd(stub.windowTable, (unsigned int) drawable, winInfo); #else @@ -266,7 +271,6 @@ stubNewContext( const char *dpyName, GLint visBits, ContextType type, context->spuContext = spuContext; context->visBits = visBits; context->currentDrawable = NULL; - context->pOwnWindow = NULL; crStrncpy(context->dpyName, dpyName, MAX_DPY_NAME); context->dpyName[MAX_DPY_NAME-1] = 0; @@ -785,6 +789,24 @@ stubCheckUseChromium( WindowInfo *window ) return GL_TRUE; /* use Chromium! */ } +static void stubWindowCheckOwnerCB(unsigned long key, void *data1, void *data2) +{ + WindowInfo *pWindow = (WindowInfo *) data1; + ContextInfo *pCtx = (ContextInfo *) data2; + + if (pWindow->pOwner == pCtx) + { +#ifdef WINDOWS + /* Note: can't use WindowFromDC(context->pOwnWindow->drawable) here + because GL context is already released from DC and actual guest window + could be destroyed. + */ + crWindowDestroy((GLint)pWindow->hWnd); +#else + crWindowDestroy((GLint)pWindow->drawable); +#endif + } +} GLboolean stubMakeCurrent( WindowInfo *window, ContextInfo *context ) @@ -834,9 +856,8 @@ stubMakeCurrent( WindowInfo *window, ContextInfo *context ) spuShareCtx ); if (window->spuWindow == -1) { + /*crDebug("(1)stubMakeCurrent ctx=%p(%i) window=%p(%i)", context, context->spuContext, window, window->spuWindow);*/ window->spuWindow = stub.spu->dispatch_table.WindowCreate( window->dpyName, context->visBits ); - CRASSERT(!context->pOwnWindow); - context->pOwnWindow = window; } } else { @@ -880,8 +901,8 @@ stubMakeCurrent( WindowInfo *window, ContextInfo *context ) CRASSERT(context->type == CHROMIUM); CRASSERT(context->spuContext >= 0); - if (context->currentDrawable && context->currentDrawable != window) - crWarning("Rebinding context %p to a different window", context); + /*if (context->currentDrawable && context->currentDrawable != window) + crDebug("Rebinding context %p to a different window", context);*/ if (window->type == NATIVE) { crWarning("Can't rebind a chromium context to a native window\n"); @@ -890,9 +911,28 @@ stubMakeCurrent( WindowInfo *window, ContextInfo *context ) else { if (window->spuWindow == -1) { + /*crDebug("(2)stubMakeCurrent ctx=%p(%i) window=%p(%i)", context, context->spuContext, window, window->spuWindow);*/ window->spuWindow = stub.spu->dispatch_table.WindowCreate( window->dpyName, context->visBits ); - CRASSERT(!context->pOwnWindow); - context->pOwnWindow = window; + if (context->currentDrawable && context->currentDrawable->type==CHROMIUM + && context->currentDrawable->pOwner==context) + { +#ifdef WINDOWS + if (!WindowFromDC(context->currentDrawable->drawable)) + { + crWindowDestroy((GLint)context->currentDrawable->hWnd); + } +#else + Window root; + int x, y; + unsigned int border, depth, w, h; + + if (!XGetGeometry(context->currentDrawable->dpy, context->currentDrawable->drawable, &root, &x, &y, &w, &h, &border, &depth)) + { + crWindowDestroy((GLint)context->currentDrawable->drawable); + } +#endif + + } } if (window->spuWindow != (GLint)window->drawable) @@ -905,6 +945,7 @@ stubMakeCurrent( WindowInfo *window, ContextInfo *context ) } window->type = context->type; + window->pOwner = context; context->currentDrawable = window; stub.currentContext = context; @@ -964,8 +1005,6 @@ stubMakeCurrent( WindowInfo *window, ContextInfo *context ) return retVal; } - - void stubDestroyContext( unsigned long contextId ) { @@ -991,18 +1030,7 @@ stubDestroyContext( unsigned long contextId ) /* Have pack SPU or tilesort SPU, etc. destroy the context */ CRASSERT(context->spuContext >= 0); stub.spu->dispatch_table.DestroyContext( context->spuContext ); - if (context->pOwnWindow) - { - /* Note: can't use WindowFromDC(context->pOwnWindow->drawable) here - because GL context is already released from DC and actual guest window - could be destroyed. - */ -#ifdef WINDOWS - crWindowDestroy((GLint)context->pOwnWindow->hWnd); -#else - crWindowDestroy((GLint)context->pOwnWindow->drawable); -#endif - } + crHashtableWalk(stub.windowTable, stubWindowCheckOwnerCB, context); } if (stub.currentContext == context) { diff --git a/src/VBox/Additions/common/crOpenGL/load.c b/src/VBox/Additions/common/crOpenGL/load.c index 59ea8b180..1639a3b68 100644 --- a/src/VBox/Additions/common/crOpenGL/load.c +++ b/src/VBox/Additions/common/crOpenGL/load.c @@ -79,18 +79,10 @@ static SwapBuffersFunc_t origSwapBuffers; static DrawBufferFunc_t origDrawBuffer; static ScissorFunc_t origScissor; -static void stubCheckWindowState(void) +static void stubCheckWindowState(WindowInfo *window) { - WindowInfo *window; bool bForceUpdate = false; - CRASSERT(stub.trackWindowSize || stub.trackWindowPos); - - if (!stub.currentContext) - return; - - window = stub.currentContext->currentDrawable; - #ifdef WINDOWS /* @todo install hook and track for WM_DISPLAYCHANGE */ { @@ -128,6 +120,64 @@ static void stubCheckWindowState(void) } } +static bool stubSystemWindowExist(WindowInfo *pWindow) +{ +#ifdef WINDOWS + if (!WindowFromDC(pWindow->drawable)) + { + return false; + } +#else + Window root; + int x, y; + unsigned int border, depth, w, h; + + if (!XGetGeometry(pWindow->dpy, pWindow->drawable, &root, &x, &y, &w, &h, &border, &depth)) + { + return false; + } +#endif + + return true; +} + +static void stubCheckWindowsCB(unsigned long key, void *data1, void *data2) +{ + WindowInfo *pWindow = (WindowInfo *) data1; + ContextInfo *pCtx = (ContextInfo *) data2; + + if (pWindow == pCtx->currentDrawable + || pWindow->type!=CHROMIUM + || pWindow->pOwner!=pCtx) + { + return; + } + + if (!stubSystemWindowExist(pWindow)) + { +#ifdef WINDOWS + crWindowDestroy((GLint)pWindow->hWnd); +#else + crWindowDestroy((GLint)pWindow->drawable); +#endif + return; + } + + stubCheckWindowState(pWindow); +} + +static void stubCheckWindowsState(void) +{ + CRASSERT(stub.trackWindowSize || stub.trackWindowPos); + + if (!stub.currentContext) + return; + + stubCheckWindowState(stub.currentContext->currentDrawable); + + crHashtableWalk(stub.windowTable, stubCheckWindowsCB, stub.currentContext); +} + /** * Override the head SPU's glClear function. @@ -136,7 +186,7 @@ static void stubCheckWindowState(void) */ static void SPU_APIENTRY trapClear(GLbitfield mask) { - stubCheckWindowState(); + stubCheckWindowsState(); /* call the original SPU glClear function */ origClear(mask); } @@ -147,7 +197,7 @@ static void SPU_APIENTRY trapClear(GLbitfield mask) */ static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h) { - stubCheckWindowState(); + stubCheckWindowsState(); /* call the original SPU glViewport function */ if (!stub.viewportHack) { @@ -166,13 +216,13 @@ static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h) static void SPU_APIENTRY trapSwapBuffers(GLint window, GLint flags) { - stubCheckWindowState(); + stubCheckWindowsState(); origSwapBuffers(window, flags); } static void SPU_APIENTRY trapDrawBuffer(GLenum buf) { - stubCheckWindowState(); + stubCheckWindowsState(); origDrawBuffer(buf); } diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py b/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py index f26dd52f3..0531594cc 100644 --- a/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py @@ -24,6 +24,23 @@ void PACKSPU_APIENTRY packspu_Begin( GLenum mode ) /* XXX comparing mode >= 0 here is not needed since mode is unsigned */ CRASSERT( mode >= GL_POINTS && mode <= GL_POLYGON ); +#if CR_ARB_vertex_buffer_object + { + GLboolean serverArrays = GL_FALSE; + GET_CONTEXT(ctx); + if (ctx->clientState->extensions.ARB_vertex_buffer_object) + serverArrays = crStateUseServerArrays(); + if (serverArrays) { + CRClientState *clientState = &(ctx->clientState->client); + if (clientState->array.locked && !clientState->array.synced) + { + crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount); + clientState->array.synced = GL_TRUE; + } + } + } +#endif + if (pack_spu.swap) { crPackBeginSWAP( mode ); diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c index 1eb8fad5b..07248ad08 100644 --- a/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c @@ -191,12 +191,11 @@ packspu_ArrayElement( GLint index ) GET_CONTEXT(ctx); CRClientState *clientState = &(ctx->clientState->client); - /*Note the comment in packspu_LockArraysEXT*/ - if (clientState->array.locked && !clientState->array.synced) - { - crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount); - clientState->array.synced = GL_TRUE; - } + /* LockArraysEXT can not be executed between glBegin/glEnd pair, it also + * leads to vertexpointers being adjusted on the host side between glBegin/glEnd calls which + * produces unpredictable results. Locking is done before the glBegin call instead. + */ + CRASSERT(!clientState->array.locked || clientState->array.synced); /* Send the DrawArrays command over the wire */ if (pack_spu.swap) @@ -491,7 +490,7 @@ void PACKSPU_APIENTRY packspu_LockArraysEXT(GLint first, GLint count) crStateLockArraysEXT(first, count); /*Note: this is a workaround for quake3 based apps. It's modifying vertex data between glLockArraysEXT and glDrawElements calls, - so we'd pass data to host right before the glDrawSomething call. + so we'd pass data to host right before the glDrawSomething or glBegin call. */ /*crPackLockArraysEXT(first, count);*/ } diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_getstring.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_getstring.c index aa1db7e2c..c9f97b935 100644 --- a/src/VBox/Additions/common/crOpenGL/pack/packspu_getstring.c +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_getstring.c @@ -96,7 +96,7 @@ const GLubyte * PACKSPU_APIENTRY packspu_GetString( GLenum name ) case GL_EXTENSIONS: return GetExtensions(); case GL_VERSION: -#ifdef WINDOWS +#if 0 && defined(WINDOWS) if (packspuRunningUnderWine()) { GetString(GL_REAL_VERSION, ctx->pszRealVersion); diff --git a/src/VBox/Additions/common/crOpenGL/stub.h b/src/VBox/Additions/common/crOpenGL/stub.h index 557b793f8..eab35b335 100644 --- a/src/VBox/Additions/common/crOpenGL/stub.h +++ b/src/VBox/Additions/common/crOpenGL/stub.h @@ -90,7 +90,7 @@ struct context_info_t unsigned long id; /* the client-visible handle */ GLint visBits; WindowInfo *currentDrawable; - WindowInfo *pOwnWindow; /* window created by first call to MakeCurrent with this context */ + #ifdef WINDOWS HGLRC hglrc; #elif defined(DARWIN) @@ -135,6 +135,7 @@ struct window_info_t unsigned int width, height; ContextType type; GLint spuWindow; /* returned by head SPU's WindowCreate() */ + ContextInfo *pOwner; /* ctx which created this window */ GLboolean mapped; #ifdef WINDOWS HDC drawable; diff --git a/src/VBox/Additions/linux/drm/vboxvideo_drm.c b/src/VBox/Additions/linux/drm/vboxvideo_drm.c index a3e6b9893..6f07e2d3d 100644 --- a/src/VBox/Additions/linux/drm/vboxvideo_drm.c +++ b/src/VBox/Additions/linux/drm/vboxvideo_drm.c @@ -87,7 +87,13 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, + /* This was changed with Linux 2.6.33 but Fedora backported this + * change to their 2.6.32 kernel. */ +#if defined(DRM_UNLOCKED) || LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 33) + .unlocked_ioctl = drm_ioctl, +#else .ioctl = drm_ioctl, +#endif .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/src/VBox/Additions/linux/installer/vboxadd-service.sh b/src/VBox/Additions/linux/installer/vboxadd-service.sh index 9bc990bf0..1e613de16 100755 --- a/src/VBox/Additions/linux/installer/vboxadd-service.sh +++ b/src/VBox/Additions/linux/installer/vboxadd-service.sh @@ -257,7 +257,7 @@ start() { exit 1 } testbinary - daemon $binary + daemon $binary > /dev/null RETVAL=$? test $RETVAL -eq 0 && echo `pidof VBoxService` > $PIDFILE succ_msg diff --git a/src/VBox/Additions/linux/installer/vboxadd-x11.sh b/src/VBox/Additions/linux/installer/vboxadd-x11.sh index 097b4c802..eb0340cdb 100755 --- a/src/VBox/Additions/linux/installer/vboxadd-x11.sh +++ b/src/VBox/Additions/linux/installer/vboxadd-x11.sh @@ -1,6 +1,6 @@ #! /bin/sh # Sun VirtualBox -# Linux Additions X11 setup init script ($Revision: 56118 $) +# Linux Additions X11 setup init script ($Revision: 59059 $) # # @@ -73,6 +73,8 @@ if [ -f /etc/arch-release ]; then system=arch elif [ -f /etc/redhat-release ]; then system=redhat +elif [ -f /etc/debian_version ]; then + system=debian elif [ -f /etc/SuSE-release ]; then system=suse elif [ -f /etc/gentoo-release ]; then @@ -162,7 +164,7 @@ if [ "$system" = "lfs" ]; then } fi -if [ "$system" = "other" ]; then +if [ "$system" = "debian" -o "$system" = "other" ]; then fail_msg() { echo " ...fail!" } @@ -287,8 +289,10 @@ setup() setupxorgconf="true" # But without the workaround for SUSE 11.1 not doing input auto-detection newmouse="" - # By default we want to use hal for auto-loading the mouse driver - usehal="--useHal" + # By default we want to use hal/udev/whatever for auto-loading the mouse driver + automouse="--autoMouse" + # But we only install the udev rule if we detect a server that needs it + udevmouse="" # We need to tell our xorg.conf hacking script whether /dev/psaux exists nopsaux="--nopsaux" test -c /dev/psaux && nopsaux="" @@ -324,6 +328,7 @@ setup() vboxvideo_src=vboxvideo_drv_17.so vboxmouse_src=vboxmouse_drv_17.so setupxorgconf="" + test "$system" = "debian" && udevmouse="true" ;; 1.5.99.* | 1.6.* ) begin "Installing X.Org Server 1.6 modules" @@ -348,14 +353,14 @@ setup() vboxvideo_src=vboxvideo_drv_15.so vboxmouse_src=vboxmouse_drv_15.so # SUSE with X.Org 1.5 is a special case, and is handled specially - test -r /etc/SuSE-release && - { usehal=""; newmouse="--newMouse"; } + test "$system" = "suse" && + { automouse=""; newmouse="--newMouse"; } ;; 1.4.* ) begin "Installing X.Org Server 1.4 modules" vboxvideo_src=vboxvideo_drv_14.so vboxmouse_src=vboxmouse_drv_14.so - usehal="" + automouse="" newmouse="--newMouse" ;; 1.3.* ) @@ -364,21 +369,21 @@ setup() begin "Installing X.Org Server 1.3 modules" vboxvideo_src=vboxvideo_drv_13.so vboxmouse_src=vboxmouse_drv_13.so - usehal="" + automouse="" newmouse="--newMouse" ;; 7.1.* | 7.2.* ) begin "Installing X.Org 7.1 modules" vboxvideo_src=vboxvideo_drv_71.so vboxmouse_src=vboxmouse_drv_71.so - usehal="" + automouse="" testrandr="" ;; 6.9.* | 7.0.* ) begin "Installing X.Org 6.9/7.0 modules" vboxvideo_src=vboxvideo_drv_70.so vboxmouse_src=vboxmouse_drv_70.so - usehal="" + automouse="" testrandr="" ;; 6.7* | 6.8.* | 4.2.* | 4.3.* ) @@ -388,7 +393,7 @@ setup() rm "$modules_dir/input/vboxmouse_drv.o" 2>/dev/null ln -s "$lib_dir/vboxvideo_drv.o" "$modules_dir/drivers/vboxvideo_drv.o" ln -s "$lib_dir/vboxmouse_drv.o" "$modules_dir/input/vboxmouse_drv.o" - usehal="" + automouse="" testrandr="" succ_msg ;; @@ -424,11 +429,11 @@ EOF # video drivers. Some versions have the directory and don't use it. # Those versions can autoload vboxvideo though, so we don't need to # hack the configuration file for them. - test -f /etc/debian_version -a -d /usr/share/xserver-xorg/pci && + test "$system" = "debian" -a -d /usr/share/xserver-xorg/pci && { rm -f "/usr/share/xserver-xorg/pci/vboxvideo.ids" ln -s "$share_dir/vboxvideo.ids" /usr/share/xserver-xorg/pci 2>/dev/null - test -n "$usehal" && setupxorgconf="" + test -n "$automouse" && setupxorgconf="" } # Do the XF86Config/xorg.conf hack for those versions that require it @@ -440,7 +445,7 @@ EOF if grep -q "VirtualBox generated" "$i"; then generated="$generated `printf "$i\n"`" else - "$lib_dir/x11config-new.pl" $newmouse $usehal $nopsaux "$i" + "$lib_dir/x11config-new.pl" $newmouse $automouse $nopsaux "$i" fi configured="true" fi @@ -452,15 +457,15 @@ EOF # need a configuration file for VBoxVideo. main_cfg="/etc/X11/xorg.conf" nobak="/etc/X11/xorg.vbox.nobak" - if test -z "$configured" -a ! -r "$nobak"; then + if test -z "$configured"; then touch "$main_cfg" - "$lib_dir/x11config-new.pl" --useHal --noBak "$main_cfg" + "$lib_dir/x11config-new.pl" $newmouse $automouse $nopsaux --noBak "$main_cfg" touch "$nobak" fi fi # X.Org Server versions starting with 1.5 can do mouse auto-detection, # to make our lives easier and spare us the nasty hacks. - test -n "$usehal" && + test -n "$automouse" && if [ -d /etc/hal/fdi/policy ] then # Install hal information about the mouse driver so that X.Org @@ -469,6 +474,17 @@ EOF # Delete the hal cache so that it notices our fdi file rm -r /var/cache/hald/fdi-cache 2> /dev/null fi + test -n "$udevmouse" && + if [ -d /etc/udev/rules.d ] + then + echo "KERNEL==\"vboxguest\",ENV{ID_INPUT}=\"1\"" > /etc/udev/rules.d/70-xorg-vboxmouse.rules + echo "KERNEL==\"vboxguest\",ENV{ID_INPUT_MOUSE}=\"1\"" >> /etc/udev/rules.d/70-xorg-vboxmouse.rules + echo "KERNEL==\"vboxguest\",ENV{x11_driver}=\"vboxmouse\"" >> /etc/udev/rules.d/70-xorg-vboxmouse.rules + # This is normally silent. I have purposely not redirected + # error output as I want to know if something goes wrong, + # particularly if the command syntax ever changes. + udevadm trigger --action=change + fi succ_msg test -n "$generated" && cat << EOF @@ -598,6 +614,8 @@ EOF # Remove other files rm /etc/hal/fdi/policy/90-vboxguest.fdi 2>/dev/null + rm /etc/udev/rules.d/70-xorg-vboxmouse.rules 2>/dev/null + udevadm trigger --action=change 2>/dev/null rm /usr/share/xserver-xorg/pci/vboxvideo.ids 2>/dev/null } diff --git a/src/VBox/Additions/linux/installer/vboxadd.sh b/src/VBox/Additions/linux/installer/vboxadd.sh index de925a910..e0d5d5164 100755 --- a/src/VBox/Additions/linux/installer/vboxadd.sh +++ b/src/VBox/Additions/linux/installer/vboxadd.sh @@ -1,6 +1,6 @@ #! /bin/sh # Sun VirtualBox -# Linux Additions kernel module init script ($Revision: 56414 $) +# Linux Additions kernel module init script ($Revision: 58884 $) # # @@ -20,7 +20,7 @@ # -# chkconfig: 35 30 70 +# chkconfig: 357 30 70 # description: VirtualBox Linux Additions kernel modules # ### BEGIN INIT INFO @@ -400,6 +400,9 @@ setup() # Put mount.vboxsf in the right place ln -sf "$lib_path/$PACKAGE/mount.vboxsf" /sbin + # At least Fedora 11 and Fedora 12 demand on the correct security context when + # executing this command from service scripts. Shouldn't hurt for other distributions. + chcon -u system_u -t mount_exec_t "$lib_path/$PACKAGE/mount.vboxsf" > /dev/null 2>&1 succ_msg if running_vboxguest || running_vboxadd; then diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c new file mode 100644 index 000000000..f06bb43c1 --- /dev/null +++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c @@ -0,0 +1,710 @@ +/** @file + * VirtualBox File System for Solaris Guests, provider implementation. + */ + +/* + * Copyright (C) 2008 Sun Microsystems, Inc. + * + * Sun Microsystems, Inc. confidential + * All rights reserved + */ +/* + * Provider interfaces for shared folder file system. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mntent.h> +#include <sys/param.h> +#include <sys/modctl.h> +#include <sys/mount.h> +#include <sys/policy.h> +#include <sys/atomic.h> +#include <sys/sysmacros.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include "vboxfs_prov.h" +#ifdef u +#undef u +#endif +#include "../../common/VBoxGuestLib/VBoxCalls.h" + +#define SFPROV_VERSION 1 + +static VBSFCLIENT vbox_client; + +/* + * utility to create strings + */ +static SHFLSTRING * +sfprov_string(char *path, int *sz) +{ + SHFLSTRING *str; + int len = strlen(path); + + *sz = len + 1 + sizeof (*str) - sizeof (str->String); + str = kmem_zalloc(*sz, KM_SLEEP); + str->u16Size = len + 1; + str->u16Length = len; + strcpy(str->String.utf8, path); + return (str); +} + +sfp_connection_t * +sfprov_connect(int version) +{ + /* + * only one version for now, so must match + */ + int rc = -1; + if (version != SFPROV_VERSION) + { + cmn_err(CE_WARN, "sfprov_connect: wrong version"); + return NULL; + } + rc = vboxInit(); + if (RT_SUCCESS(rc)) + { + rc = vboxConnect(&vbox_client); + if (RT_SUCCESS(rc)) + { + rc = vboxCallSetUtf8(&vbox_client); + if (RT_SUCCESS(rc)) + { + return ((sfp_connection_t *)&vbox_client); + } + else + cmn_err(CE_WARN, "sfprov_connect: vboxCallSetUtf8() failed"); + + vboxDisconnect(&vbox_client); + } + else + cmn_err(CE_WARN, "sfprov_connect: vboxConnect() failed rc=%d", rc); + vboxUninit(); + } + else + cmn_err(CE_WARN, "sfprov_connect: vboxInit() failed rc=%d", rc); +} + +void +sfprov_disconnect(sfp_connection_t *conn) +{ + if (conn != (sfp_connection_t *)&vbox_client) + cmn_err(CE_WARN, "sfprov_disconnect: bad argument"); + vboxDisconnect(&vbox_client); + vboxUninit(); +} + + +/* + * representation of an active mount point + */ +struct sfp_mount { + VBSFMAP map; +}; + +int +sfprov_mount(sfp_connection_t *conn, char *path, sfp_mount_t **mnt) +{ + sfp_mount_t *m; + SHFLSTRING *str; + int size; + int rc; + + m = kmem_zalloc(sizeof (*m), KM_SLEEP); + str = sfprov_string(path, &size); + rc = vboxCallMapFolder(&vbox_client, str, &m->map); + if (!VBOX_SUCCESS(rc)) { + cmn_err(CE_WARN, "sfprov_mount: vboxCallMapFolder() failed"); + kmem_free(m, sizeof (*m)); + *mnt = NULL; + rc = EINVAL; + } else { + *mnt = m; + rc = 0; + } + kmem_free(str, size); + return (rc); +} + +int +sfprov_unmount(sfp_mount_t *mnt) +{ + int rc; + + rc = vboxCallUnmapFolder(&vbox_client, &mnt->map); + if (!VBOX_SUCCESS(rc)) { + cmn_err(CE_WARN, "sfprov_mount: vboxCallUnmapFolder() failed"); + rc = EINVAL; + } else { + rc = 0; + } + kmem_free(mnt, sizeof (*mnt)); + return (rc); +} + +/* + * query information about a mounted file system + */ +int +sfprov_get_blksize(sfp_mount_t *mnt, uint64_t *blksize) +{ + int rc; + SHFLVOLINFO info; + uint32_t bytes = sizeof(SHFLVOLINFO); + + rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0, + (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info); + if (VBOX_FAILURE(rc)) + return (EINVAL); + *blksize = info.ulBytesPerAllocationUnit; + return (0); +} + +int +sfprov_get_blksused(sfp_mount_t *mnt, uint64_t *blksused) +{ + int rc; + SHFLVOLINFO info; + uint32_t bytes = sizeof(SHFLVOLINFO); + + rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0, + (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info); + if (VBOX_FAILURE(rc)) + return (EINVAL); + *blksused = (info.ullTotalAllocationBytes - + info.ullAvailableAllocationBytes) / info.ulBytesPerAllocationUnit; + return (0); +} + +int +sfprov_get_blksavail(sfp_mount_t *mnt, uint64_t *blksavail) +{ + int rc; + SHFLVOLINFO info; + uint32_t bytes = sizeof(SHFLVOLINFO); + + rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0, + (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info); + if (VBOX_FAILURE(rc)) + return (EINVAL); + *blksavail = + info.ullAvailableAllocationBytes / info.ulBytesPerAllocationUnit; + return (0); +} + +int +sfprov_get_maxnamesize(sfp_mount_t *mnt, uint32_t *maxnamesize) +{ + int rc; + SHFLVOLINFO info; + uint32_t bytes = sizeof(SHFLVOLINFO); + + rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0, + (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info); + if (VBOX_FAILURE(rc)) + return (EINVAL); + *maxnamesize = info.fsProperties.cbMaxComponent; + return (0); +} + +int +sfprov_get_readonly(sfp_mount_t *mnt, uint32_t *readonly) +{ + int rc; + SHFLVOLINFO info; + uint32_t bytes = sizeof(SHFLVOLINFO); + + rc = vboxCallFSInfo(&vbox_client, &mnt->map, 0, + (SHFL_INFO_GET | SHFL_INFO_VOLUME), &bytes, (SHFLDIRINFO *)&info); + if (VBOX_FAILURE(rc)) + return (EINVAL); + *readonly = info.fsProperties.fReadOnly; + return (0); +} + +/* + * File operations: open/close/read/write/etc. + * + * open/create can return any relevant errno, however ENOENT + * generally means that the host file didn't exist. + */ +struct sfp_file { + SHFLHANDLE handle; + VBSFMAP map; /* need this again for the close operation */ +}; + +int +sfprov_create(sfp_mount_t *mnt, char *path, sfp_file_t **fp) +{ + int rc; + SHFLCREATEPARMS parms; + SHFLSTRING *str; + int size; + sfp_file_t *newfp; + + str = sfprov_string(path, &size); + parms.Handle = 0; + parms.Info.cbObject = 0; + parms.CreateFlags = SHFL_CF_ACT_CREATE_IF_NEW | + SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACCESS_READWRITE; + rc = vboxCallCreate(&vbox_client, &mnt->map, str, &parms); + kmem_free(str, size); + + if (RT_FAILURE(rc)) + return (EINVAL); + if (parms.Handle == SHFL_HANDLE_NIL) { + if (parms.Result == SHFL_FILE_EXISTS) + return (EEXIST); + return (ENOENT); + } + newfp = kmem_alloc(sizeof(sfp_file_t), KM_SLEEP); + newfp->handle = parms.Handle; + newfp->map = mnt->map; + *fp = newfp; + return (0); +} + +int +sfprov_open(sfp_mount_t *mnt, char *path, sfp_file_t **fp) +{ + int rc; + SHFLCREATEPARMS parms; + SHFLSTRING *str; + int size; + sfp_file_t *newfp; + + /* + * First we attempt to open it read/write. If that fails we + * try read only. + */ + str = sfprov_string(path, &size); + parms.Handle = 0; + parms.Info.cbObject = 0; + parms.CreateFlags = SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READWRITE; + rc = vboxCallCreate(&vbox_client, &mnt->map, str, &parms); + + if (RT_FAILURE(rc)) { + kmem_free(str, size); + return (EINVAL); + } + if (parms.Handle == SHFL_HANDLE_NIL) { + if (parms.Result == SHFL_NO_RESULT || + parms.Result == SHFL_PATH_NOT_FOUND || + parms.Result == SHFL_FILE_NOT_FOUND) { + kmem_free(str, size); + return (ENOENT); + } + parms.CreateFlags = + SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; + rc = vboxCallCreate(&vbox_client, &mnt->map, str, &parms); + if (RT_FAILURE(rc)) { + kmem_free(str, size); + return (EINVAL); + } + if (parms.Handle == SHFL_HANDLE_NIL) { + kmem_free(str, size); + return (ENOENT); + } + } + newfp = kmem_alloc(sizeof(sfp_file_t), KM_SLEEP); + newfp->handle = parms.Handle; + newfp->map = mnt->map; + *fp = newfp; + return (0); +} + +int +sfprov_trunc(sfp_mount_t *mnt, char *path) +{ + int rc; + SHFLCREATEPARMS parms; + SHFLSTRING *str; + int size; + sfp_file_t *newfp; + + /* + * open it read/write. + */ + str = sfprov_string(path, &size); + parms.Handle = 0; + parms.Info.cbObject = 0; + parms.CreateFlags = SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READWRITE | + SHFL_CF_ACT_OVERWRITE_IF_EXISTS; + rc = vboxCallCreate(&vbox_client, &mnt->map, str, &parms); + + if (RT_FAILURE(rc)) { + kmem_free(str, size); + return (EINVAL); + } + (void)vboxCallClose(&vbox_client, &mnt->map, parms.Handle); + return (0); +} + +int +sfprov_close(sfp_file_t *fp) +{ + int rc; + + rc = vboxCallClose(&vbox_client, &fp->map, fp->handle); + kmem_free(fp, sizeof(sfp_file_t)); + return (0); +} + +int +sfprov_read(sfp_file_t *fp, char *buffer, uint64_t offset, uint32_t *numbytes) +{ + int rc; + + rc = vboxCallRead(&vbox_client, &fp->map, fp->handle, offset, + numbytes, (uint8_t *)buffer, 0); /* what is that last arg? */ + if (RT_FAILURE(rc)) + return (EINVAL); + return (0); +} + +int +sfprov_write(sfp_file_t *fp, char *buffer, uint64_t offset, uint32_t *numbytes) +{ + int rc; + + rc = vboxCallWrite(&vbox_client, &fp->map, fp->handle, offset, + numbytes, (uint8_t *)buffer, 0); /* what is that last arg? */ + if (RT_FAILURE(rc)) + return (EINVAL); + return (0); +} + + +static int +sfprov_getinfo(sfp_mount_t *mnt, char *path, RTFSOBJINFO *info) +{ + int rc; + SHFLCREATEPARMS parms; + SHFLSTRING *str; + int size; + + str = sfprov_string(path, &size); + parms.Handle = 0; + parms.Info.cbObject = 0; + parms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; + rc = vboxCallCreate(&vbox_client, &mnt->map, str, &parms); + kmem_free(str, size); + + if (RT_FAILURE(rc)) + return (EINVAL); + if (parms.Result != SHFL_FILE_EXISTS) + return (ENOENT); + *info = parms.Info; + return (0); +} + +/* + * get information about a file (or directory) + */ +int +sfprov_get_mode(sfp_mount_t *mnt, char *path, mode_t *mode) +{ + int rc; + RTFSOBJINFO info; + mode_t m = 0; + + rc = sfprov_getinfo(mnt, path, &info); + if (rc) + return (rc); + if (RTFS_IS_DIRECTORY(info.Attr.fMode)) + m |= S_IFDIR; + else if (RTFS_IS_FILE(info.Attr.fMode)) + m |= S_IFREG; + else if (RTFS_IS_FIFO(info.Attr.fMode)) + m |= S_IFDIR; + else if (RTFS_IS_DEV_CHAR(info.Attr.fMode)) + m |= S_IFCHR; + else if (RTFS_IS_DEV_BLOCK(info.Attr.fMode)) + m |= S_IFBLK; + else if (RTFS_IS_SYMLINK(info.Attr.fMode)) + m |= S_IFLNK; + else if (RTFS_IS_SOCKET(info.Attr.fMode)) + m |= S_IFSOCK; + + if (info.Attr.fMode & RTFS_UNIX_IRUSR) + m |= S_IRUSR; + if (info.Attr.fMode & RTFS_UNIX_IWUSR) + m |= S_IWUSR; + if (info.Attr.fMode & RTFS_UNIX_IXUSR) + m |= S_IXUSR; + if (info.Attr.fMode & RTFS_UNIX_IRGRP) + m |= S_IRGRP; + if (info.Attr.fMode & RTFS_UNIX_IWGRP) + m |= S_IWGRP; + if (info.Attr.fMode & RTFS_UNIX_IXGRP) + m |= S_IXGRP; + if (info.Attr.fMode & RTFS_UNIX_IROTH) + m |= S_IROTH; + if (info.Attr.fMode & RTFS_UNIX_IWOTH) + m |= S_IWOTH; + if (info.Attr.fMode & RTFS_UNIX_IXOTH) + m |= S_IXOTH; + *mode = m; + return (0); +} + +int +sfprov_get_size(sfp_mount_t *mnt, char *path, uint64_t *size) +{ + int rc; + RTFSOBJINFO info; + + rc = sfprov_getinfo(mnt, path, &info); + if (rc) + return (rc); + *size = info.cbObject; + return (0); +} + +int +sfprov_get_atime(sfp_mount_t *mnt, char *path, timestruc_t *time) +{ + int rc; + RTFSOBJINFO info; + uint64_t nanosec; + + rc = sfprov_getinfo(mnt, path, &info); + if (rc) + return (rc); + nanosec = RTTimeSpecGetNano(&info.AccessTime); + time->tv_sec = nanosec / 1000000000; + time->tv_nsec = nanosec % 1000000000; + return (0); +} + +int +sfprov_get_mtime(sfp_mount_t *mnt, char *path, timestruc_t *time) +{ + int rc; + RTFSOBJINFO info; + uint64_t nanosec; + + rc = sfprov_getinfo(mnt, path, &info); + if (rc) + return (rc); + nanosec = RTTimeSpecGetNano(&info.ModificationTime); + time->tv_sec = nanosec / 1000000000; + time->tv_nsec = nanosec % 1000000000; + return (0); +} + +int +sfprov_get_ctime(sfp_mount_t *mnt, char *path, timestruc_t *time) +{ + int rc; + RTFSOBJINFO info; + uint64_t nanosec; + + rc = sfprov_getinfo(mnt, path, &info); + if (rc) + return (rc); + nanosec = RTTimeSpecGetNano(&info.ChangeTime); + time->tv_sec = nanosec / 1000000000; + time->tv_nsec = nanosec % 1000000000; + return (0); +} + +/* + * Directory operations + */ +int +sfprov_mkdir(sfp_mount_t *mnt, char *path, sfp_file_t **fp) +{ + int rc; + SHFLCREATEPARMS parms; + SHFLSTRING *str; + int size; + sfp_file_t *newfp; + + str = sfprov_string(path, &size); + parms.Handle = 0; + parms.Info.cbObject = 0; + parms.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_CREATE_IF_NEW | + SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACCESS_READ; + rc = vboxCallCreate(&vbox_client, &mnt->map, str, &parms); + kmem_free(str, size); + + if (RT_FAILURE(rc)) + return (EINVAL); + if (parms.Handle == SHFL_HANDLE_NIL) { + if (parms.Result == SHFL_FILE_EXISTS) + return (EEXIST); + return (ENOENT); + } + newfp = kmem_alloc(sizeof(sfp_file_t), KM_SLEEP); + newfp->handle = parms.Handle; + newfp->map = mnt->map; + *fp = newfp; + return (0); +} + +int +sfprov_remove(sfp_mount_t *mnt, char *path) +{ + int rc; + SHFLSTRING *str; + int size; + + str = sfprov_string(path, &size); + rc = vboxCallRemove(&vbox_client, &mnt->map, str, SHFL_REMOVE_FILE); + kmem_free(str, size); + if (RT_FAILURE(rc)) + return (EINVAL); + return (0); +} + +int +sfprov_rmdir(sfp_mount_t *mnt, char *path) +{ + int rc; + SHFLSTRING *str; + int size; + + str = sfprov_string(path, &size); + rc = vboxCallRemove(&vbox_client, &mnt->map, str, SHFL_REMOVE_DIR); + kmem_free(str, size); + if (RT_FAILURE(rc)) + return (RTErrConvertToErrno(rc)); + return (0); +} + +int +sfprov_rename(sfp_mount_t *mnt, char *from, char *to, uint_t is_dir) +{ + int rc; + SHFLSTRING *old, *new; + int old_size, new_size; + + old = sfprov_string(from, &old_size); + new = sfprov_string(to, &new_size); + rc = vboxCallRename(&vbox_client, &mnt->map, old, new, + (is_dir ? SHFL_RENAME_DIR : SHFL_RENAME_FILE) | + SHFL_RENAME_REPLACE_IF_EXISTS); + kmem_free(old, old_size); + kmem_free(new, new_size); + if (RT_FAILURE(rc)) + return (RTErrConvertToErrno(rc)); + return (0); +} + + +/* + * Read all filenames in a directory. + * + * - success - all entries read and returned + * - ENOENT - Couldn't open the directory for reading + * - EINVAL - Internal error of some kind + * + * On successful return, buffer[0] is the start of an array of "char *" + * pointers to the filenames. The array ends with a NULL pointer. + * The remaining storage in buffer after that NULL pointer is where the + * filename strings actually are. + * + * On input nents is the max number of filenames the requestor can handle. + * On output nents is the number of entries at buff[0] + * + * The caller is responsible for freeing the returned buffer. + */ +int +sfprov_readdir( + sfp_mount_t *mnt, + char *path, + void **buffer, + size_t *buffersize, + uint32_t *nents) +{ + int error; + char *cp; + int len; + SHFLSTRING *mask_str = NULL; /* must be path with "/*" appended */ + int mask_size; + sfp_file_t *fp; + void *buff_start = NULL; + char **curr_b; + char *buff_end; + size_t buff_size; + static char infobuff[2 * MAXNAMELEN]; /* not on stack!! */ + SHFLDIRINFO *info = (SHFLDIRINFO *)&infobuff; + uint32_t numbytes = sizeof (infobuff); + uint32_t justone; + uint32_t cnt; + char **name_ptrs; + + *buffer = NULL; + *buffersize = 0; + if (*nents == 0) + return (EINVAL); + error = sfprov_open(mnt, path, &fp); + if (error != 0) + return (ENOENT); + + /* + * Create mask that VBox expects. This needs to be the directory path, + * plus a "*" wildcard to get all files. + */ + len = strlen(path) + 3; + cp = kmem_alloc(len, KM_SLEEP); + strcpy(cp, path); + strcat(cp, "/*"); + mask_str = sfprov_string(cp, &mask_size); + kmem_free(cp, len); + + /* + * Allocate the buffer to use for return values. Each entry + * in the buffer will have a pointer and the string itself. + * The pointers go in the front of the buffer, the strings + * at the end. + */ + buff_size = *nents * (sizeof(char *) + MAXNAMELEN); + name_ptrs = buff_start = kmem_alloc(buff_size, KM_SLEEP); + cp = (char *)buff_start + buff_size; + + /* + * Now loop using vboxCallDirInfo to get one file name at a time + */ + cnt = 0; + for (;;) { + justone = 1; + numbytes = sizeof (infobuff); + error = vboxCallDirInfo(&vbox_client, &fp->map, fp->handle, + mask_str, SHFL_LIST_RETURN_ONE, cnt, &numbytes, info, + &justone); + if (error == VERR_NO_MORE_FILES) { + break; + } + if (error == VERR_NO_TRANSLATION) { + continue; /* ?? just skip this one */ + } + if (error != VINF_SUCCESS || justone != 1) { + error = EINVAL; + goto done; + } + + /* + * Put this name in the buffer, stop if we run out of room. + */ + cp -= strlen(info->name.String.utf8) + 1; + if (cp < (char *)(&name_ptrs[cnt + 2])) + break; + strcpy(cp, info->name.String.utf8); + name_ptrs[cnt] = cp; + ++cnt; + } + error = 0; + name_ptrs[cnt] = NULL; + *nents = cnt; + *buffer = buff_start; + *buffersize = buff_size; +done: + if (error != 0) + kmem_free(buff_start, buff_size); + kmem_free(mask_str, mask_size); + sfprov_close(fp); + return (error); +} diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h new file mode 100644 index 000000000..c1ef4b89c --- /dev/null +++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h @@ -0,0 +1,110 @@ +/** @file + * VirtualBox File System for Solaris Guests, provider header. + */ + +/* + * Copyright (C) 2009 Sun Microsystems, Inc. + * + * Sun Microsystems, Inc. confidential + * All rights reserved + */ + +#ifndef __VBoxFS_prov_Solaris_h +#define __VBoxFS_prov_Solaris_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * These are the provider interfaces used by sffs to access the underlying + * shared file system. + */ +#define SFPROV_VERSION 1 + +/* + * Initialization and termination. + * sfprov_connect() is called once before any other interfaces and returns + * a handle used in further calls. The argument should be SFPROV_VERSION + * from above. On failure it returns a NULL pointer. + * + * sfprov_disconnect() must only be called after all sf file systems have been + * unmounted. + */ +typedef struct sfp_connection sfp_connection_t; + +extern sfp_connection_t *sfprov_connect(int); +extern void sfprov_disconnect(sfp_connection_t *); + + +/* + * Mount / Unmount a shared folder. + * + * sfprov_mount() takes as input the connection pointer and the name of + * the shared folder. On success, it returns zero and supplies an + * sfp_mount_t handle. On failure it returns any relevant errno value. + * + * sfprov_unmount() unmounts the mounted file system. It returns 0 on + * success and any relevant errno on failure. + */ +typedef struct sfp_mount sfp_mount_t; + +extern int sfprov_mount(sfp_connection_t *, char *, sfp_mount_t **); +extern int sfprov_unmount(sfp_mount_t *); + +/* + * query information about a mounted file system + */ +extern int sfprov_get_blksize(sfp_mount_t *, uint64_t *); +extern int sfprov_get_blksused(sfp_mount_t *, uint64_t *); +extern int sfprov_get_blksavail(sfp_mount_t *, uint64_t *); +extern int sfprov_get_maxnamesize(sfp_mount_t *, uint32_t *); +extern int sfprov_get_readonly(sfp_mount_t *, uint32_t *); + +/* + * File operations: open/close/read/write/etc. + * + * open/create can return any relevant errno, however ENOENT + * generally means that the host file didn't exist. + */ +typedef struct sfp_file sfp_file_t; + +extern int sfprov_create(sfp_mount_t *, char *path, sfp_file_t **fp); +extern int sfprov_open(sfp_mount_t *, char *path, sfp_file_t **fp); +extern int sfprov_close(sfp_file_t *fp); +extern int sfprov_read(sfp_file_t *, char * buffer, uint64_t offset, + uint32_t *numbytes); +extern int sfprov_write(sfp_file_t *, char * buffer, uint64_t offset, + uint32_t *numbytes); + + +/* + * get information about a file (or directory) using pathname + */ +extern int sfprov_get_mode(sfp_mount_t *, char *, mode_t *); +extern int sfprov_get_size(sfp_mount_t *, char *, uint64_t *); +extern int sfprov_get_atime(sfp_mount_t *, char *, timestruc_t *); +extern int sfprov_get_mtime(sfp_mount_t *, char *, timestruc_t *); +extern int sfprov_get_ctime(sfp_mount_t *, char *, timestruc_t *); + + +/* + * File/Directory operations + */ +extern int sfprov_trunc(sfp_mount_t *, char *); +extern int sfprov_remove(sfp_mount_t *, char *path); +extern int sfprov_mkdir(sfp_mount_t *, char *path, sfp_file_t **fp); +extern int sfprov_rmdir(sfp_mount_t *, char *path); +extern int sfprov_rename(sfp_mount_t *, char *from, char *to, uint_t is_dir); + +/* + * Read directory entries. + */ +extern int sfprov_readdir(sfp_mount_t *mnt, char *path, void **buffer, + size_t *buffersize, uint32_t *nents); + +#ifdef __cplusplus +} +#endif + +#endif /* __VBoxFS_prov_Solaris_h */ diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c new file mode 100644 index 000000000..599224a7b --- /dev/null +++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c @@ -0,0 +1,486 @@ +/** @file + * VirtualBox File System for Solaris Guests, VFS implementation. + */ + +/* + * Copyright (C) 2009 Sun Microsystems, Inc. + * + * Sun Microsystems, Inc. confidential + * All rights reserved + */ + +#include <VBox/log.h> +#include <VBox/version.h> + +#include <sys/types.h> +#include <sys/mntent.h> +#include <sys/param.h> +#include <sys/modctl.h> +#include <sys/mount.h> +#include <sys/policy.h> +#include <sys/atomic.h> +#include <sys/sysmacros.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/vfs.h> +#if !defined(VBOX_VFS_SOLARIS_10U6) +#include <sys/vfs_opreg.h> +#endif +#include <sys/pathname.h> +#include "vboxfs_prov.h" +#include "vboxfs_vnode.h" +#include "vboxfs_vfs.h" + +#ifdef u +#undef u +#endif + +#define VBOXSOLQUOTE2(x) #x +#define VBOXSOLQUOTE(x) VBOXSOLQUOTE2(x) +/** The module name. */ +#define DEVICE_NAME "vboxfs" +/** The module description as seen in 'modinfo'. */ +#define DEVICE_DESC "VirtualBox ShrdFS" + + +/* + * Shared Folders filesystem implementation of the Solaris VFS interfaces. + * Much of this is cookie cutter code for Solaris filesystem implementation. + */ + +/* forward declarations */ +static int sffs_init(int fstype, char *name); +static int sffs_mount(vfs_t *, vnode_t *, struct mounta *, cred_t *); +static int sffs_unmount(vfs_t *vfsp, int flag, cred_t *cr); +static int sffs_root(vfs_t *vfsp, vnode_t **vpp); +static int sffs_statvfs(vfs_t *vfsp, statvfs64_t *sbp); + +static mntopt_t sffs_options[] = { + /* Option Cancels Opt Arg Flags Data */ + {"uid", NULL, NULL, MO_HASVALUE, NULL}, + {"gid", NULL, NULL, MO_HASVALUE, NULL} +}; + +static mntopts_t sffs_options_table = { + sizeof (sffs_options) / sizeof (mntopt_t), + sffs_options +}; + +static vfsdef_t sffs_vfsdef = { + VFSDEF_VERSION, + DEVICE_NAME, + sffs_init, + VSW_HASPROTO, + &sffs_options_table +}; + +static int sffs_fstype; +static int sffs_major; /* major number for device */ + +kmutex_t sffs_minor_lock; +int sffs_minor; /* minor number for device */ + +/* + * Module linkage information + */ +static struct modlfs modlfs = { + &mod_fsops, + DEVICE_DESC " " VBOX_VERSION_STRING "r" VBOXSOLQUOTE(VBOX_SVN_REV), + &sffs_vfsdef +}; + +static struct modlinkage modlinkage = { + MODREV_1, &modlfs, NULL +}; + +static sfp_connection_t *sfprov = NULL; + +int +_init() +{ + return (mod_install(&modlinkage)); +} + +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&modlinkage, modinfop)); +} + + +int +_fini() +{ + int error; + + error = mod_remove(&modlinkage); + if (error) + return (error); + + /* + * Tear down the operations vectors + */ + sffs_vnode_fini(); + (void) vfs_freevfsops_by_type(sffs_fstype); + + /* + * close connection to the provider + */ + sfprov_disconnect(sfprov); + return (0); +} + + +static int +sffs_init(int fstype, char *name) +{ +#if defined(VBOX_VFS_SOLARIS_10U6) + static const fs_operation_def_t sffs_vfsops_template[] = { + VFSNAME_MOUNT, sffs_mount, + VFSNAME_UNMOUNT, sffs_unmount, + VFSNAME_ROOT, sffs_root, + VFSNAME_STATVFS, sffs_statvfs, + NULL, NULL + }; +#else + static const fs_operation_def_t sffs_vfsops_template[] = { + VFSNAME_MOUNT, { .vfs_mount = sffs_mount }, + VFSNAME_UNMOUNT, { .vfs_unmount = sffs_unmount }, + VFSNAME_ROOT, { .vfs_root = sffs_root }, + VFSNAME_STATVFS, { .vfs_statvfs = sffs_statvfs }, + NULL, NULL + }; +#endif + int error; + + ASSERT(fstype != 0); + sffs_fstype = fstype; + LogFlowFunc(("sffs_init() name=%s\n", name)); + + /* + * This may seem a silly way to do things for now. But the code + * is structured to easily allow it to be used on other hypervisors + * which would have a different implementation of the provider. + * Hopefully that'll never happen. :) + */ + sfprov = sfprov_connect(SFPROV_VERSION); + if (sfprov == NULL) { + cmn_err(CE_WARN, "sffs_init(): couldn't init sffs provider"); + return (ENODEV); + } + + error = vfs_setfsops(fstype, sffs_vfsops_template, NULL); + if (error != 0) { + cmn_err(CE_WARN, "sffs_init: bad vfs ops template"); + return (error); + } + + error = sffs_vnode_init(); + if (error != 0) { + (void) vfs_freevfsops_by_type(fstype); + cmn_err(CE_WARN, "sffs_init: bad vnode ops template"); + return (error); + } + + if ((sffs_major = getudev()) == (major_t)-1) { + cmn_err(CE_WARN, "sffs_init: Can't get unique device number."); + sffs_major = 0; + } + mutex_init(&sffs_minor_lock, NULL, MUTEX_DEFAULT, NULL); + return (0); +} + +/* + * wrapper for pn_get + */ +static int +sf_pn_get(char *rawpath, struct mounta *uap, char **outpath) +{ + pathname_t path; + int error; + + error = pn_get(rawpath, (uap->flags & MS_SYSSPACE) ? UIO_SYSSPACE : + UIO_USERSPACE, &path); + if (error) { + LogFlowFunc(("pn_get(%s) failed\n", rawpath)); + return (error); + } + *outpath = kmem_alloc(path.pn_pathlen + 1, KM_SLEEP); + strcpy(*outpath, path.pn_path); + pn_free(&path); + return (0); +} + +static int +sffs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) +{ + sffs_data_t *sffs; + char *mount_point = NULL; + char *share_name = NULL; + int error; + dev_t dev; + uid_t uid = 0; + gid_t gid = 0; + char *optval; + long val; + char *path; + sfp_mount_t *handle; + sfnode_t *sfnode; + + /* + * check we have permission to do the mount + */ + LogFlowFunc(("sffs_mount() started\n")); + error = secpolicy_fs_mount(cr, mvp, vfsp); + if (error != 0) + return (error); + + /* + * Mount point must be a directory + */ + if (mvp->v_type != VDIR) + return (ENOTDIR); + + /* + * no support for remount (what is it?) + */ + if (uap->flags & MS_REMOUNT) + return (ENOTSUP); + + /* + * Ensure that nothing else is actively in/under the mount point + */ + mutex_enter(&mvp->v_lock); + if ((uap->flags & MS_OVERLAY) == 0 && + (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { + mutex_exit(&mvp->v_lock); + return (EBUSY); + } + mutex_exit(&mvp->v_lock); + + /* + * check for read only has to be done early + */ + if (uap->flags & MS_RDONLY) { + vfsp->vfs_flag |= VFS_RDONLY; + vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); + } + + /* + * UID to use for all files + */ + if (vfs_optionisset(vfsp, "uid", &optval) && + ddi_strtol(optval, NULL, 10, &val) == 0 && + (uid_t)val == val) + uid = val; + + /* + * GID to use for all files + */ + if (vfs_optionisset(vfsp, "gid", &optval) && + ddi_strtol(optval, NULL, 10, &val) == 0 && + (gid_t)val == val) + gid = val; + + /* + * Any unknown options are an error + */ + if ((uap->flags & MS_DATA) && uap->datalen > 0) { + cmn_err(CE_WARN, "sffs: unknown mount options specified"); + return (EINVAL); + } + + /* + * get the mount point pathname + */ + error = sf_pn_get(uap->dir, uap, &mount_point); + if (error) + return (error); + + /* + * find what we are mounting + */ + error = sf_pn_get(uap->spec, uap, &share_name); + if (error) { + kmem_free(mount_point, strlen(mount_point) + 1); + return (error); + } + + /* + * Invoke Hypervisor mount interface before proceeding + */ + error = sfprov_mount(sfprov, share_name, &handle); + if (error) { + kmem_free(share_name, strlen(share_name) + 1); + kmem_free(mount_point, strlen(mount_point) + 1); + return (error); + } + + /* + * find an available minor device number for this mount + */ + mutex_enter(&sffs_minor_lock); + do { + sffs_minor = (sffs_minor + 1) & L_MAXMIN32; + dev = makedevice(sffs_major, sffs_minor); + } while (vfs_devismounted(dev)); + mutex_exit(&sffs_minor_lock); + + /* + * allocate and fill in the sffs structure + */ + sffs = kmem_alloc(sizeof (*sffs), KM_SLEEP); + sffs->sf_vfsp = vfsp; + sffs->sf_uid = uid; + sffs->sf_gid = gid; + sffs->sf_share_name = share_name; + sffs->sf_mntpath = mount_point; + sffs->sf_handle = handle; + sffs->sf_ino = 3; /* root mount point is always '3' */ + + /* + * fill in the vfs structure + */ + vfsp->vfs_data = (caddr_t)sffs; + vfsp->vfs_fstype = sffs_fstype; + vfsp->vfs_dev = dev; + vfsp->vfs_bsize = PAGESIZE; /* HERE JOE ??? */ + vfsp->vfs_flag |= VFS_NOTRUNC; /* HERE JOE ???? */ + vfs_make_fsid(&vfsp->vfs_fsid, dev, sffs_fstype); + + /* + * create the root vnode. + * XXX JOE What should the path be here? is "/" really right? + * other options? + */ + path = kmem_alloc(2, KM_SLEEP); + strcpy(path, "."); + mutex_enter(&sffs_lock); + sfnode = sfnode_make(sffs, path, VDIR, NULL, NULL); + sffs->sf_rootnode = sfnode_get_vnode(sfnode); + sffs->sf_rootnode->v_flag |= VROOT; + sffs->sf_rootnode->v_vfsp = vfsp; + mutex_exit(&sffs_lock); + + LogFlowFunc(("sffs_mount() success sffs=0x%p\n", sffs)); + return (error); +} + +static int +sffs_unmount(vfs_t *vfsp, int flag, cred_t *cr) +{ + sffs_data_t *sffs = (sffs_data_t *)vfsp->vfs_data; + int error; + + /* + * generic securty check + */ + LogFlowFunc(("sffs_unmount() of sffs=0x%p\n", sffs)); + if ((error = secpolicy_fs_unmount(cr, vfsp)) != 0) + return (error); + + /* + * forced unmount is not supported by this file system + * and thus, ENOTSUP, is being returned. + */ + if (flag & MS_FORCE) + return (ENOTSUP); + + /* + * Make sure nothing is still in use. + */ + if (sffs_purge(sffs) != 0) + return (EBUSY); + + /* + * Invoke Hypervisor unmount interface before proceeding + */ + error = sfprov_unmount(sffs->sf_handle); + if (error != 0) { + /* TBD anything here? */ + } + + kmem_free(sffs->sf_share_name, strlen(sffs->sf_share_name) + 1); + kmem_free(sffs->sf_mntpath, strlen(sffs->sf_mntpath) + 1); + kmem_free(sffs, sizeof(*sffs)); + LogFlowFunc(("sffs_unmount() done\n")); + return (0); +} + +/* + * return the vnode for the root of the mounted file system + */ +static int +sffs_root(vfs_t *vfsp, vnode_t **vpp) +{ + sffs_data_t *sffs = (sffs_data_t *)vfsp->vfs_data; + vnode_t *vp = sffs->sf_rootnode; + + VN_HOLD(vp); + *vpp = vp; + return (0); +} + +/* + * get some stats.. fake up the rest + */ +static int +sffs_statvfs(vfs_t *vfsp, statvfs64_t *sbp) +{ + sffs_data_t *sffs = (sffs_data_t *)vfsp->vfs_data; + uint64_t x; + uint32_t u; + dev32_t d32; + int error; + + bzero(sbp, sizeof(*sbp)); + error = sfprov_get_blksize(sffs->sf_handle, &x); + if (error != 0) + return (error); + sbp->f_bsize = x; + sbp->f_frsize = x; + + error = sfprov_get_blksavail(sffs->sf_handle, &x); + if (error != 0) + return (error); + sbp->f_bfree = x; + sbp->f_bavail = x; + sbp->f_files = x / 4; /* some kind of reasonable value */ + sbp->f_ffree = x / 4; + sbp->f_favail = x / 4; + + error = sfprov_get_blksused(sffs->sf_handle, &x); + if (error != 0) + return (error); + sbp->f_blocks = x + sbp->f_bavail; + + (void) cmpldev(&d32, vfsp->vfs_dev); + sbp->f_fsid = d32; + strcpy(&sbp->f_basetype[0], "sffs"); + sbp->f_flag |= ST_NOSUID; + + error = sfprov_get_readonly(sffs->sf_handle, &u); + if (error != 0) + return (error); + if (u) + sbp->f_flag |= ST_RDONLY; + + error = sfprov_get_maxnamesize(sffs->sf_handle, &u); + if (error != 0) + return (error); + sbp->f_namemax = u; + return (0); +} + +static void sffs_print(sffs_data_t *sffs) +{ + Log(("sffs_data_t at 0x%p\n", sffs)); + Log((" vfs_t *sf_vfsp = 0x%p\n", sffs->sf_vfsp)); + Log((" vnode_t *sf_rootnode = 0x%p\n", sffs->sf_rootnode)); + Log((" uid_t sf_uid = 0x%l\n", (ulong_t)sffs->sf_uid)); + Log((" gid_t sf_gid = 0x%l\n", (ulong_t)sffs->sf_gid)); + Log((" char *sf_share_name = %s\n", sffs->sf_share_name)); + Log((" char *sf_mntpath = %s\n", sffs->sf_mntpath)); + Log((" sfp_mount_t *sf_handle = 0x%p\n", sffs->sf_handle)); +} + diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.h b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.h new file mode 100644 index 000000000..95b93671b --- /dev/null +++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.h @@ -0,0 +1,38 @@ +/** @file + * VirtualBox File System Driver for Solaris Guests, VFS header. + */ + +/* + * Copyright (C) 2009 Sun Microsystems, Inc. + * + * Sun Microsystems, Inc. confidential + * All rights reserved + */ + +#ifndef __VBoxFS_vfs_Solaris_h +#define __VBoxFS_vfs_Solaris_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Shared Folders filesystem per-mount data structure. + */ +typedef struct sffs_data { + vfs_t *sf_vfsp; /* filesystem's vfs struct */ + vnode_t *sf_rootnode; /* of vnode of the root directory */ + uid_t sf_uid; /* owner of all shared folders */ + gid_t sf_gid; /* group of all shared folders */ + char *sf_share_name; + char *sf_mntpath; /* name of mount point */ + sfp_mount_t *sf_handle; + uint64_t sf_ino; /* per FS ino generator */ +} sffs_data_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* __VBoxFS_vfs_Solaris_h */ diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c new file mode 100644 index 000000000..793fb8b8f --- /dev/null +++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c @@ -0,0 +1,1630 @@ +/** @file + * VirtualBox File System for Solaris Guests, vnode implementation. + */ + +/* + * Copyright (C) 2009 Sun Microsystems, Inc. + * + * Sun Microsystems, Inc. confidential + * All rights reserved + */ + +/* + * Shared Folder File System is used from Solaris when run as a guest operating + * system on VirtualBox, though is meant to be usable with any hypervisor that + * can provide similar functionality. The sffs code handles all the Solaris + * specific semantics and relies on a provider module to actually access + * directories, files, etc. The provider interfaces are described in + * "vboxfs_prov.h" and the module implementing them is shipped as part of the + * VirtualBox Guest Additions for Solaris. + * + * The shared folder file system is similar to a networked file system, + * but with some caveats. The sffs code caches minimal information and proxies + * out to the provider whenever possible. Here are some things that are + * handled in this code and not by the proxy: + * + * - a way to open ".." from any already open directory + * - st_ino numbers + * - detecting directory changes that happened on the host. + * + * The implementation builds a cache of information for every file/directory + * ever accessed in all mounted sffs filesystems using sf_node structures. + * + * This information for both open or closed files can become invalid if + * asynchronous changes are made on the host. Solaris should not panic() in + * this event, but some file system operations may return unexpected errors. + * Information for such directories or files while they have active vnodes + * is removed from the regular cache and stored in a "stale" bucket until + * the vnode becomes completely inactive. + * + * No file data is cached in the guest. This means we don't support mmap() yet. + * A future version could relatively easily add support for read-only + * mmap(MAP_SHARED) and any mmap(MAP_PRIVATE). But a la ZFS, this data caching + * would not be coherent with normal simultaneous read()/write() operations, + * nor will it be coherent with data access on the host. Writable + * mmap(MAP_SHARED) access is possible, but guaranteeing any kind of coherency + * with concurrent activity on the host would be near impossible with the + * existing interfaces. + * + * A note about locking. sffs is not a high performance file system. + * No fine grained locking is done. The one sffs_lock protects just about + * everything. + */ + +#include <VBox/log.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mntent.h> +#include <sys/param.h> +#include <sys/modctl.h> +#include <sys/mount.h> +#include <sys/policy.h> +#include <sys/atomic.h> +#include <sys/sysmacros.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/vfs.h> +#if !defined(VBOX_VFS_SOLARIS_10U6) +#include <sys/vfs_opreg.h> +#endif +#include <sys/pathname.h> +#include <sys/dirent.h> +#include <sys/fs_subr.h> +#include "vboxfs_prov.h" +#include "vboxfs_vnode.h" +#include "vboxfs_vfs.h" + +static struct vnodeops *sffs_ops = NULL; + +kmutex_t sffs_lock; +static avl_tree_t sfnodes; +static avl_tree_t stale_sfnodes; + +/* + * For now we'll use an I/O buffer that doesn't page fault for VirtualBox + * to transfer data into. + */ +char *sffs_buffer; + +/* + * sfnode_compare() is needed for AVL tree functionality. + * The nodes are sorted by mounted filesystem, then path. If the + * nodes are stale, the node pointer itself is used to force uniqueness. + */ +static int +sfnode_compare(const void *a, const void *b) +{ + sfnode_t *x = (sfnode_t *)a; + sfnode_t *y = (sfnode_t *)b; + int diff; + + if (x->sf_is_stale) { + ASSERT(y->sf_is_stale); + diff = strcmp(x->sf_path, y->sf_path); + if (diff == 0) + diff = (uintptr_t)y - (uintptr_t)x; + } else { + ASSERT(!y->sf_is_stale); + diff = (uintptr_t)y->sf_sffs - (uintptr_t)x->sf_sffs; + if (diff == 0) + diff = strcmp(x->sf_path, y->sf_path); + } + if (diff < 0) + return (-1); + if (diff > 0) + return (1); + return (0); +} + +/* + * Construct a new pathname given an sfnode plus an optional tail component. + * This handles ".." and "." + */ +static char * +sfnode_construct_path(sfnode_t *node, char *tail) +{ + char *p; + + if (strcmp(tail, ".") == 0 || strcmp(tail, "..") == 0) + panic("construct path for %s", tail); + p = kmem_alloc(strlen(node->sf_path) + 1 + strlen(tail) + 1, KM_SLEEP); + strcpy(p, node->sf_path); + strcat(p, "/"); + strcat(p, tail); + return (p); +} + +/* + * Open the provider file associated with a vnode. Holding the file open is + * the only way we have of trying to have a vnode continue to refer to the + * same host file in the host in light of the possibility of host side renames. + */ +static void +sfnode_open(sfnode_t *node) +{ + int error; + sfp_file_t *fp; + + if (node->sf_file != NULL) + return; + error = sfprov_open(node->sf_sffs->sf_handle, node->sf_path, &fp); + if (error == 0) + node->sf_file = fp; +} + +/* + * get a new vnode reference for an sfnode + */ +vnode_t * +sfnode_get_vnode(sfnode_t *node) +{ + vnode_t *vp; + + if (node->sf_vnode != NULL) { + VN_HOLD(node->sf_vnode); + } else { + vp = vn_alloc(KM_SLEEP); + LogFlowFunc((" %s gets vnode 0x%p\n", node->sf_path, vp)); + vp->v_type = node->sf_type; + vp->v_vfsp = node->sf_sffs->sf_vfsp; + VFS_HOLD(vp->v_vfsp); + vn_setops(vp, sffs_ops); + vp->v_flag = VNOMAP | VNOSWAP; + vn_exists(vp); + vp->v_data = node; + node->sf_vnode = vp; + } + sfnode_open(node); + return (node->sf_vnode); +} + +/* + * Allocate and initialize a new sfnode and assign it a vnode + */ +sfnode_t * +sfnode_make( + sffs_data_t *sffs, + char *path, + vtype_t type, + sfp_file_t *fp, + sfnode_t *parent) /* can be NULL for root */ +{ + sfnode_t *node; + avl_index_t where; + + ASSERT(MUTEX_HELD(&sffs_lock)); + ASSERT(path != NULL); + + /* + * build the sfnode + */ + LogFlowFunc(("sffs_make(%s)\n", path)); + node = kmem_alloc(sizeof (*node), KM_SLEEP); + node->sf_sffs = sffs; + node->sf_path = path; + node->sf_ino = sffs->sf_ino++; + node->sf_type = type; + node->sf_is_stale = 0; /* never stale at creation */ + node->sf_file = fp; + node->sf_vnode = NULL; /* do this before any sfnode_get_vnode() */ + node->sf_children = 0; + node->sf_parent = parent; + if (parent) + ++parent->sf_children; + + /* + * add the new node to our cache + */ + if (avl_find(&sfnodes, node, &where) != NULL) + panic("sffs_create_sfnode(%s): duplicate sfnode_t", path); + avl_insert(&sfnodes, node, where); + return (node); +} + +/* + * destroy an sfnode + */ +static void +sfnode_destroy(sfnode_t *node) +{ + avl_index_t where; + avl_tree_t *tree; + sfnode_t *parent; +top: + parent = node->sf_parent; + ASSERT(MUTEX_HELD(&sffs_lock)); + ASSERT(node->sf_path != NULL); + LogFlowFunc(("sffs_destroy(%s)%s\n", node->sf_path, node->sf_is_stale ? " stale": "")); + if (node->sf_children != 0) + panic("sfnode_destroy(%s) has %d children", node->sf_children); + if (node->sf_vnode != NULL) + panic("sfnode_destroy(%s) has active vnode", node->sf_path); + + if (node->sf_is_stale) + tree = &stale_sfnodes; + else + tree = &sfnodes; + if (avl_find(tree, node, &where) == NULL) + panic("sfnode_destroy(%s) not found", node->sf_path); + avl_remove(tree, node); + + VFS_RELE(node->sf_sffs->sf_vfsp); + kmem_free(node->sf_path, strlen(node->sf_path) + 1); + kmem_free(node, sizeof (*node)); + if (parent != NULL) { + if (parent->sf_children == 0) + panic("sfnode_destroy(%s) parent has no child"); + --parent->sf_children; + if (parent->sf_children == 0 && + parent->sf_is_stale && + parent->sf_vnode == NULL) { + node = parent; + goto top; + } + } +} + +/* + * Some sort of host operation on an sfnode has failed or it has been + * deleted. Mark this node and any children as stale, deleting knowledge + * about any which do not have active vnodes or children + * This also handle deleting an inactive node that was already stale. + */ +static void +sfnode_make_stale(sfnode_t *node) +{ + sfnode_t *n; + int len; + ASSERT(MUTEX_HELD(&sffs_lock)); + avl_index_t where; + + /* + * First deal with any children of a directory node. + * If a directory becomes stale, anything below it becomes stale too. + */ + if (!node->sf_is_stale && node->sf_type == VDIR) { + len = strlen(node->sf_path); + + n = node; + while ((n = AVL_NEXT(&sfnodes, node)) != NULL) { + ASSERT(!n->sf_is_stale); + + /* + * quit when no longer seeing children of node + */ + if (n->sf_sffs != node->sf_sffs || + strncmp(node->sf_path, n->sf_path, len) != 0 || + n->sf_path[len] != '/') + break; + + /* + * Either mark the child as stale or destroy it + */ + if (n->sf_vnode == NULL && n->sf_children == 0) { + sfnode_destroy(n); + } else { + LogFlowFunc(("sffs_make_stale(%s) sub\n", n->sf_path)); + if (avl_find(&sfnodes, n, &where) == NULL) + panic("sfnode_make_stale(%s)" + " not in sfnodes", n->sf_path); + avl_remove(&sfnodes, n); + n->sf_is_stale = 1; + if (avl_find(&stale_sfnodes, n, &where) != NULL) + panic("sffs_make_stale(%s) duplicates", + n->sf_path); + avl_insert(&stale_sfnodes, n, where); + } + } + } + + /* + * Now deal with the given node. + */ + if (node->sf_vnode == NULL && node->sf_children == 0) { + sfnode_destroy(node); + } else if (!node->sf_is_stale) { + LogFlowFunc(("sffs_make_stale(%s)\n", node->sf_path)); + if (avl_find(&sfnodes, node, &where) == NULL) + panic("sfnode_make_stale(%s) not in sfnodes", + node->sf_path); + avl_remove(&sfnodes, node); + node->sf_is_stale = 1; + if (avl_find(&stale_sfnodes, node, &where) != NULL) + panic("sffs_make_stale(%s) duplicates", node->sf_path); + avl_insert(&stale_sfnodes, node, where); + } +} + +/* + * Rename a file or a directory + */ +static void +sfnode_rename(sfnode_t *node, sfnode_t *newparent, char *path) +{ + sfnode_t *n; + sfnode_t template; + avl_index_t where; + int len = strlen(path); + int old_len; + char *new_path; + char *tail; + ASSERT(MUTEX_HELD(&sffs_lock)); + + ASSERT(!node->sf_is_stale); + + /* + * Have to remove anything existing that had the new name. + */ + template.sf_sffs = node->sf_sffs; + template.sf_path = path; + template.sf_is_stale = 0; + n = avl_find(&sfnodes, &template, &where); + if (n != NULL) + sfnode_make_stale(n); + + /* + * Do the renaming, deal with any children of this node first. + */ + if (node->sf_type == VDIR) { + old_len = strlen(node->sf_path); + while ((n = AVL_NEXT(&sfnodes, node)) != NULL) { + + /* + * quit when no longer seeing children of node + */ + if (n->sf_sffs != node->sf_sffs || + strncmp(node->sf_path, n->sf_path, old_len) != 0 || + n->sf_path[old_len] != '/') + break; + + /* + * Rename the child: + * - build the new path name + * - unlink the AVL node + * - assign the new name + * - re-insert the AVL name + */ + ASSERT(strlen(n->sf_path) > old_len); + tail = n->sf_path + old_len; /* includes intial "/" */ + new_path = kmem_alloc(len + strlen(tail) + 1, + KM_SLEEP); + strcpy(new_path, path); + strcat(new_path, tail); + if (avl_find(&sfnodes, n, &where) == NULL) + panic("sfnode_rename(%s) not in sfnodes", + n->sf_path); + avl_remove(&sfnodes, n); + LogFlowFunc(("sfnode_rname(%s to %s) sub\n", n->sf_path, new_path)); + kmem_free(n->sf_path, strlen(n->sf_path) + 1); + n->sf_path = new_path; + if (avl_find(&sfnodes, n, &where) != NULL) + panic("sfnode_rename(%s) duplicates", + n->sf_path); + avl_insert(&sfnodes, n, where); + } + } + + /* + * Deal with the given node. + */ + if (avl_find(&sfnodes, node, &where) == NULL) + panic("sfnode_rename(%s) not in sfnodes", node->sf_path); + avl_remove(&sfnodes, node); + LogFlowFunc(("sfnode_rname(%s to %s)\n", node->sf_path, path)); + kmem_free(node->sf_path, strlen(node->sf_path) + 1); + node->sf_path = path; + if (avl_find(&sfnodes, node, &where) != NULL) + panic("sfnode_rename(%s) duplicates", node->sf_path); + avl_insert(&sfnodes, node, where); + + /* + * change the parent + */ + if (node->sf_parent == NULL) + panic("sfnode_rename(%s) no parent", node->sf_path); + if (node->sf_parent->sf_children == 0) + panic("sfnode_rename(%s) parent has no child", node->sf_path); + --node->sf_parent->sf_children; + node->sf_parent = newparent; + ++newparent->sf_children; +} + +/* + * Look for a cached node, if not found either handle ".." or try looking + * via the provider. Create an entry in sfnodes if found but not cached yet. + * If the create flag is set, a file or directory is created. If the file + * already existed, an error is returned. + * Nodes returned from this routine always have a vnode with its ref count + * bumped by 1. + */ +static sfnode_t * +sfnode_lookup(sfnode_t *dir, char *name, vtype_t create) +{ + avl_index_t where; + sfnode_t template; + sfnode_t *node; + int error; + int type; + char *fullpath; + sfp_file_t *fp; + + ASSERT(MUTEX_HELD(&sffs_lock)); + + /* + * handle referencing myself + */ + if (strcmp(name, "") == 0 || strcmp(name, ".") == 0) + return (dir); + + /* + * deal with parent + */ + if (strcmp(name, "..") == 0) + return (dir->sf_parent); + + /* + * Look for an existing node. + */ + fullpath = sfnode_construct_path(dir, name); + template.sf_sffs = dir->sf_sffs; + template.sf_path = fullpath; + template.sf_is_stale = 0; + node = avl_find(&sfnodes, &template, &where); + if (node != NULL) { + kmem_free(fullpath, strlen(fullpath) + 1); + if (create != VNON) + return (NULL); + return (node); + } + + /* + * No entry for this path currently. + * Check if the file exists with the provider and get the type from + * there. + */ + if (create == VREG) { + type = VREG; + error = sfprov_create(dir->sf_sffs->sf_handle, fullpath, &fp); + } else if (create == VDIR) { + type = VDIR; + error = sfprov_mkdir(dir->sf_sffs->sf_handle, fullpath, &fp); + } else { + mode_t m; + fp = NULL; + type = VNON; + error = + sfprov_get_mode(dir->sf_sffs->sf_handle, fullpath, &m); + if (error != 0) + error = ENOENT; + else if (S_ISDIR(m)) + type = VDIR; + else if (S_ISREG(m)) + type = VREG; + } + + /* + * If no errors, make a new node and return it. + */ + if (error) { + kmem_free(fullpath, strlen(fullpath) + 1); + return (NULL); + } + node = sfnode_make(dir->sf_sffs, fullpath, type, fp, dir); + return (node); +} + + +/* + * uid and gid in sffs determine owner and group for all files. + */ +static int +sfnode_access(sfnode_t *node, mode_t mode, cred_t *cr) +{ + sffs_data_t *sffs = node->sf_sffs; + mode_t m; + int shift = 0; + int error; + vnode_t *vp; + + ASSERT(MUTEX_HELD(&sffs_lock)); + + /* + * get the mode from the provider + */ + error = sfprov_get_mode(node->sf_sffs->sf_handle, node->sf_path, &m); + if (error != 0) { + m = 0; + if (error == ENOENT) + sfnode_make_stale(node); + } + + /* + * mask off the permissions based on uid/gid + */ + if (crgetuid(cr) != sffs->sf_uid) { + shift += 3; + if (groupmember(sffs->sf_gid, cr) == 0) + shift += 3; + } + mode &= ~(m << shift); + + if (mode == 0) { + error = 0; + } else { + vp = sfnode_get_vnode(node); + error = secpolicy_vnode_access(cr, vp, sffs->sf_uid, mode); + VN_RELE(vp); + } + return (error); +} + + +/* + * + * Everything below this point are the vnode operations used by Solaris VFS + */ +static int +sffs_readdir( + vnode_t *vp, + uio_t *uiop, + cred_t *cred, + int *eofp, + caller_context_t *ct, + int flags) +{ + sfnode_t *dir = VN2SFN(vp); + sfnode_t *node; + struct dirent64 *dirent; + int dummy_eof; + int error = 0; + int namelen; + void *prov_buff = NULL; + size_t prov_buff_size; + char **names; + uint32_t nents; + uint32_t index; + + if (uiop->uio_iovcnt != 1) + return (EINVAL); + + if (vp->v_type != VDIR) + return (ENOTDIR); + + if (eofp == NULL) + eofp = &dummy_eof; + *eofp = 0; + + if (uiop->uio_loffset >= MAXOFF_T) { + *eofp = 1; + return (0); + } + + dirent = kmem_zalloc(DIRENT64_RECLEN(MAXNAMELEN), KM_SLEEP); + + /* + * Get the directory entry names from the host. This gets all + * entries, so add in starting offset. Max the caller can expect + * would be the size of the UIO buffer / sizeof of a dirent for + * file with name of length 1 + */ + mutex_enter(&sffs_lock); + index = uiop->uio_loffset; + nents = index + (uiop->uio_resid / DIRENT64_RECLEN(1)); + error = sfprov_readdir(dir->sf_sffs->sf_handle, dir->sf_path, + &prov_buff, &prov_buff_size, &nents); + if (error != 0) + goto done; + if (nents <= index) { + *eofp = 1; + goto done; + } + names = (void *)prov_buff; + + /* + * Lookup each of the names, so that we have ino's. + */ + for (; index < nents; ++index) { + if (strcmp(names[index], ".") == 0) { + node = dir; + } else if (strcmp(names[index], "..") == 0) { + node = dir->sf_parent; + if (node == NULL) + node = dir; + } else { + node = sfnode_lookup(dir, names[index], VNON); + if (node == NULL) + panic("sffs_readdir() lookup failed"); + } + namelen = strlen(names[index]); + strcpy(&dirent->d_name[0], names[index]); + dirent->d_reclen = DIRENT64_RECLEN(namelen); + dirent->d_off = index; + dirent->d_ino = node->sf_ino; + if (dirent->d_reclen > uiop->uio_resid) { + error = ENOSPC; + break; + } + error = uiomove(dirent, dirent->d_reclen, UIO_READ, uiop); + if (error != 0) + break; + bzero(&dirent->d_name[0], namelen); + } + if (error == 0 && index >= nents) + *eofp = 1; +done: + mutex_exit(&sffs_lock); + if (prov_buff != NULL) + kmem_free(prov_buff, prov_buff_size); + kmem_free(dirent, DIRENT64_RECLEN(MAXNAMELEN)); + return (error); +} + + +#if defined(VBOX_VFS_SOLARIS_10U6) +/* + * HERE JOE.. this may need more logic, need to look at other file systems + */ +static int +sffs_pathconf( + vnode_t *vp, + int cmd, + ulong_t *valp, + cred_t *cr) +{ + return (fs_pathconf(vp, cmd, valp, cr)); +} +#else +/* + * HERE JOE.. this may need more logic, need to look at other file systems + */ +static int +sffs_pathconf( + vnode_t *vp, + int cmd, + ulong_t *valp, + cred_t *cr, + caller_context_t *ct) +{ + return (fs_pathconf(vp, cmd, valp, cr, ct)); +} +#endif + +static int +sffs_getattr( + vnode_t *vp, + vattr_t *vap, + int flags, + cred_t *cred, + caller_context_t *ct) +{ + sfnode_t *node = VN2SFN(vp); + sffs_data_t *sffs = node->sf_sffs; + mode_t mode; + timestruc_t time; + uint64_t x; + int error; + + mutex_enter(&sffs_lock); + vap->va_type = vp->v_type; + vap->va_uid = sffs->sf_uid; + vap->va_gid = sffs->sf_gid; + vap->va_fsid = sffs->sf_vfsp->vfs_dev; + vap->va_nodeid = node->sf_ino; + vap->va_nlink = 1; + vap->va_rdev = sffs->sf_vfsp->vfs_dev; + vap->va_seq = 0; + + error = sfprov_get_mode(node->sf_sffs->sf_handle, node->sf_path, &mode); + if (error == ENOENT) + sfnode_make_stale(node); + if (error != 0) + goto done; + vap->va_mode = mode & MODEMASK; + + error = sfprov_get_size(node->sf_sffs->sf_handle, node->sf_path, &x); + if (error == ENOENT) + sfnode_make_stale(node); + if (error != 0) + goto done; + vap->va_size = x; + vap->va_blksize = 512; + vap->va_nblocks = (x + 511) / 512; + + error = + sfprov_get_atime(node->sf_sffs->sf_handle, node->sf_path, &time); + if (error == ENOENT) + sfnode_make_stale(node); + if (error != 0) + goto done; + vap->va_atime = time; + + error = + sfprov_get_mtime(node->sf_sffs->sf_handle, node->sf_path, &time); + if (error == ENOENT) + sfnode_make_stale(node); + if (error != 0) + goto done; + vap->va_mtime = time; + + error = + sfprov_get_ctime(node->sf_sffs->sf_handle, node->sf_path, &time); + if (error == ENOENT) + sfnode_make_stale(node); + if (error != 0) + goto done; + vap->va_ctime = time; + +done: + mutex_exit(&sffs_lock); + return (error); +} + +/*ARGSUSED*/ +static int +sffs_read( + vnode_t *vp, + struct uio *uio, + int ioflag, + cred_t *cred, + caller_context_t *ct) +{ + sfnode_t *node = VN2SFN(vp); + int error = 0; + uint32_t bytes; + uint32_t done; + ulong_t offset; + ssize_t total; + + if (vp->v_type == VDIR) + return (EISDIR); + if (vp->v_type != VREG) + return (EINVAL); + if (uio->uio_loffset >= MAXOFF_T) + return (0); + if (uio->uio_loffset < 0) + return (EINVAL); + total = uio->uio_resid; + if (total == 0) + return (0); + + mutex_enter(&sffs_lock); + sfnode_open(node); + if (node->sf_file == NULL) { + mutex_exit(&sffs_lock); + return (EINVAL); + } + + do { + offset = uio->uio_offset; + done = bytes = MIN(PAGESIZE, uio->uio_resid); + error = sfprov_read(node->sf_file, sffs_buffer, offset, &done); + if (error == 0 && done > 0) + error = uiomove(sffs_buffer, done, UIO_READ, uio); + } while (error == 0 && uio->uio_resid > 0 && done > 0); + + mutex_exit(&sffs_lock); + + /* + * a partial read is never an error + */ + if (total != uio->uio_resid) + error = 0; + return (error); +} + +/*ARGSUSED*/ +static int +sffs_write( + vnode_t *vp, + struct uio *uiop, + int ioflag, + cred_t *cred, + caller_context_t *ct) +{ + sfnode_t *node = VN2SFN(vp); + int error = 0; + uint32_t bytes; + uint32_t done; + ulong_t offset; + ssize_t total; + rlim64_t limit = uiop->uio_llimit; + + if (vp->v_type == VDIR) + return (EISDIR); + if (vp->v_type != VREG) + return (EINVAL); + + /* + * We have to hold this lock for a long time to keep + * multiple FAPPEND writes from intermixing + */ + mutex_enter(&sffs_lock); + sfnode_open(node); + if (node->sf_file == NULL) { + mutex_exit(&sffs_lock); + return (EINVAL); + } + if (ioflag & FAPPEND) { + uint64_t endoffile; + + error = sfprov_get_size(node->sf_sffs->sf_handle, + node->sf_path, &endoffile); + if (error == ENOENT) + sfnode_make_stale(node); + if (error != 0) { + mutex_exit(&sffs_lock); + return (error); + } + uiop->uio_loffset = endoffile; + } + + if (vp->v_type != VREG || uiop->uio_loffset < 0) { + mutex_exit(&sffs_lock); + return (EINVAL); + } + if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) + limit = MAXOFFSET_T; + if (limit > MAXOFF_T) + limit = MAXOFF_T; + + if (uiop->uio_loffset >= limit) { + proc_t *p = ttoproc(curthread); + mutex_enter(&p->p_lock); + (void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE], p->p_rctls, + p, RCA_UNSAFE_SIGINFO); + mutex_exit(&p->p_lock); + mutex_exit(&sffs_lock); + return (EFBIG); + } + + if (uiop->uio_loffset >= MAXOFF_T) { + mutex_exit(&sffs_lock); + return (EFBIG); + } + + + total = uiop->uio_resid; + if (total == 0) { + mutex_exit(&sffs_lock); + return (0); + } + + do { + offset = uiop->uio_offset; + bytes = MIN(PAGESIZE, uiop->uio_resid); + if (offset + bytes >= limit) { + if (offset >= limit) { + error = EFBIG; + break; + } + bytes = limit - offset; + } + error = uiomove(sffs_buffer, bytes, UIO_WRITE, uiop); + if (error != 0) + break; + done = bytes; + if (error == 0) + error = sfprov_write(node->sf_file, sffs_buffer, + offset, &done); + total -= done; + if (done != bytes) { + uiop->uio_resid += bytes - done; + break; + } + } while (error == 0 && uiop->uio_resid > 0 && done > 0); + + mutex_exit(&sffs_lock); + + /* + * A short write is never really an error. + */ + if (total != uiop->uio_resid) + error = 0; + return (error); +} + +/*ARGSUSED*/ +static int +sffs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct) +{ + sfnode_t *node = VN2SFN(vp); + int error; + + mutex_enter(&sffs_lock); + error = sfnode_access(node, mode, cr); + mutex_exit(&sffs_lock); + return (error); +} + +/* + * Lookup an entry in a directory and create a new vnode if found. + */ +/* ARGSUSED3 */ +static int +sffs_lookup( + vnode_t *dvp, /* the directory vnode */ + char *name, /* the name of the file or directory */ + vnode_t **vpp, /* the vnode we found or NULL */ + struct pathname *pnp, + int flags, + vnode_t *rdir, + cred_t *cred, + caller_context_t *ct, + int *direntflags, + struct pathname *realpnp) +{ + int error; + sfnode_t *node; + + /* + * dvp must be a directory + */ + if (dvp->v_type != VDIR) + return (ENOTDIR); + + /* + * An empty component name or just "." means the directory itself. + * Don't do any further lookup or checking. + */ + if (strcmp(name, "") == 0 || strcmp(name, ".") == 0) { + VN_HOLD(dvp); + *vpp = dvp; + return (0); + } + + /* + * Check permission to look at this directory. We always allow "..". + */ + mutex_enter(&sffs_lock); + if (strcmp(name, "..") != 0) { + error = sfnode_access(VN2SFN(dvp), VEXEC, cred); + if (error) { + mutex_exit(&sffs_lock); + return (error); + } + } + + /* + * Lookup the node. + */ + node = sfnode_lookup(VN2SFN(dvp), name, VNON); + if (node != NULL) + *vpp = sfnode_get_vnode(node); + mutex_exit(&sffs_lock); + return ((node == NULL) ? ENOENT : 0); +} + +/*ARGSUSED*/ +static int +sffs_create( + vnode_t *dvp, + char *name, + struct vattr *vap, + vcexcl_t exclusive, + int mode, + vnode_t **vpp, + cred_t *cr, + int flag, + caller_context_t *ct, + vsecattr_t *vsecp) +{ + vnode_t *vp; + sfnode_t *node; + int error; + + ASSERT(name != NULL); + + /* + * this is used for regular files, not mkdir + */ + if (vap->va_type == VDIR) + return (EISDIR); + if (vap->va_type != VREG) + return (EINVAL); + + /* + * is this a pre-existing file? + */ + error = sffs_lookup(dvp, name, &vp, + NULL, 0, NULL, cr, ct, NULL, NULL); + if (error == ENOENT) + vp = NULL; + else if (error != 0) + return (error); + + /* + * Operation on a pre-existing file. + */ + if (vp != NULL) { + if (exclusive == EXCL) { + VN_RELE(vp); + return (EEXIST); + } + if (vp->v_type == VDIR && (mode & VWRITE) == VWRITE) { + VN_RELE(vp); + return (EISDIR); + } + + mutex_enter(&sffs_lock); + node = VN2SFN(vp); + error = sfnode_access(node, mode, cr); + if (error != 0) { + mutex_exit(&sffs_lock); + VN_RELE(vp); + return (error); + } + + /* + * handle truncating an existing file + */ + if (vp->v_type == VREG && (vap->va_mask & AT_SIZE) && + vap->va_size == 0) { + sfnode_open(node); + if (node->sf_path == NULL) + error = ENOENT; + else + error = sfprov_trunc(node->sf_sffs->sf_handle, + node->sf_path); + if (error) { + mutex_exit(&sffs_lock); + VN_RELE(vp); + return (error); + } + } + mutex_exit(&sffs_lock); + *vpp = vp; + return (0); + } + + /* + * Create a new node. First check for a race creating it. + */ + mutex_enter(&sffs_lock); + node = sfnode_lookup(VN2SFN(dvp), name, VNON); + if (node != NULL) { + mutex_exit(&sffs_lock); + return (EEXIST); + } + + /* + * Doesn't exist yet and we have the lock, so create it. + */ + node = sfnode_lookup(VN2SFN(dvp), name, VREG); + mutex_exit(&sffs_lock); + if (node == NULL) + return (EINVAL); + *vpp = sfnode_get_vnode(node); + return (0); +} + +/*ARGSUSED*/ +static int +sffs_mkdir( + vnode_t *dvp, + char *nm, + vattr_t *va, + vnode_t **vpp, + cred_t *cred, + caller_context_t *ct, + int flags, + vsecattr_t *vsecp) +{ + sfnode_t *node; + vnode_t *vp; + int error; + + /* + * These should never happen + */ + ASSERT(nm != NULL); + ASSERT(strcmp(nm, "") != 0); + ASSERT(strcmp(nm, ".") != 0); + ASSERT(strcmp(nm, "..") != 0); + + /* + * Do an unlocked look up first + */ + error = sffs_lookup(dvp, nm, &vp, NULL, 0, NULL, cred, ct, NULL, NULL); + if (error == 0) { + VN_RELE(vp); + return (EEXIST); + } + if (error != ENOENT) + return (error); + + /* + * Must be able to write in current directory + */ + mutex_enter(&sffs_lock); + error = sfnode_access(VN2SFN(dvp), VWRITE, cred); + if (error) { + mutex_exit(&sffs_lock); + return (error); + } + + node = sfnode_lookup(VN2SFN(dvp), nm, VDIR); + mutex_exit(&sffs_lock); + if (node == NULL) + return (EACCES); + *vpp = sfnode_get_vnode(node); + return (0); +} + +/*ARGSUSED*/ +static int +sffs_rmdir( + struct vnode *dvp, + char *nm, + vnode_t *cdir, + cred_t *cred, + caller_context_t *ct, + int flags) +{ + sfnode_t *node; + vnode_t *vp; + int error; + + /* + * Return error when removing . and .. + */ + if (strcmp(nm, ".") == 0 || strcmp(nm, "") == 0) + return (EINVAL); + if (strcmp(nm, "..") == 0) + return (EEXIST); + + error = sffs_lookup(dvp, nm, &vp, NULL, 0, NULL, cred, ct, NULL, NULL); + if (error) + return (error); + if (vp->v_type != VDIR) { + VN_RELE(vp); + return (ENOTDIR); + } + if (vn_vfswlock(vp) || vn_mountedvfs(vp)) { + VN_RELE(vp); + return (EBUSY); + } + + node = VN2SFN(vp); + + mutex_enter(&sffs_lock); + error = sfnode_access(VN2SFN(dvp), VEXEC | VWRITE, cred); + if (error) + goto done; + + /* + * If anything else is using this vnode, then fail the remove. + * Why? Windows hosts can't remove something that is open, + * so we have to sfprov_close() it first. + * There is no errno for this - since it's not a problem on UNIX, + * but EINVAL is the closest. + */ + if (node->sf_file != NULL) { + if (vp->v_count > 1) { + error = EINVAL; + goto done; + } + (void)sfprov_close(node->sf_file); + node->sf_file = NULL; + } + + /* + * Remove the directory on the host and mark the node as stale. + */ + error = sfprov_rmdir(node->sf_sffs->sf_handle, node->sf_path); + if (error == ENOENT || error == 0) + sfnode_make_stale(node); +done: + mutex_exit(&sffs_lock); + VN_RELE(vp); + return (error); +} + + +/*ARGSUSED*/ +static int +sffs_remove( + vnode_t *dvp, + char *name, + cred_t *cred, + caller_context_t *ct, + int flags) +{ + vnode_t *vp; + sfnode_t *node; + int error; + + /* + * These should never happen + */ + ASSERT(name != NULL); + ASSERT(strcmp(name, "..") != 0); + + error = sffs_lookup(dvp, name, &vp, + NULL, 0, NULL, cred, ct, NULL, NULL); + if (error) + return (error); + node = VN2SFN(vp); + + mutex_enter(&sffs_lock); + error = sfnode_access(VN2SFN(dvp), VEXEC | VWRITE, cred); + if (error) + goto done; + + /* + * If anything else is using this vnode, then fail the remove. + * Why? Windows hosts can't sfprov_remove() a file that is open, + * so we have to sfprov_close() it first. + * There is no errno for this - since it's not a problem on UNIX, + * but ETXTBSY is the closest. + */ + if (node->sf_file != NULL) { + if (vp->v_count > 1) { + error = ETXTBSY; + goto done; + } + (void)sfprov_close(node->sf_file); + node->sf_file = NULL; + } + + /* + * Remove the file on the host and mark the node as stale. + */ + error = sfprov_remove(node->sf_sffs->sf_handle, node->sf_path); + if (error == ENOENT || error == 0) + sfnode_make_stale(node); +done: + mutex_exit(&sffs_lock); + VN_RELE(vp); + return (error); +} + +/*ARGSUSED*/ +static int +sffs_rename( + vnode_t *old_dir, + char *old_nm, + vnode_t *new_dir, + char *new_nm, + cred_t *cred, + caller_context_t *ct, + int flags) +{ + char *newpath; + int error; + sfnode_t *node; + + if (strcmp(new_nm, "") == 0 || + strcmp(new_nm, ".") == 0 || + strcmp(new_nm, "..") == 0 || + strcmp(old_nm, "") == 0 || + strcmp(old_nm, ".") == 0 || + strcmp(old_nm, "..") == 0) + return (EINVAL); + + /* + * make sure we have permission to do the rename + */ + mutex_enter(&sffs_lock); + error = sfnode_access(VN2SFN(old_dir), VEXEC | VWRITE, cred); + if (error == 0 && new_dir != old_dir) + error = sfnode_access(VN2SFN(new_dir), VEXEC | VWRITE, cred); + if (error) + goto done; + + node = sfnode_lookup(VN2SFN(old_dir), old_nm, VNON); + if (node == NULL) { + error = ENOENT; + goto done; + } + + + /* + * Rename the file on the host and in our caches. + */ + newpath = sfnode_construct_path(VN2SFN(new_dir), new_nm); + error = sfprov_rename(node->sf_sffs->sf_handle, node->sf_path, newpath, + node->sf_type == VDIR); + if (error == 0) + sfnode_rename(node, VN2SFN(new_dir), newpath); + else { + kmem_free(newpath, strlen(newpath) + 1); + if (error == ENOENT) + sfnode_make_stale(node); + } +done: + mutex_exit(&sffs_lock); + return (error); +} + + +/*ARGSUSED*/ +static int +sffs_fsync(vnode_t *vp, int flag, cred_t *cr, caller_context_t *ct) +{ +#if 0 + sfnode_t *node; + + /* + * Ask the host to sync any data it may have cached for open files. + * I don't think we care about errors. + */ + mutex_enter(&sffs_lock); + node = VN2SFN(vp); + if (node->sf_file != NULL) + (void) sfprov_fsync(node->sf_file); + mutex_exit(&sffs_lock); +#endif + return (0); +} + +/* + * This may be the last reference, possibly time to close the file and + * destroy the vnode. If the sfnode is stale, we'll destroy that too. + */ +/*ARGSUSED*/ +static void +sffs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) +{ + sfnode_t *node; + + /* + * nothing to do if this isn't the last use + */ + mutex_enter(&sffs_lock); + node = VN2SFN(vp); + mutex_enter(&vp->v_lock); + if (vp->v_count > 1) { + --vp->v_count; + mutex_exit(&vp->v_lock); + mutex_exit(&sffs_lock); + return; + } + + /* + * There should never be cached data, since we don't support mmap(). + */ + if (vn_has_cached_data(vp)) + panic("sffs_inactive() found cached data"); + + /* + * destroy the vnode + */ + node->sf_vnode = NULL; + mutex_exit(&vp->v_lock); + vn_invalid(vp); + vn_free(vp); + LogFlowFunc((" %s vnode cleared\n", node->sf_path)); + + /* + * Close the sf_file for the node. + */ + if (node->sf_file != NULL) { + (void)sfprov_close(node->sf_file); + node->sf_file = NULL; + } + + /* + * If the node is stale, we can also destroy it. + */ + if (node->sf_is_stale && node->sf_children == 0) + sfnode_destroy(node); + + mutex_exit(&sffs_lock); + return; +} + +/* + * All the work for this is really done in lookup. + */ +/*ARGSUSED*/ +static int +sffs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) +{ + return (0); +} + +/* + * All the work for this is really done in inactive. + */ +/*ARGSUSED*/ +static int +sffs_close( + vnode_t *vp, + int flag, + int count, + offset_t offset, + cred_t *cr, + caller_context_t *ct) +{ + return (0); +} + +/* ARGSUSED */ +static int +sffs_seek(vnode_t *v, offset_t o, offset_t *no, caller_context_t *ct) +{ + if (*no < 0 || *no > MAXOFFSET_T) + return (EINVAL); + return (0); +} + + + +/* + * By returning an error for this, we prevent anything in sffs from + * being re-exported by NFS + */ +/* ARGSUSED */ +static int +sffs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct) +{ + return (ENOTSUP); +} + +/* + * vnode operations for regular files + */ +const fs_operation_def_t sffs_ops_template[] = { +#if defined(VBOX_VFS_SOLARIS_10U6) + VOPNAME_ACCESS, sffs_access, + VOPNAME_CLOSE, sffs_close, + VOPNAME_CREATE, sffs_create, + VOPNAME_FID, sffs_fid, + VOPNAME_FSYNC, sffs_fsync, + VOPNAME_GETATTR, sffs_getattr, + VOPNAME_INACTIVE, sffs_inactive, + VOPNAME_LOOKUP, sffs_lookup, + VOPNAME_MKDIR, sffs_mkdir, + VOPNAME_OPEN, sffs_open, + VOPNAME_PATHCONF, sffs_pathconf, + VOPNAME_READ, sffs_read, + VOPNAME_READDIR, sffs_readdir, + VOPNAME_REMOVE, sffs_remove, + VOPNAME_RENAME, sffs_rename, + VOPNAME_RMDIR, sffs_rmdir, + VOPNAME_SEEK, sffs_seek, + VOPNAME_WRITE, sffs_write, + NULL, NULL +#else + VOPNAME_ACCESS, { .vop_access = sffs_access }, + VOPNAME_CLOSE, { .vop_close = sffs_close }, + VOPNAME_CREATE, { .vop_create = sffs_create }, + VOPNAME_FID, { .vop_fid = sffs_fid }, + VOPNAME_FSYNC, { .vop_fsync = sffs_fsync }, + VOPNAME_GETATTR, { .vop_getattr = sffs_getattr }, + VOPNAME_INACTIVE, { .vop_inactive = sffs_inactive }, + VOPNAME_LOOKUP, { .vop_lookup = sffs_lookup }, + VOPNAME_MKDIR, { .vop_mkdir = sffs_mkdir }, + VOPNAME_OPEN, { .vop_open = sffs_open }, + VOPNAME_PATHCONF, { .vop_pathconf = sffs_pathconf }, + VOPNAME_READ, { .vop_read = sffs_read }, + VOPNAME_READDIR, { .vop_readdir = sffs_readdir }, + VOPNAME_REMOVE, { .vop_remove = sffs_remove }, + VOPNAME_RENAME, { .vop_rename = sffs_rename }, + VOPNAME_RMDIR, { .vop_rmdir = sffs_rmdir }, + VOPNAME_SEEK, { .vop_seek = sffs_seek }, + VOPNAME_WRITE, { .vop_write = sffs_write }, + NULL, NULL +#endif +}; + +/* + * Also, init and fini functions... + */ +int +sffs_vnode_init(void) +{ + int err; + + err = vn_make_ops("sffs", sffs_ops_template, &sffs_ops); + if (err) + return (err); + + avl_create(&sfnodes, sfnode_compare, sizeof (sfnode_t), + offsetof(sfnode_t, sf_linkage)); + avl_create(&stale_sfnodes, sfnode_compare, sizeof (sfnode_t), + offsetof(sfnode_t, sf_linkage)); + + sffs_buffer = kmem_alloc(PAGESIZE, KM_SLEEP); + + return (0); +} + +void +sffs_vnode_fini(void) +{ + if (sffs_ops) + vn_freevnodeops(sffs_ops); + ASSERT(avl_first(&sfnodes) == NULL); + avl_destroy(&sfnodes); + if (sffs_buffer != NULL) { + kmem_free(sffs_buffer, PAGESIZE); + sffs_buffer = NULL; + } +} + +/* + * Utility at unmount to get all nodes in that mounted filesystem removed. + */ +int +sffs_purge(struct sffs_data *sffs) +{ + sfnode_t *node; + sfnode_t *prev; + + /* + * Check that no vnodes are active. + */ + if (sffs->sf_rootnode->v_count > 1) + return (-1); + for (node = avl_first(&sfnodes); node; + node = AVL_NEXT(&sfnodes, node)) { + if (node->sf_sffs == sffs && node->sf_vnode && + node->sf_vnode != sffs->sf_rootnode) + return (-1); + } + for (node = avl_first(&stale_sfnodes); node; + node = AVL_NEXT(&stale_sfnodes, node)) { + if (node->sf_sffs == sffs && node->sf_vnode && + node->sf_vnode != sffs->sf_rootnode) + return (-1); + } + + /* + * All clear to destroy all node information. Since there are no + * vnodes, the make stale will cause deletion. + */ + VN_RELE(sffs->sf_rootnode); + mutex_enter(&sffs_lock); + for (prev = NULL;;) { + if (prev == NULL) + node = avl_first(&sfnodes); + else + node = AVL_NEXT(&sfnodes, prev); + + if (node == NULL) + break; + + if (node->sf_sffs == sffs) { + if (node->sf_vnode != NULL) + panic("vboxfs: purge hit active vnode"); + sfnode_make_stale(node); + } else { + prev = node; + } + } +done: + mutex_exit(&sffs_lock); + return (0); +} + +static void +sfnode_print(sfnode_t *node) +{ + Log(("0x%p", node)); + Log((" type=%s (%d)", + node->sf_type == VDIR ? "VDIR" : + node->sf_type == VNON ? "VNON" : + node->sf_type == VREG ? "VREG" : "other", node->sf_type)); + Log((" ino=%d", (uint_t)node->sf_ino)); + Log((" path=%s", node->sf_path)); + Log((" parent=0x%p", node->sf_parent)); + if (node->sf_children) + Log((" children=%d", node->sf_children)); + if (node->sf_vnode) + Log((" vnode=0x%p", node->sf_vnode)); + Log(("%s\n", node->sf_is_stale ? " STALE" : "")); +} + +void +sfnode_list() +{ + sfnode_t *n; + for (n = avl_first(&sfnodes); n != NULL; n = AVL_NEXT(&sfnodes, n)) + sfnode_print(n); + for (n = avl_first(&stale_sfnodes); n != NULL; + n = AVL_NEXT(&stale_sfnodes, n)) + sfnode_print(n); +} + diff --git a/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.h b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.h new file mode 100644 index 000000000..83bf98561 --- /dev/null +++ b/src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.h @@ -0,0 +1,67 @@ +/** @file + * VirtualBox File System for Solaris Guests, vnode header. + */ + +/* + * Copyright (C) 2009 Sun Microsystems, Inc. + * + * Sun Microsystems, Inc. confidential + * All rights reserved + */ + +#ifndef __VBoxFS_node_Solaris_h +#define __VBoxFS_node_Solaris_h + +#include <sys/t_lock.h> +#include <sys/avl.h> +#include <vm/seg.h> +#include <vm/seg_vn.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * sfnode is the file system dependent vnode data for vboxsf. + * sfnode's also track all files ever accessed, both open and closed. + * It duplicates some of the information in vnode, since it holds + * information for files that may have been completely closed. + * + * The sfnode_t's are stored in an AVL tree sorted by: + * sf_sffs, sf_path + */ +typedef struct sfnode { + avl_node_t sf_linkage; /* AVL tree linkage */ + struct sffs_data *sf_sffs; /* containing mounted file system */ + char *sf_path; /* full pathname to file or dir */ + uint64_t sf_ino; /* assigned unique ID number */ + vnode_t *sf_vnode; /* vnode if active */ + sfp_file_t *sf_file; /* non NULL if open */ + struct sfnode *sf_parent; /* parent sfnode of this one */ + uint16_t sf_children; /* number of children sfnodes */ + uint8_t sf_type; /* VDIR or VREG */ + uint8_t sf_is_stale; /* this is stale and should be purged */ +} sfnode_t; + +#define VN2SFN(vp) ((sfnode_t *)(vp)->v_data) + +#ifdef _KERNEL +extern int sffs_vnode_init(void); +extern void sffs_vnode_fini(void); +extern sfnode_t *sfnode_make(struct sffs_data *, char *, vtype_t, sfp_file_t *, + sfnode_t *parent); +extern vnode_t *sfnode_get_vnode(sfnode_t *); + +/* + * Purge all cached information about a shared file system at unmount + */ +extern int sffs_purge(struct sffs_data *); + +extern kmutex_t sffs_lock; +#endif /* _KERNEL */ + +#ifdef __cplusplus +} +#endif + +#endif /* __VBoxFS_node_Solaris_h */ diff --git a/src/VBox/Additions/x11/Installer/x11config-new.pl b/src/VBox/Additions/x11/Installer/x11config-new.pl index 81e8012ab..edd4e205f 100755 --- a/src/VBox/Additions/x11/Installer/x11config-new.pl +++ b/src/VBox/Additions/x11/Installer/x11config-new.pl @@ -19,16 +19,16 @@ # additional information or have any questions. # -my $use_hal = 0; +my $auto_mouse = 0; my $new_mouse = 0; my $no_bak = 0; my $old_mouse_dev = "/dev/psaux"; foreach $arg (@ARGV) { - if (lc($arg) eq "--usehal") + if (lc($arg) eq "--autoMouse") { - $use_hal = 1; + $auto_mouse = 1; } elsif (lc($arg) eq "--newmouse") { @@ -48,6 +48,7 @@ foreach $arg (@ARGV) my $CFG; my $xkbopts = ""; my $kb_driver = ""; + my $layout_kb = ""; if (open(CFG, $cfg)) { my $TMP; @@ -108,9 +109,10 @@ $xkbopts Option "Protocol" "Standard" Option "CoreKeyboard" EndSection EOF + $layout_kb = " InputDevice \"Keyboard[0]\" \"CoreKeyboard\"\n" } - if (!$use_hal && !$new_mouse) { + if (!$auto_mouse && !$new_mouse) { print TMP <<EOF; Section "InputDevice" @@ -127,8 +129,7 @@ EndSection Section "ServerLayout" Identifier "Layout[all]" - InputDevice "Keyboard[0]" "CoreKeyboard" - InputDevice "Mouse[1]" "CorePointer" +$layout_kb InputDevice "Mouse[1]" "CorePointer" Option "Clone" "off" Option "Xinerama" "off" Screen "Screen[0]" @@ -136,7 +137,7 @@ EndSection EOF } - if (!$use_hal && $new_mouse) { + if (!$auto_mouse && $new_mouse) { print TMP <<EOF; Section "InputDevice" diff --git a/src/VBox/Additions/x11/VBoxClient/clipboard.h b/src/VBox/Additions/x11/VBoxClient/clipboard.h index 7ea0390a4..275140ffc 100644 --- a/src/VBox/Additions/x11/VBoxClient/clipboard.h +++ b/src/VBox/Additions/x11/VBoxClient/clipboard.h @@ -94,13 +94,13 @@ public: */ int init(void) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); int rc = mThreadFunction.init(); if (RT_SUCCESS(rc)) rc = mThread.start(); if (RT_SUCCESS(rc)) mInit = true; - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } /** @@ -109,10 +109,10 @@ public: */ void uninit(unsigned cMillies = RT_INDEFINITE_WAIT) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (mInit) mThread.stop(cMillies, NULL); - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } VBoxGuestClipboard() : mThread(&mThreadFunction, 0, RTTHREADTYPE_MSG_PUMP, @@ -120,12 +120,12 @@ public: { mInit = false; } ~VBoxGuestClipboard() { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (mInit) try { uninit(2000); } catch (...) { } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } }; diff --git a/src/VBox/Additions/x11/VBoxClient/display.cpp b/src/VBox/Additions/x11/VBoxClient/display.cpp index 95d96f46a..3b6da5538 100644 --- a/src/VBox/Additions/x11/VBoxClient/display.cpp +++ b/src/VBox/Additions/x11/VBoxClient/display.cpp @@ -44,7 +44,7 @@ static int initDisplay() int rcSystem, rcErrno; uint32_t fMouseFeatures = 0; - LogFlowFunc(("enabling dynamic resizing\n")); + LogRelFlowFunc(("enabling dynamic resizing\n")); rcSystem = system("VBoxRandR --test"); if (-1 == rcSystem) { @@ -62,9 +62,9 @@ static int initDisplay() VbglR3CtlFilterMask(0, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST); /* Log and ignore the return value, as there is not much we can do with * it. */ - LogFlowFunc(("dynamic resizing: result %Rrc\n", rc)); + LogRelFlowFunc(("dynamic resizing: result %Rrc\n", rc)); /* Enable support for switching between hardware and software cursors */ - LogFlowFunc(("enabling relative mouse re-capturing support\n")); + LogRelFlowFunc(("enabling relative mouse re-capturing support\n")); rc = VbglR3GetMouseStatus(&fMouseFeatures, NULL, NULL); if (RT_SUCCESS(rc)) { @@ -86,21 +86,21 @@ static int initDisplay() VbglR3SetMouseStatus( fMouseFeatures | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR); } - LogFlowFunc(("mouse re-capturing support: result %Rrc\n", rc)); + LogRelFlowFunc(("mouse re-capturing support: result %Rrc\n", rc)); return VINF_SUCCESS; } void cleanupDisplay(void) { uint32_t fMouseFeatures = 0; - LogFlowFunc(("\n")); + LogRelFlowFunc(("\n")); VbglR3CtlFilterMask(0, VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED); int rc = VbglR3GetMouseStatus(&fMouseFeatures, NULL, NULL); if (RT_SUCCESS(rc)) VbglR3SetMouseStatus( fMouseFeatures | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR); - LogFlowFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** This thread just runs a dummy X11 event loop to be sure that we get @@ -123,8 +123,7 @@ static int x11ConnectionMonitor(RTTHREAD, void *) */ int runDisplay() { - LogFlowFunc(("\n")); - uint32_t cx0 = 0, cy0 = 0, cBits0 = 0, iDisplay0 = 0; + LogRelFlowFunc(("\n")); Display *pDisplay = XOpenDisplay(NULL); if (pDisplay == NULL) return VERR_NOT_FOUND; @@ -134,7 +133,6 @@ int runDisplay() RTTHREADTYPE_INFREQUENT_POLLER, 0, "X11 monitor"); if (RT_FAILURE(rc)) return rc; - VbglR3GetDisplayChangeRequest(&cx0, &cy0, &cBits0, &iDisplay0, false); while (true) { uint32_t fEvents = 0, cx = 0, cy = 0, cBits = 0, iDisplay = 0; @@ -145,20 +143,12 @@ int runDisplay() { int rc2 = VbglR3GetDisplayChangeRequest(&cx, &cy, &cBits, &iDisplay, true); - /* Ignore the request if it is stale */ - if ((cx != cx0) || (cy != cy0) || RT_FAILURE(rc2)) - { - /* If we are not stopping, sleep for a bit to avoid using up - too much CPU while retrying. */ - if (RT_FAILURE(rc2)) - RTThreadYield(); - else - { - system("VBoxRandR"); - cx0 = cx; - cy0 = cy; - } - } + /* If we are not stopping, sleep for a bit to avoid using up + too much CPU while retrying. */ + if (RT_FAILURE(rc2)) + RTThreadYield(); + else + system("VBoxRandR"); } if ( RT_SUCCESS(rc) && (fEvents & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED)) @@ -175,7 +165,7 @@ int runDisplay() XFlush(pDisplay); } } - LogFlowFunc(("returning VINF_SUCCESS\n")); + LogRelFlowFunc(("returning VINF_SUCCESS\n")); return VINF_SUCCESS; } diff --git a/src/VBox/Additions/x11/VBoxClient/hostversion.cpp b/src/VBox/Additions/x11/VBoxClient/hostversion.cpp index 05db468fc..e4e7d9959 100644 --- a/src/VBox/Additions/x11/VBoxClient/hostversion.cpp +++ b/src/VBox/Additions/x11/VBoxClient/hostversion.cpp @@ -51,7 +51,7 @@ public: conn = dbus_bus_get (DBUS_BUS_SESSON, NULL); if (conn == NULL) { - LogFlow(("Could not retrieve D-BUS session bus!\n")); + LogRelFlow(("Could not retrieve D-BUS session bus!\n")); rc = VERR_INVALID_HANDLE; } else @@ -62,7 +62,7 @@ public: "Notify"); if (msg == NULL) { - Log(("Could not create D-BUS message!\n")); + LogRel(("Could not create D-BUS message!\n")); rc = VERR_INVALID_HANDLE; } else @@ -108,7 +108,7 @@ public: 30 * 1000 /* 30 seconds timeout */, &err); if (dbus_error_is_set(&err)) { - Log(("D-BUS returned an error while sending the notification: %s", err.message)); + LogRel(("D-BUS returned an error while sending the notification: %s", err.message)); } else if (reply) { @@ -132,7 +132,7 @@ public: virtual int run(bool fDaemonised /* = false */) { int rc; - LogFlowFunc(("\n")); + LogRelFlowFunc(("\n")); /* Because we need desktop notifications to be displayed, wait * some time to make the desktop environment load (as a work around). */ @@ -153,7 +153,7 @@ public: { rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID); if (RT_FAILURE(rc)) - Log(("Cannot connect to guest property service! rc = %Rrc\n", rc)); + LogRel(("Cannot connect to guest property service! rc = %Rrc\n", rc)); } if (RT_SUCCESS(rc)) @@ -178,7 +178,7 @@ public: rc = showNotify(szTitle, szMsg); LogRel(("VBoxClient: VirtualBox Guest Additions update available!")); if (RT_FAILURE(rc)) - Log(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc)); + LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc)); } /* Store host version to not notify again */ @@ -190,7 +190,7 @@ public: VbglR3GuestPropDisconnect(uGuestPropSvcClientID); } # endif /* VBOX_WITH_GUEST_PROPS */ - LogFlowFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } diff --git a/src/VBox/Additions/x11/VBoxClient/main.cpp b/src/VBox/Additions/x11/VBoxClient/main.cpp index 21c516880..ea87e12a6 100644 --- a/src/VBox/Additions/x11/VBoxClient/main.cpp +++ b/src/VBox/Additions/x11/VBoxClient/main.cpp @@ -40,7 +40,7 @@ #include "VBoxClient.h" -#define TRACE RTPrintf("%s: %d\n", __PRETTY_FUNCTION__, __LINE__); Log(("%s: %d\n", __PRETTY_FUNCTION__, __LINE__)) +#define TRACE RTPrintf("%s: %d\n", __PRETTY_FUNCTION__, __LINE__); LogRel(("%s: %d\n", __PRETTY_FUNCTION__, __LINE__)) static int (*gpfnOldIOErrorHandler)(Display *) = NULL; @@ -74,7 +74,7 @@ void VBoxClient::CleanUp() */ void vboxClientSignalHandler(int cSignal) { - Log(("VBoxClient: terminated with signal %d\n", cSignal)); + LogRel(("VBoxClient: terminated with signal %d\n", cSignal)); /** Disable seamless mode */ RTPrintf(("VBoxClient: terminating...\n")); VBoxClient::CleanUp(); @@ -98,7 +98,7 @@ int vboxClientXLibErrorHandler(Display *pDisplay, XErrorEvent *pError) */ static int vboxClientXLibIOErrorHandler(Display *pDisplay) { - Log(("VBoxClient: a fatal guest X Window error occurred. This may just mean that the Window system was shut down while the client was still running.\n")); + LogRel(("VBoxClient: a fatal guest X Window error occurred. This may just mean that the Window system was shut down while the client was still running.\n")); VBoxClient::CleanUp(); return 0; /* We should never reach this. */ } @@ -111,7 +111,7 @@ void vboxClientSetSignalHandlers(void) { struct sigaction sigAction; - LogFlowFunc(("\n")); + LogRelFlowFunc(("\n")); sigAction.sa_handler = vboxClientSignalHandler; sigemptyset(&sigAction.sa_mask); sigAction.sa_flags = 0; @@ -124,7 +124,7 @@ void vboxClientSetSignalHandlers(void) sigaction(SIGTERM, &sigAction, NULL); sigaction(SIGUSR1, &sigAction, NULL); sigaction(SIGUSR2, &sigAction, NULL); - LogFlowFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** @@ -222,7 +222,7 @@ int main(int argc, char *argv[]) if (RT_FAILURE(rc)) { RTPrintf("VBoxClient: failed to daemonize. Exiting.\n"); - Log(("VBoxClient: failed to daemonize. Exiting.\n")); + LogRel(("VBoxClient: failed to daemonize. Exiting.\n")); # ifdef DEBUG RTPrintf("Error %Rrc\n", rc); # endif @@ -233,27 +233,27 @@ int main(int argc, char *argv[]) if (pszHome == NULL) { RTPrintf("VBoxClient: failed to get home directory. Exiting.\n"); - Log(("VBoxClient: failed to get home directory. Exiting.\n")); + LogRel(("VBoxClient: failed to get home directory. Exiting.\n")); return 1; } if (RTStrAPrintf(&g_pszPidFile, "%s/%s", pszHome, g_pService->getPidFilePath()) == -1) if (pszHome == NULL) { RTPrintf("VBoxClient: out of memory. Exiting.\n"); - Log(("VBoxClient: out of memory. Exiting.\n")); + LogRel(("VBoxClient: out of memory. Exiting.\n")); return 1; } /* Initialise the guest library. */ if (RT_FAILURE(VbglR3InitUser())) { RTPrintf("Failed to connect to the VirtualBox kernel service\n"); - Log(("Failed to connect to the VirtualBox kernel service\n")); + LogRel(("Failed to connect to the VirtualBox kernel service\n")); return 1; } if (g_pszPidFile && RT_FAILURE(VbglR3PidFile(g_pszPidFile, &g_hPidFile))) { RTPrintf("Failed to create a pidfile. Exiting.\n"); - Log(("Failed to create a pidfile. Exiting.\n")); + LogRel(("Failed to create a pidfile. Exiting.\n")); VbglR3Term(); return 1; } diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp b/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp index b13b0a1d0..a9f8457f2 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp +++ b/src/VBox/Additions/x11/VBoxClient/seamless-host.cpp @@ -37,7 +37,7 @@ int VBoxGuestSeamlessHost::start(void) { int rc = VERR_NOT_SUPPORTED; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (mRunning) /* Assertion */ { LogRel(("VBoxClient: seamless service started twice!\n")); @@ -51,7 +51,7 @@ int VBoxGuestSeamlessHost::start(void) rc = VbglR3SeamlessSetCap(true); if (RT_SUCCESS(rc)) { - Log(("VBoxClient: enabled seamless capability on host.\n")); + LogRel(("VBoxClient: enabled seamless capability on host.\n")); rc = mThread.start(); if (RT_SUCCESS(rc)) { @@ -65,16 +65,16 @@ int VBoxGuestSeamlessHost::start(void) } if (RT_FAILURE(rc)) { - Log(("VBoxClient (seamless): failed to enable seamless capability on host, rc=%Rrc\n", rc)); + LogRel(("VBoxClient (seamless): failed to enable seamless capability on host, rc=%Rrc\n", rc)); } - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } /** Stops the service. */ void VBoxGuestSeamlessHost::stop(unsigned cMillies /* = RT_INDEFINITE_WAIT */) { - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); if (!mRunning) /* Assertion */ { LogRel(("VBoxClient: tried to stop seamless service which is not running!\n")); @@ -84,7 +84,7 @@ void VBoxGuestSeamlessHost::stop(unsigned cMillies /* = RT_INDEFINITE_WAIT */) VbglR3CtlFilterMask(0, VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST); VbglR3SeamlessSetCap(false); mRunning = false; - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** @@ -96,7 +96,7 @@ int VBoxGuestSeamlessHost::nextEvent(void) { VMMDevSeamlessMode newMode = VMMDev_Seamless_Disabled; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); int rc = VbglR3SeamlessWaitEvent(&newMode); if (RT_SUCCESS(rc)) { @@ -128,9 +128,9 @@ int VBoxGuestSeamlessHost::nextEvent(void) } else { - LogFunc(("VbglR3SeamlessWaitEvent returned %Rrc (VBoxClient)\n", rc)); + LogRelFunc(("VbglR3SeamlessWaitEvent returned %Rrc (VBoxClient)\n", rc)); } - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } @@ -139,14 +139,14 @@ int VBoxGuestSeamlessHost::nextEvent(void) */ void VBoxGuestSeamlessHost::updateRects(std::auto_ptr<std::vector<RTRECT> > pRects) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (0 == pRects.get()) /* Assertion */ { LogRelThisFunc(("ERROR: called with null pointer!\n")); return; } VbglR3SeamlessSendRects(pRects.get()->size(), pRects.get()->empty() ? NULL : &pRects.get()->front()); - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** @@ -157,7 +157,7 @@ void VBoxGuestSeamlessHost::updateRects(std::auto_ptr<std::vector<RTRECT> > pRec */ int VBoxGuestSeamlessHostThread::threadFunction(VBoxGuestThread *pThread) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (0 != mHost) { mThread = pThread; @@ -171,7 +171,7 @@ int VBoxGuestSeamlessHostThread::threadFunction(VBoxGuestThread *pThread) } } } - LogFlowThisFunc(("returning VINF_SUCCESS\n")); + LogRelFlowFunc(("returning VINF_SUCCESS\n")); return VINF_SUCCESS; } @@ -180,7 +180,7 @@ int VBoxGuestSeamlessHostThread::threadFunction(VBoxGuestThread *pThread) */ void VBoxGuestSeamlessHostThread::stop(void) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (0 != mHost) { /** @@ -195,5 +195,5 @@ void VBoxGuestSeamlessHostThread::stop(void) mThread->yield(); } } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-host.h b/src/VBox/Additions/x11/VBoxClient/seamless-host.h index 73c287283..a8134901c 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless-host.h +++ b/src/VBox/Additions/x11/VBoxClient/seamless-host.h @@ -125,14 +125,14 @@ public: */ int init(VBoxGuestSeamlessObserver *pObserver) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (mObserver != 0) /* Assertion */ { LogRel(("VBoxClient: ERROR: attempt to initialise seamless host object twice!\n")); return VERR_INTERNAL_ERROR; } mObserver = pObserver; - LogFlowThisFunc(("returning VINF_SUCCESS\n")); + LogRelFlowFunc(("returning VINF_SUCCESS\n")); return VINF_SUCCESS; } @@ -167,7 +167,7 @@ public: ~VBoxGuestSeamlessHost() { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (mRunning) /* Assertion */ { LogRel(("VBoxClient: seamless host object still running! Stopping...\n")); @@ -177,7 +177,7 @@ public: } catch(...) {} } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } }; diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp b/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp index f247d8019..1bd9c260e 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp +++ b/src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp @@ -45,7 +45,7 @@ static unsigned char *XXGetProperty (Display *aDpy, Window aWnd, Atom aPropType, const char *aPropName, unsigned long *nItems) { - LogFlowFunc(("\n")); + LogRelFlowFunc(("\n")); Atom propNameAtom = XInternAtom (aDpy, aPropName, True /* only_if_exists */); if (propNameAtom == None) @@ -64,7 +64,7 @@ static unsigned char *XXGetProperty (Display *aDpy, Window aWnd, Atom aPropType, if (rc != Success) return NULL; - LogFlowFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); return propVal; } @@ -77,7 +77,7 @@ int VBoxGuestSeamlessX11::init(VBoxGuestSeamlessObserver *pObserver) { int rc = VINF_SUCCESS; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (0 != mObserver) /* Assertion */ { LogRel(("VBoxClient: ERROR: attempt to initialise seamless guest object twice!\n")); @@ -89,7 +89,7 @@ int VBoxGuestSeamlessX11::init(VBoxGuestSeamlessObserver *pObserver) return VERR_ACCESS_DENIED; } mObserver = pObserver; - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } @@ -107,12 +107,12 @@ int VBoxGuestSeamlessX11::start(void) /** Dummy values for XShapeQueryExtension */ int error, event; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); mSupportsShape = XShapeQueryExtension(mDisplay, &event, &error); mEnabled = true; monitorClientList(); rebuildWindowTree(); - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } @@ -120,22 +120,22 @@ int VBoxGuestSeamlessX11::start(void) and stop requesting updates. */ void VBoxGuestSeamlessX11::stop(void) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); mEnabled = false; unmonitorClientList(); freeWindowTree(); - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } void VBoxGuestSeamlessX11::monitorClientList(void) { - LogFlowThisFunc(("called\n")); + LogRelFlowFunc(("called\n")); XSelectInput(mDisplay, DefaultRootWindow(mDisplay.get()), SubstructureNotifyMask); } void VBoxGuestSeamlessX11::unmonitorClientList(void) { - LogFlowThisFunc(("called\n")); + LogRelFlowFunc(("called\n")); XSelectInput(mDisplay, DefaultRootWindow(mDisplay.get()), 0); } @@ -145,7 +145,7 @@ void VBoxGuestSeamlessX11::unmonitorClientList(void) */ void VBoxGuestSeamlessX11::rebuildWindowTree(void) { - LogFlowThisFunc(("called\n")); + LogRelFlowFunc(("called\n")); freeWindowTree(); addClients(DefaultRootWindow(mDisplay.get())); mChanged = true; @@ -169,19 +169,19 @@ void VBoxGuestSeamlessX11::addClients(const Window hRoot) /** The number of children of the root supplied */ unsigned cChildren; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (!XQueryTree(mDisplay.get(), hRoot, &hRealRoot, &hParent, &phChildrenRaw, &cChildren)) return; phChildren = phChildrenRaw; for (unsigned i = 0; i < cChildren; ++i) addClientWindow(phChildren.get()[i]); - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } void VBoxGuestSeamlessX11::addClientWindow(const Window hWin) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); XWindowAttributes winAttrib; bool fAddWin = true; char *pszWinName = NULL; @@ -201,7 +201,7 @@ void VBoxGuestSeamlessX11::addClientWindow(const Window hWin) if (fAddWin && (!XGetWMNormalHints(mDisplay, hClient, &dummyHints, &dummyLong))) { - LogFlowFunc(("window %lu, client window %lu has no size hints\n", + LogRelFlowFunc(("window %lu, client window %lu has no size hints\n", hWin, hClient)); fAddWin = false; } @@ -211,7 +211,7 @@ void VBoxGuestSeamlessX11::addClientWindow(const Window hWin) int cRects = 0, iOrdering; bool hasShape = false; - LogFlowFunc(("adding window %lu, client window %lu\n", hWin, + LogRelFlowFunc(("adding window %lu, client window %lu\n", hWin, hClient)); if (mSupportsShape) { @@ -233,7 +233,7 @@ void VBoxGuestSeamlessX11::addClientWindow(const Window hWin) mGuestWindows.addWindow(hWin, hasShape, winAttrib.x, winAttrib.y, winAttrib.width, winAttrib.height, cRects, rects); } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } @@ -249,7 +249,7 @@ bool VBoxGuestSeamlessX11::isVirtualRoot(Window hWin) unsigned long ulCount; bool rc = false; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); windowTypeRaw = XXGetProperty(mDisplay, hWin, XA_ATOM, WM_TYPE_PROP, &ulCount); if (windowTypeRaw != NULL) { @@ -258,7 +258,7 @@ bool VBoxGuestSeamlessX11::isVirtualRoot(Window hWin) && (*windowType == XInternAtom(mDisplay, WM_TYPE_DESKTOP_PROP, True))) rc = true; } - LogFlowThisFunc(("returning %s\n", rc ? "true" : "false")); + LogRelFlowFunc(("returning %s\n", rc ? "true" : "false")); return rc; } @@ -269,13 +269,13 @@ bool VBoxGuestSeamlessX11::isVirtualRoot(Window hWin) void VBoxGuestSeamlessX11::freeWindowTree(void) { /* We use post-increment in the operation to prevent the iterator from being invalidated. */ - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); for (VBoxGuestWindowList::iterator it = mGuestWindows.begin(); it != mGuestWindows.end(); mGuestWindows.removeWindow(it++)) { XShapeSelectInput(mDisplay, it->first, 0); } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } @@ -288,7 +288,7 @@ void VBoxGuestSeamlessX11::nextEvent(void) { XEvent event; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); /* Start by sending information about the current window setup to the host. We do this here because we want to send all such information from a single thread. */ if (mChanged) @@ -313,7 +313,7 @@ void VBoxGuestSeamlessX11::nextEvent(void) default: break; } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** @@ -323,7 +323,7 @@ void VBoxGuestSeamlessX11::nextEvent(void) */ void VBoxGuestSeamlessX11::doConfigureEvent(Window hWin) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); VBoxGuestWindowList::iterator iter; iter = mGuestWindows.find(hWin); @@ -351,7 +351,7 @@ void VBoxGuestSeamlessX11::doConfigureEvent(Window hWin) } mChanged = true; } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** @@ -361,7 +361,7 @@ void VBoxGuestSeamlessX11::doConfigureEvent(Window hWin) */ void VBoxGuestSeamlessX11::doMapEvent(Window hWin) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); VBoxGuestWindowList::iterator iter; iter = mGuestWindows.find(hWin); @@ -370,7 +370,7 @@ void VBoxGuestSeamlessX11::doMapEvent(Window hWin) addClientWindow(hWin); mChanged = true; } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } @@ -381,7 +381,7 @@ void VBoxGuestSeamlessX11::doMapEvent(Window hWin) */ void VBoxGuestSeamlessX11::doShapeEvent(Window hWin) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); VBoxGuestWindowList::iterator iter; iter = mGuestWindows.find(hWin); @@ -399,7 +399,7 @@ void VBoxGuestSeamlessX11::doShapeEvent(Window hWin) iter->second->mapRects = rects; mChanged = true; } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** @@ -409,7 +409,7 @@ void VBoxGuestSeamlessX11::doShapeEvent(Window hWin) */ void VBoxGuestSeamlessX11::doUnmapEvent(Window hWin) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); VBoxGuestWindowList::iterator iter; iter = mGuestWindows.find(hWin); @@ -418,7 +418,7 @@ void VBoxGuestSeamlessX11::doUnmapEvent(Window hWin) mGuestWindows.removeWindow(iter); mChanged = true; } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** @@ -426,7 +426,7 @@ void VBoxGuestSeamlessX11::doUnmapEvent(Window hWin) */ std::auto_ptr<std::vector<RTRECT> > VBoxGuestSeamlessX11::getRects(void) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); unsigned cRects = 0; std::auto_ptr<std::vector<RTRECT> > apRects(new std::vector<RTRECT>); @@ -470,7 +470,7 @@ std::auto_ptr<std::vector<RTRECT> > VBoxGuestSeamlessX11::getRects(void) } } mcRects = cRects; - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); return apRects; } @@ -483,7 +483,7 @@ bool VBoxGuestSeamlessX11::interruptEvent(void) { bool rc = false; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); /* Message contents set to zero. */ XClientMessageEvent clientMessage = { ClientMessage, 0, 0, 0, 0, 0, 8 }; @@ -493,6 +493,6 @@ bool VBoxGuestSeamlessX11::interruptEvent(void) XFlush(mDisplay); rc = true; } - LogFlowThisFunc(("returning %s\n", rc ? "true" : "false")); + LogRelFlowFunc(("returning %s\n", rc ? "true" : "false")); return rc; } diff --git a/src/VBox/Additions/x11/VBoxClient/seamless-x11.h b/src/VBox/Additions/x11/VBoxClient/seamless-x11.h index 399adba4a..d5f4ced60 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless-x11.h +++ b/src/VBox/Additions/x11/VBoxClient/seamless-x11.h @@ -145,9 +145,9 @@ public: VBoxGuestX11Display(void) { mDisplay = NULL; } bool init(char *name = NULL) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); mDisplay = XOpenDisplay(name); - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); return (mDisplay != NULL); } operator Display *() { return mDisplay; } @@ -155,10 +155,10 @@ public: bool isValid(void) { return (mDisplay != NULL); } int close(void) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); int rc = XCloseDisplay(mDisplay); mDisplay = NULL; - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); return rc; } ~VBoxGuestX11Display() @@ -243,23 +243,23 @@ public: void addWindow(Window hWin, bool isMapped, int x, int y, int w, int h, int cRects, VBoxGuestX11Pointer<XRectangle> rects) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); VBoxGuestWinInfo *pInfo = new VBoxGuestWinInfo(isMapped, x, y, w, h, cRects, rects); mWindows.insert(std::pair<Window, VBoxGuestWinInfo *>(hWin, pInfo)); - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } void removeWindow(iterator it) { - LogFlowThisFunc(("called\n")); + LogRelFlowFunc(("called\n")); delete it->second; mWindows.erase(it); } void removeWindow(Window hWin) { - LogFlowThisFunc(("called\n")); + LogRelFlowFunc(("called\n")); removeWindow(find(hWin)); } }; diff --git a/src/VBox/Additions/x11/VBoxClient/seamless.h b/src/VBox/Additions/x11/VBoxClient/seamless.h index a665543b2..efce9793f 100644 --- a/src/VBox/Additions/x11/VBoxClient/seamless.h +++ b/src/VBox/Additions/x11/VBoxClient/seamless.h @@ -58,7 +58,7 @@ public: { int rc = VINF_SUCCESS; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); rc = mGuest->start(); if (RT_SUCCESS(rc)) { @@ -68,7 +68,7 @@ public: } mGuest->stop(); } - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } /** @@ -147,7 +147,7 @@ public: { int rc = VINF_SUCCESS; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (isInitialised) /* Assertion */ { LogRelFunc(("error: called a second time! (VBoxClient)\n")); @@ -171,15 +171,15 @@ public: } if (RT_FAILURE(rc)) { - LogFunc(("returning %Rrc (VBoxClient)\n", rc)); + LogRelFunc(("returning %Rrc (VBoxClient)\n", rc)); } - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } void uninit(unsigned cMillies = RT_INDEFINITE_WAIT) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (isInitialised) { mHost.stop(cMillies); @@ -187,7 +187,7 @@ public: mGuest.uninit(); isInitialised = false; } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } VBoxGuestSeamless() : mGuestFunction(&mGuest, &mGuestObs), diff --git a/src/VBox/Additions/x11/VBoxClient/thread.cpp b/src/VBox/Additions/x11/VBoxClient/thread.cpp index c29eaf715..b7aeb037a 100644 --- a/src/VBox/Additions/x11/VBoxClient/thread.cpp +++ b/src/VBox/Additions/x11/VBoxClient/thread.cpp @@ -29,7 +29,7 @@ int VBoxGuestThread::stop(unsigned cMillies, int *prc) { int rc = VINF_SUCCESS; - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (NIL_RTTHREAD == mSelf) /* Assertion */ { LogRelThisFunc(("Attempted to stop thread %s which is not running!\n", mName)); @@ -49,14 +49,14 @@ int VBoxGuestThread::stop(unsigned cMillies, int *prc) LogRelThisFunc(("Failed to stop thread %s!\n", mName)); } } - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } /** Destroy the class, stopping the thread if necessary. */ VBoxGuestThread::~VBoxGuestThread(void) { - LogFlowThisFunc(("\n")); + LogRelFlowFunc(("\n")); if (NIL_RTTHREAD != mSelf) { LogRelThisFunc(("Warning! Stopping thread %s, as it is still running!\n", mName)); @@ -66,7 +66,7 @@ VBoxGuestThread::~VBoxGuestThread(void) } catch(...) {} } - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); } /** Start the thread. */ @@ -74,7 +74,7 @@ int VBoxGuestThread::start(void) { int rc = VINF_SUCCESS; - LogFlowThisFunc(("returning\n")); + LogRelFlowFunc(("returning\n")); if (NIL_RTTHREAD != mSelf) /* Assertion */ { LogRelThisFunc(("Attempted to start thead %s twice!\n", mName)); @@ -83,7 +83,7 @@ int VBoxGuestThread::start(void) mExit = false; rc = RTThreadCreate(&mSelf, threadFunction, reinterpret_cast<void *>(this), mStack, mType, mFlags, mName); - LogFlowThisFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } @@ -98,7 +98,7 @@ int VBoxGuestThread::threadFunction(RTTHREAD self, void *pvUser) { int rc = VINF_SUCCESS; - LogFlowFunc(("\n")); + LogRelFlowFunc(("\n")); PSELF pSelf = reinterpret_cast<PSELF>(pvUser); pSelf->mRunning = true; try @@ -116,6 +116,6 @@ int VBoxGuestThread::threadFunction(RTTHREAD self, void *pvUser) rc = VERR_UNRESOLVED_ERROR; } pSelf->mRunning = false; - LogFlowFunc(("returning %Rrc\n", rc)); + LogRelFlowFunc(("returning %Rrc\n", rc)); return rc; } diff --git a/src/VBox/Additions/x11/vboxvideo/undefined_68 b/src/VBox/Additions/x11/vboxvideo/undefined_68 index 4fc93af03..f8ee0f396 100644 --- a/src/VBox/Additions/x11/vboxvideo/undefined_68 +++ b/src/VBox/Additions/x11/vboxvideo/undefined_68 @@ -76,3 +76,4 @@ resVgaShared xf86SetBackingStore xf86snprintf XNFstrdup +__stack_chk_fail diff --git a/src/VBox/Additions/x11/x11stubs/Makefile.kmk b/src/VBox/Additions/x11/x11stubs/Makefile.kmk index 7268ac735..b5a0aae54 100644 --- a/src/VBox/Additions/x11/x11stubs/Makefile.kmk +++ b/src/VBox/Additions/x11/x11stubs/Makefile.kmk @@ -33,5 +33,35 @@ libXcomposite_INST = $(INST_LIB) libXcomposite_SONAME = libXcomposite.so.1 libXcomposite_SOURCES = libXcomposite-1.0.0/libXcomposite.c +# +# libXdamage import library. +# +IMPORT_LIBS += libXdamage +libXdamage_TEMPLATE = VBOXR3 +libXdamage_INST = $(INST_LIB) +# This may need fixing later. +libXdamage_SONAME = libXdamage.so.1 +libXdamage_SOURCES = libXdamage-1.1.0/libXdamage.c + +# +# libXfixes import library. +# +IMPORT_LIBS += libXfixes +libXfixes_TEMPLATE = VBOXR3 +libXfixes_INST = $(INST_LIB) +# This may need fixing later. +libXfixes_SONAME = libXfixes.so.3 +libXfixes_SOURCES = libXfixes-3.1.0/libXfixes.c + +# +# libXfixes import library. +# +IMPORT_LIBS += libXext +libXext_TEMPLATE = VBOXR3 +libXext_INST = $(INST_LIB) +# This may need fixing later. +libXext_SONAME = libXext.so.6 +libXext_SOURCES = libXext-6.4.0/libXext.c + include $(KBUILD_PATH)/subfooter.kmk diff --git a/src/VBox/Additions/x11/x11stubs/libXcomposite-1.0.0/libXcomposite.c b/src/VBox/Additions/x11/x11stubs/libXcomposite-1.0.0/libXcomposite.c index c77643819..c3166584d 100644 --- a/src/VBox/Additions/x11/x11stubs/libXcomposite-1.0.0/libXcomposite.c +++ b/src/VBox/Additions/x11/x11stubs/libXcomposite-1.0.0/libXcomposite.c @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: libXcomposite.c $ */ /** @file * X.Org libXcomposite.so linker stub diff --git a/src/VBox/Additions/x11/x11stubs/libXdamage-1.1.0/libXdamage.c b/src/VBox/Additions/x11/x11stubs/libXdamage-1.1.0/libXdamage.c new file mode 100644 index 000000000..8213fb6e1 --- /dev/null +++ b/src/VBox/Additions/x11/x11stubs/libXdamage-1.1.0/libXdamage.c @@ -0,0 +1,37 @@ +/* $Id: libXdamage.c $ */ + +/** @file + * X.Org libXdamage.so linker stub + */ + +/* + * Copyright (C) 2010 Sun Microsystems, Inc. + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa + * Clara, CA 95054 USA or visit http://www.sun.com if you need + * additional information or have any questions. + */ + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +#define DECLXSTUB(func) \ + DECLEXPORT(void) func(void); \ + void func(void) {} + +DECLXSTUB(XDamageCreate) +DECLXSTUB(XDamageFindDisplay) +DECLXSTUB(XDamageQueryExtension) +DECLXSTUB(XDamageSubtract) +DECLXSTUB(XDamageAdd) +DECLXSTUB(XDamageDestroy) +DECLXSTUB(XDamageExtensionInfo) +DECLXSTUB(XDamageQueryVersion) diff --git a/src/VBox/Additions/x11/x11stubs/libXext-6.4.0/libXext.c b/src/VBox/Additions/x11/x11stubs/libXext-6.4.0/libXext.c new file mode 100644 index 000000000..1b9cd12dc --- /dev/null +++ b/src/VBox/Additions/x11/x11stubs/libXext-6.4.0/libXext.c @@ -0,0 +1,156 @@ +/* $Id: libXext.c $ */ + +/** @file + * X.Org libXext.so linker stub + */ + +/* + * Copyright (C) 2010 Sun Microsystems, Inc. + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa + * Clara, CA 95054 USA or visit http://www.sun.com if you need + * additional information or have any questions. + */ + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +#define DECLXSTUB(func) \ + DECLEXPORT(void) func(void); \ + void func(void) {} + +DECLXSTUB(XSyncAwait) +DECLXSTUB(XagCreateEmbeddedApplicationGroup) +DECLXSTUB(XeviGetVisualInfo) +DECLXSTUB(XSyncValueGreaterOrEqual) +DECLXSTUB(XSyncIntToValue) +DECLXSTUB(DPMSDisable) +DECLXSTUB(XSyncValueSubtract) +DECLXSTUB(DPMSEnable) +DECLXSTUB(XShmQueryExtension) +DECLXSTUB(DPMSGetVersion) +DECLXSTUB(XTestFakeInput) +DECLXSTUB(XdbeAllocateBackBufferName) +DECLXSTUB(DPMSInfo) +DECLXSTUB(XTestGetInput) +DECLXSTUB(XmbufGetWindowAttributes) +DECLXSTUB(XMITMiscGetBugMode) +DECLXSTUB(XTestReset) +DECLXSTUB(XSyncChangeAlarm) +DECLXSTUB(XdbeDeallocateBackBufferName) +DECLXSTUB(XSyncValueIsNegative) +DECLXSTUB(XTestQueryInputSize) +DECLXSTUB(XLbxQueryExtension) +DECLXSTUB(XeviQueryVersion) +DECLXSTUB(XShapeQueryExtension) +DECLXSTUB(XmbufGetScreenInfo) +DECLXSTUB(XSyncValueLow32) +DECLXSTUB(XSyncIntsToValue) +DECLXSTUB(XSyncValueAdd) +DECLXSTUB(XSecurityGenerateAuthorization) +DECLXSTUB(DPMSSetTimeouts) +DECLXSTUB(XShapeQueryVersion) +DECLXSTUB(XShmCreatePixmap) +DECLXSTUB(XmbufDisplayBuffers) +DECLXSTUB(XShapeCombineShape) +DECLXSTUB(XMITMiscSetBugMode) +DECLXSTUB(XmbufCreateBuffers) +DECLXSTUB(XagGetApplicationGroupAttributes) +DECLXSTUB(XSecurityQueryExtension) +DECLXSTUB(DPMSGetTimeouts) +DECLXSTUB(XSyncQueryCounter) +DECLXSTUB(XextAddDisplay) +DECLXSTUB(XSyncChangeCounter) +DECLXSTUB(XSyncDestroyAlarm) +DECLXSTUB(XeviQueryExtension) +DECLXSTUB(XMissingExtension) +DECLXSTUB(XmbufChangeWindowAttributes) +DECLXSTUB(XSyncQueryAlarm) +DECLXSTUB(XdbeGetVisualInfo) +DECLXSTUB(XShmGetEventBase) +DECLXSTUB(XSyncValueLessOrEqual) +DECLXSTUB(XextFindDisplay) +DECLXSTUB(XShapeQueryExtents) +DECLXSTUB(XdbeQueryExtension) +DECLXSTUB(XShapeOffsetShape) +DECLXSTUB(XdbeFreeVisualInfo) +DECLXSTUB(XShapeSelectInput) +DECLXSTUB(XGEQueryVersion) +DECLXSTUB(XagDestroyApplicationGroup) +DECLXSTUB(XShmQueryVersion) +DECLXSTUB(XSyncCreateAlarm) +DECLXSTUB(XSyncValueEqual) +DECLXSTUB(XSyncSetPriority) +DECLXSTUB(xgeExtRegister) +DECLXSTUB(DPMSQueryExtension) +DECLXSTUB(XagCreateAssociation) +DECLXSTUB(XSyncValueIsPositive) +DECLXSTUB(XagQueryApplicationGroup) +DECLXSTUB(XSetExtensionErrorHandler) +DECLXSTUB(XmbufGetBufferAttributes) +DECLXSTUB(XdbeBeginIdiom) +DECLXSTUB(XSyncMinValue) +DECLXSTUB(XagDestroyAssociation) +DECLXSTUB(XTestFlush) +DECLXSTUB(XSyncGetPriority) +DECLXSTUB(XagCreateNonembeddedApplicationGroup) +DECLXSTUB(XShmPutImage) +DECLXSTUB(XagQueryVersion) +DECLXSTUB(XSecurityAllocXauth) +DECLXSTUB(XSyncDestroyCounter) +DECLXSTUB(XShapeGetRectangles) +DECLXSTUB(XShmDetach) +DECLXSTUB(XSyncSetCounter) +DECLXSTUB(XTestPressButton) +DECLXSTUB(XSyncValueLessThan) +DECLXSTUB(XTestMovePointer) +DECLXSTUB(XSyncValueGreaterThan) +DECLXSTUB(XLbxQueryVersion) +DECLXSTUB(XShapeCombineRegion) +DECLXSTUB(XextCreateExtension) +DECLXSTUB(XShapeCombineRectangles) +DECLXSTUB(XcupStoreColors) +DECLXSTUB(XSecurityRevokeAuthorization) +DECLXSTUB(XdbeGetBackBufferAttributes) +DECLXSTUB(XmbufClearBufferArea) +DECLXSTUB(XLbxGetEventBase) +DECLXSTUB(XShmGetImage) +DECLXSTUB(XTestStopInput) +DECLXSTUB(XShmAttach) +DECLXSTUB(XdbeEndIdiom) +DECLXSTUB(XdbeSwapBuffers) +DECLXSTUB(XmbufGetVersion) +DECLXSTUB(XmbufCreateStereoWindow) +DECLXSTUB(XmbufDestroyBuffers) +DECLXSTUB(XGEQueryExtension) +DECLXSTUB(XSyncValueIsZero) +DECLXSTUB(XShapeCombineMask) +DECLXSTUB(XSyncListSystemCounters) +DECLXSTUB(XSyncCreateCounter) +DECLXSTUB(DPMSCapable) +DECLXSTUB(XcupGetReservedColormapEntries) +DECLXSTUB(XmbufChangeBufferAttributes) +DECLXSTUB(XSyncQueryExtension) +DECLXSTUB(XmbufQueryExtension) +DECLXSTUB(XShapeInputSelected) +DECLXSTUB(XMITMiscQueryExtension) +DECLXSTUB(XShmCreateImage) +DECLXSTUB(XSecurityFreeXauth) +DECLXSTUB(DPMSForceLevel) +DECLXSTUB(XSyncValueHigh32) +DECLXSTUB(XTestPressKey) +DECLXSTUB(XSyncInitialize) +DECLXSTUB(XShmPixmapFormat) +DECLXSTUB(XextRemoveDisplay) +DECLXSTUB(XSyncMaxValue) +DECLXSTUB(XSyncFreeSystemCounterList) +DECLXSTUB(XcupQueryVersion) +DECLXSTUB(XextDestroyExtension) diff --git a/src/VBox/Additions/x11/x11stubs/libXfixes-3.1.0/libXfixes.c b/src/VBox/Additions/x11/x11stubs/libXfixes-3.1.0/libXfixes.c new file mode 100644 index 000000000..f7dbe2f2b --- /dev/null +++ b/src/VBox/Additions/x11/x11stubs/libXfixes-3.1.0/libXfixes.c @@ -0,0 +1,65 @@ +/* $Id: libXfixes.c $ */ + +/** @file + * X.Org libXfixes.so linker stub + */ + +/* + * Copyright (C) 2010 Sun Microsystems, Inc. + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa + * Clara, CA 95054 USA or visit http://www.sun.com if you need + * additional information or have any questions. + */ + +#include <iprt/cdefs.h> +#include <iprt/types.h> + +#define DECLXSTUB(func) \ + DECLEXPORT(void) func(void); \ + void func(void) {} + +DECLXSTUB(XFixesTranslateRegion) +DECLXSTUB(XFixesRegionExtents) +DECLXSTUB(XFixesFetchRegion) +DECLXSTUB(XFixesExpandRegion) +DECLXSTUB(XFixesSelectSelectionInput) +DECLXSTUB(XFixesChangeCursorByName) +DECLXSTUB(XFixesInvertRegion) +DECLXSTUB(XFixesQueryVersion) +DECLXSTUB(XFixesCreateRegionFromBitmap) +DECLXSTUB(XFixesSetRegion) +DECLXSTUB(XFixesCreateRegion) +DECLXSTUB(XFixesGetCursorImage) +DECLXSTUB(XFixesDestroyRegion) +DECLXSTUB(XFixesSetCursorName) +DECLXSTUB(XFixesIntersectRegion) +DECLXSTUB(XFixesCopyRegion) +DECLXSTUB(XFixesSelectCursorInput) +DECLXSTUB(XFixesShowCursor) +DECLXSTUB(XFixesHideCursor) +DECLXSTUB(XFixesGetCursorName) +DECLXSTUB(XFixesExtensionName) +DECLXSTUB(XFixesVersion) +DECLXSTUB(XFixesSetGCClipRegion) +DECLXSTUB(XFixesQueryExtension) +DECLXSTUB(XFixesFindDisplay) +DECLXSTUB(XFixesChangeCursor) +DECLXSTUB(XFixesSetWindowShapeRegion) +DECLXSTUB(XFixesCreateRegionFromPicture) +DECLXSTUB(XFixesSetPictureClipRegion) +DECLXSTUB(XFixesFetchRegionAndBounds) +DECLXSTUB(XFixesExtensionInfo) +DECLXSTUB(XFixesSubtractRegion) +DECLXSTUB(XFixesUnionRegion) +DECLXSTUB(XFixesCreateRegionFromGC) +DECLXSTUB(XFixesChangeSaveSet) +DECLXSTUB(XFixesCreateRegionFromWindow) |
