summaryrefslogtreecommitdiff
path: root/src/VBox/Additions
diff options
context:
space:
mode:
authorFelix Geyer <debfx-pkg@fobos.de>2010-03-26 10:38:21 +0100
committerFelix Geyer <debfx-pkg@fobos.de>2010-03-26 10:38:21 +0100
commit0429962c55c464036f613d707f26b91f252584e7 (patch)
treeb359d4c41578b576d90240489a1ba273ab46a6b7 /src/VBox/Additions
parent48be1cf480743cdc0e60dd1edc9677b4349a570d (diff)
downloadvirtualbox-0429962c55c464036f613d707f26b91f252584e7.tar.gz
Imported Upstream version 3.1.6-dfsgupstream/3.1.6-dfsg
Diffstat (limited to 'src/VBox/Additions')
-rw-r--r--src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c54
-rw-r--r--src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp20
-rw-r--r--src/VBox/Additions/common/crOpenGL/Makefile.kmk5
-rw-r--r--src/VBox/Additions/common/crOpenGL/context.c70
-rw-r--r--src/VBox/Additions/common/crOpenGL/load.c76
-rw-r--r--src/VBox/Additions/common/crOpenGL/pack/packspu_beginend.py17
-rw-r--r--src/VBox/Additions/common/crOpenGL/pack/packspu_client.c13
-rw-r--r--src/VBox/Additions/common/crOpenGL/pack/packspu_getstring.c2
-rw-r--r--src/VBox/Additions/common/crOpenGL/stub.h3
-rw-r--r--src/VBox/Additions/linux/drm/vboxvideo_drm.c6
-rwxr-xr-xsrc/VBox/Additions/linux/installer/vboxadd-service.sh2
-rwxr-xr-xsrc/VBox/Additions/linux/installer/vboxadd-x11.sh52
-rwxr-xr-xsrc/VBox/Additions/linux/installer/vboxadd.sh7
-rw-r--r--src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c710
-rw-r--r--src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.h110
-rw-r--r--src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.c486
-rw-r--r--src/VBox/Additions/solaris/SharedFolders/vboxfs_vfs.h38
-rw-r--r--src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.c1630
-rw-r--r--src/VBox/Additions/solaris/SharedFolders/vboxfs_vnode.h67
-rwxr-xr-xsrc/VBox/Additions/x11/Installer/x11config-new.pl15
-rw-r--r--src/VBox/Additions/x11/VBoxClient/clipboard.h12
-rw-r--r--src/VBox/Additions/x11/VBoxClient/display.cpp38
-rw-r--r--src/VBox/Additions/x11/VBoxClient/hostversion.cpp14
-rw-r--r--src/VBox/Additions/x11/VBoxClient/main.cpp20
-rw-r--r--src/VBox/Additions/x11/VBoxClient/seamless-host.cpp30
-rw-r--r--src/VBox/Additions/x11/VBoxClient/seamless-host.h8
-rw-r--r--src/VBox/Additions/x11/VBoxClient/seamless-x11.cpp70
-rw-r--r--src/VBox/Additions/x11/VBoxClient/seamless-x11.h16
-rw-r--r--src/VBox/Additions/x11/VBoxClient/seamless.h14
-rw-r--r--src/VBox/Additions/x11/VBoxClient/thread.cpp16
-rw-r--r--src/VBox/Additions/x11/vboxvideo/undefined_681
-rw-r--r--src/VBox/Additions/x11/x11stubs/Makefile.kmk30
-rw-r--r--src/VBox/Additions/x11/x11stubs/libXcomposite-1.0.0/libXcomposite.c2
-rw-r--r--src/VBox/Additions/x11/x11stubs/libXdamage-1.1.0/libXdamage.c37
-rw-r--r--src/VBox/Additions/x11/x11stubs/libXext-6.4.0/libXext.c156
-rw-r--r--src/VBox/Additions/x11/x11stubs/libXfixes-3.1.0/libXfixes.c65
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)