static void tstRTPipe2(void) { RTTestISub("Negative"); RTPIPE hPipeR = (RTPIPE)1; RTPIPE hPipeW = (RTPIPE)1; RTTESTI_CHECK_RC(RTPipeCreate(&hPipeR, &hPipeW, ~0), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPipeCreate(NULL, &hPipeW, 0), VERR_INVALID_POINTER); RTTESTI_CHECK_RC(RTPipeCreate(&hPipeR, NULL, 0), VERR_INVALID_POINTER); RTTESTI_CHECK(hPipeR == (RTPIPE)1); RTTESTI_CHECK(hPipeW == (RTPIPE)1); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); char abBuf[_4K]; size_t cbRead = ~(size_t)3; RTTESTI_CHECK_RC(RTPipeRead(hPipeW, abBuf, 0, &cbRead), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeRead(hPipeW, abBuf, 1, &cbRead), VERR_ACCESS_DENIED); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeW, abBuf, 0, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeW, abBuf, 1, NULL), VERR_ACCESS_DENIED); size_t cbWrite = ~(size_t)5; RTTESTI_CHECK_RC(RTPipeWrite(hPipeR, "asdf", 0, &cbWrite), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeWrite(hPipeR, "asdf", 4, &cbWrite), VERR_ACCESS_DENIED); RTTESTI_CHECK(cbWrite == ~(size_t)5); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeR, "asdf", 0, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeR, "asdf", 4, NULL), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeFlush(hPipeR), VERR_ACCESS_DENIED); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
static void tstRTPipe5(void) { RTTestISub("Inherit non-standard pipe handle, read end"); char szPathSelf[RTPATH_MAX]; RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szPathSelf, sizeof(szPathSelf)) == szPathSelf); RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); RTHCINTPTR hNative = RTPipeToNative(hPipeR); RTTESTI_CHECK_RETV(hNative != -1); char szNative[64]; RTStrPrintf(szNative, sizeof(szNative), "%RHi", hNative); const char *papszArgs[4] = { szPathSelf, "--child-5", szNative, NULL }; RTPROCESS hChild; RTTESTI_CHECK_RC_RETV(RTProcCreate(szPathSelf, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hChild), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW, g_szTest5Message, sizeof(g_szTest5Message) - 1, NULL), VINF_SUCCESS); int rc; RTTESTI_CHECK_RC(rc = RTPipeClose(hPipeW), VINF_SUCCESS); if (RT_FAILURE(rc)) RTTESTI_CHECK_RC(RTProcTerminate(hChild), VINF_SUCCESS); RTPROCSTATUS ProcStatus; RTTESTI_CHECK_RC(rc = RTProcWait(hChild, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (RT_FAILURE(rc)) return; RTTESTI_CHECK( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL && ProcStatus.iStatus == 0); }
static void tstRTCreateProcEx2(const char *pszAsUser, const char *pszPassword) { RTTestISub("Standard Err"); RTPIPE hPipeR, hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); const char * apszArgs[3] = { "non-existing-non-executable-file", "--testcase-child-2", NULL }; RTHANDLE Handle; Handle.enmType = RTHANDLETYPE_PIPE; Handle.u.hPipe = hPipeW; RTPROCESS hProc; RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, &Handle, pszAsUser, pszPassword, &hProc), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); char szOutput[_4K]; size_t offOutput = 0; for (;;) { size_t cbLeft = sizeof(szOutput) - 1 - offOutput; RTTESTI_CHECK(cbLeft > 0); if (cbLeft == 0) break; size_t cbRead; int rc = RTPipeReadBlocking(hPipeR, &szOutput[offOutput], cbLeft, &cbRead); if (RT_FAILURE(rc)) { RTTESTI_CHECK_RC(rc, VERR_BROKEN_PIPE); break; } offOutput += cbRead; } szOutput[offOutput] = '\0'; RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTPROCSTATUS ProcStatus = { -1, RTPROCEXITREASON_ABEND }; RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); RTThreadSleep(10); if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0) RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus); else if ( offOutput != sizeof("howdy") - 1 || strcmp(szOutput, "howdy")) RTTestIFailed("wrong output: \"%s\" (len=%u)", szOutput, offOutput); else RTTestIPassed(NULL); }
/** * Initializes the object (called right after construction). * * @returns S_OK on success and non-fatal failures, some COM error otherwise. */ int USBProxyBackendUsbIp::init(void) { int rc = VINF_SUCCESS; m = new Data; /** @todo: Pass in some config like host and port to connect to. */ /* Setup wakeup pipe and poll set first. */ rc = RTSemFastMutexCreate(&m->hMtxDevices); if (RT_SUCCESS(rc)) { rc = RTPipeCreate(&m->hWakeupPipeR, &m->hWakeupPipeW, 0); if (RT_SUCCESS(rc)) { rc = RTPollSetCreate(&m->hPollSet); if (RT_SUCCESS(rc)) { rc = RTPollSetAddPipe(m->hPollSet, m->hWakeupPipeR, RTPOLL_EVT_READ, USBIP_POLL_ID_PIPE); if (RT_SUCCESS(rc)) { /* Connect to the USB/IP host. */ rc = reconnect(); if (RT_SUCCESS(rc)) rc = start(); /* Start service thread. */ } if (RT_FAILURE(rc)) { RTPollSetRemove(m->hPollSet, USBIP_POLL_ID_PIPE); int rc2 = RTPollSetDestroy(m->hPollSet); AssertRC(rc2); } } if (RT_FAILURE(rc)) { int rc2 = RTPipeClose(m->hWakeupPipeR); AssertRC(rc2); rc2 = RTPipeClose(m->hWakeupPipeW); AssertRC(rc2); } } if (RT_FAILURE(rc)) RTSemFastMutexDestroy(m->hMtxDevices); } return rc; }
/** * Initialization routine for the usbfs based operation. * * @returns iprt status code. */ int USBProxyBackendLinux::initUsbfs(void) { Assert(mUsingUsbfsDevices); /* * Open the devices file. */ int rc; char *pszDevices = RTPathJoinA(mDevicesRoot.c_str(), "devices"); if (pszDevices) { rc = RTFileOpen(&mhFile, pszDevices, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { rc = RTPipeCreate(&mhWakeupPipeR, &mhWakeupPipeW, 0 /*fFlags*/); if (RT_SUCCESS(rc)) { /* * Start the poller thread. */ rc = start(); if (RT_SUCCESS(rc)) { RTStrFree(pszDevices); LogFlowThisFunc(("returns successfully\n")); return VINF_SUCCESS; } RTPipeClose(mhWakeupPipeR); RTPipeClose(mhWakeupPipeW); mhWakeupPipeW = mhWakeupPipeR = NIL_RTPIPE; } else Log(("USBProxyBackendLinux::USBProxyBackendLinux: RTFilePipe failed with rc=%Rrc\n", rc)); RTFileClose(mhFile); } RTStrFree(pszDevices); } else { rc = VERR_NO_MEMORY; Log(("USBProxyBackendLinux::USBProxyBackendLinux: out of memory!\n")); } LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc)); return rc; }
static void tstRTPipe4(void) { RTTestISub("Inherit non-standard pipe handle, write end"); char szPathSelf[RTPATH_MAX]; RTTESTI_CHECK_RETV(RTProcGetExecutablePath(szPathSelf, sizeof(szPathSelf)) == szPathSelf); RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); RTHCINTPTR hNative = RTPipeToNative(hPipeW); RTTESTI_CHECK_RETV(hNative != -1); char szNative[64]; RTStrPrintf(szNative, sizeof(szNative), "%RHi", hNative); const char *papszArgs[4] = { szPathSelf, "--child-4", szNative, NULL }; RTPROCESS hChild; RTTESTI_CHECK_RC_RETV(RTProcCreate(szPathSelf, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hChild), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); char szTmp[1024]; size_t cbRead = 0; int rc; RTTESTI_CHECK_RC(rc = RTPipeReadBlocking(hPipeR, szTmp, sizeof(szTmp) - 1, &cbRead), VINF_SUCCESS); if (RT_FAILURE(rc)) cbRead = 0; RTTESTI_CHECK_RETV(cbRead < sizeof(szTmp)); szTmp[cbRead] = '\0'; size_t cbRead2; char szTmp2[4]; RTTESTI_CHECK_RC(RTPipeReadBlocking(hPipeR, szTmp2, sizeof(szTmp2), &cbRead2), VERR_BROKEN_PIPE); RTTESTI_CHECK_RC(rc = RTPipeClose(hPipeR), VINF_SUCCESS); if (RT_FAILURE(rc)) RTTESTI_CHECK_RC(RTProcTerminate(hChild), VINF_SUCCESS); RTPROCSTATUS ProcStatus; RTTESTI_CHECK_RC(rc = RTProcWait(hChild, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS); if (RT_FAILURE(rc)) return; RTTESTI_CHECK( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL && ProcStatus.iStatus == 0); if (memcmp(szTmp, g_szTest4Message, sizeof(g_szTest4Message))) RTTestIFailed("Message mismatch.\n:Expected '%s'\nGot '%s'\n", g_szTest4Message, szTmp); }
/** * Opens the device file. * * @returns VBox status code. * @param pProxyDev The device instance. * @param pszAddress If we are using usbfs, this is the path to the * device. If we are using sysfs, this is a string of * the form "sysfs:<sysfs path>//device:<device node>". * In the second case, the two paths are guaranteed * not to contain the substring "//". * @param pvBackend Backend specific pointer, unused for the linux backend. */ static DECLCALLBACK(int) usbProxyFreeBSDOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend) { PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD); int rc; LogFlow(("usbProxyFreeBSDOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress)); NOREF(pvBackend); /* * Try open the device node. */ RTFILE hFile; rc = RTFileOpen(&hFile, pszAddress, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { /* * Initialize the FreeBSD backend data. */ pDevFBSD->hFile = hFile; rc = usbProxyFreeBSDFsInit(pProxyDev); if (RT_SUCCESS(rc)) { /* * Create wakeup pipe. */ rc = RTPipeCreate(&pDevFBSD->hPipeWakeupR, &pDevFBSD->hPipeWakeupW, 0); if (RT_SUCCESS(rc)) { LogFlow(("usbProxyFreeBSDOpen(%p, %s): returns successfully hFile=%RTfile iActiveCfg=%d\n", pProxyDev, pszAddress, pDevFBSD->hFile, pProxyDev->iActiveCfg)); return VINF_SUCCESS; } } RTFileClose(hFile); } else if (rc == VERR_ACCESS_DENIED) rc = VERR_VUSB_USBFS_PERMISSION; Log(("usbProxyFreeBSDOpen(%p, %s) failed, rc=%d!\n", pProxyDev, pszAddress, rc)); return rc; }
static void tstRTPipe3(void) { RTTestISub("Full write buffer"); RTPIPE hPipeR = (RTPIPE)999999; RTPIPE hPipeW = (RTPIPE)999999; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); static char s_abBuf[_256K]; int rc = VINF_SUCCESS; size_t cbTotal = 0; memset(s_abBuf, 0xff, sizeof(s_abBuf)); for (;;) { RTTESTI_CHECK(cbTotal < _1G); if (cbTotal > _1G) break; size_t cbWritten = _1G; rc = RTPipeWrite(hPipeW, s_abBuf, sizeof(s_abBuf), &cbWritten); RTTESTI_CHECK_MSG(rc == VINF_SUCCESS || rc == VINF_TRY_AGAIN, ("rc=%Rrc\n", rc)); if (rc != VINF_SUCCESS) break; cbTotal += cbWritten; } if (rc == VINF_TRY_AGAIN) { RTTestIPrintf(RTTESTLVL_ALWAYS, "cbTotal=%zu (%#zx)\n", cbTotal, cbTotal); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 1), VERR_TIMEOUT); size_t cbRead; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, s_abBuf, RT_MIN(sizeof(s_abBuf), cbTotal) / 2, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeSelectOne(hPipeW, 1), VINF_SUCCESS); size_t cbWritten = _1G; rc = RTPipeWrite(hPipeW, s_abBuf, sizeof(s_abBuf), &cbWritten); RTTESTI_CHECK(rc == VINF_SUCCESS); } RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
static void tstRTPipe1(void) { RTTestISub("Basics"); RTPIPE hPipeR = NIL_RTPIPE; RTPIPE hPipeW = NIL_RTPIPE; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RETV(hPipeR != NIL_RTPIPE); RTTESTI_CHECK_RETV(hPipeW != NIL_RTPIPE); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(NIL_RTPIPE), VINF_SUCCESS); hPipeR = NIL_RTPIPE; hPipeW = NIL_RTPIPE; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ | RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); int rc = RTPipeFlush(hPipeW); RTTESTI_CHECK_MSG(rc == VERR_NOT_SUPPORTED || rc == VINF_SUCCESS, ("%Rrc\n", rc)); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 0), VERR_TIMEOUT); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 1), VERR_TIMEOUT); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeW, 1), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_WRITE), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, RTPIPE_C_INHERIT_READ), VINF_SUCCESS); size_t cbRead = ~(size_t)0; char abBuf[_64K + _4K]; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VINF_TRY_AGAIN); RTTESTI_CHECK_RETV(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 1, &cbRead), VINF_TRY_AGAIN); RTTESTI_CHECK_RETV(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 0); size_t cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, abBuf, 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 0); /* We can write a number of bytes without blocking (see PIPE_BUF on POSIX systems). */ cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "42", 2, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_MSG_RETV(cbWritten == 2, ("cbWritten=%zu\n", cbWritten)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "!", 1, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 3, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 3); RTTESTI_CHECK_RETV(!memcmp(abBuf, "42!", 3)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "BigQ", 4, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 4); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 1), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 4); RTTESTI_CHECK_RETV(!memcmp(abBuf, "BigQ", 4)); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "H2G2", 4, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbWritten == 4); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 1, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[1], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 2, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[2], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 3, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[3], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_RETV(cbRead == 1); RTTESTI_CHECK_RETV(!memcmp(abBuf, "H2G2", 4)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS); RTTESTI_CHECK_MSG(cbRead == cbWritten - 4, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten)); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); RTTestISub("VERR_BROKEN_PIPE"); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "", 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 0); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "4", 1, &cbWritten), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbWritten == ~(size_t)2); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)3; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); cbWritten = ~(size_t)2; RTTESTI_CHECK_RC(RTPipeWrite(hPipeW, "42", 2, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 2); RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeW), VINF_SUCCESS); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, &abBuf[1], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); RTTESTI_CHECK(!memcmp(abBuf, "42", 2)); cbRead = ~(size_t)0; RTTESTI_CHECK_RC(RTPipeRead(hPipeR, abBuf, 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); cbRead = ~(size_t)3; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == ~(size_t)3); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTestISub("Blocking"); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "42!", 3, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 3); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, abBuf, 3, NULL), VINF_SUCCESS); RTTESTI_CHECK(!memcmp(abBuf, "42!", 3)); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 0, NULL), VINF_SUCCESS); cbRead = ~(size_t)42; RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 0, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 0); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 1, NULL), VERR_BROKEN_PIPE); cbRead = ~(size_t)42; RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[0], 1, &cbRead), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbRead == 0); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42!", 3, NULL), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 3); cbRead = ~(size_t)0; RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS); RTTESTI_CHECK(cbRead == 1); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[1], 1, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeReadBlocking(hPipeR, &abBuf[2], 1, NULL), VINF_SUCCESS); RTTESTI_CHECK(!memcmp(abBuf, "42!", 3)); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "", 0, NULL), VINF_SUCCESS); cbWritten = ~(size_t)9; RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "", 0, &cbWritten), VINF_SUCCESS); RTTESTI_CHECK(cbWritten == 0); RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42", 2, NULL), VERR_BROKEN_PIPE); cbWritten = ~(size_t)9; RTTESTI_CHECK_RC_RETV(RTPipeWriteBlocking(hPipeW, "42", 2, &cbWritten), VERR_BROKEN_PIPE); RTTESTI_CHECK(cbWritten == 0); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); }
static void tstRTPoll2(void) { RTTestISub("Negative"); /* * Bad set pointer and handle values. */ RTTESTI_CHECK_RC(RTPollSetCreate(NULL), VERR_INVALID_POINTER); RTPOLLSET hSetInvl = (RTPOLLSET)(intptr_t)-3; RTTESTI_CHECK_RC(RTPollSetDestroy(hSetInvl), VERR_INVALID_HANDLE); RTHANDLE Handle; Handle.enmType = RTHANDLETYPE_PIPE; Handle.u.hPipe = NIL_RTPIPE; RTTESTI_CHECK_RC(RTPollSetAdd(hSetInvl, &Handle, RTPOLL_EVT_ERROR, 1), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollSetRemove(hSetInvl, 1), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSetInvl, 1, NULL), VERR_INVALID_HANDLE); RTTESTI_CHECK(RTPollSetGetCount(hSetInvl) == UINT32_MAX); RTTESTI_CHECK_RC(RTPoll(hSetInvl, 0, NULL, NULL), VERR_INVALID_HANDLE); RTTESTI_CHECK_RC(RTPollNoResume(hSetInvl, 0, NULL, NULL), VERR_INVALID_HANDLE); /* * Invalid arguments and other stuff. */ RTPOLLSET hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VERR_DEADLOCK); RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VERR_DEADLOCK); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, UINT32_MAX), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 1), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, NULL, RTPOLL_EVT_ERROR, 1), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_ERROR, UINT32_MAX), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, UINT32_MAX, 3), VERR_INVALID_PARAMETER); Handle.enmType = RTHANDLETYPE_INVALID; RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_ERROR, 3), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTPollSetAdd(hSet, NULL, RTPOLL_EVT_ERROR, UINT32_MAX), VERR_INVALID_PARAMETER); /* duplicate id */ RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_ERROR, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_ERROR, 0), VERR_POLL_HANDLE_ID_EXISTS); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 0), VINF_SUCCESS); RTPipeClose(hPipeR); RTPipeClose(hPipeW); /* non-pollable handle */ RTFILE hBitBucket; RTTESTI_CHECK_RC_RETV(RTFileOpenBitBucket(&hBitBucket, RTFILE_O_WRITE), VINF_SUCCESS); Handle.enmType = RTHANDLETYPE_FILE; Handle.u.hFile = hBitBucket; RTTESTI_CHECK_RC(RTPollSetAdd(hSet, &Handle, RTPOLL_EVT_WRITE, 10), VERR_POLL_HANDLE_NOT_POLLABLE); RTFileClose(hBitBucket); RTTESTI_CHECK_RC_RETV(RTPollSetDestroy(hSet), VINF_SUCCESS); }
static void tstRTPoll1(void) { RTTestISub("Basics"); /* create and destroy. */ RTPOLLSET hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetDestroy(NIL_RTPOLLSET), VINF_SUCCESS); /* empty set, adding a NIL handle. */ hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 0, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, NIL_RTPIPE, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 0), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); /* * Set with pipes */ RTPIPE hPipeR; RTPIPE hPipeW; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); hSet = NIL_RTPOLLSET; RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET); /* add the read pipe */ RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VINF_SUCCESS); RTHANDLE Handle; RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); /* poll on the set, should time out. */ RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL, NULL), VERR_TIMEOUT); /* add the write pipe with error detection only, check that poll still times out. remove it again. */ RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_ERROR, 11 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 11 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPoll(hSet, 1, NULL, NULL), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 11), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); /* add the write pipe */ RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_WRITE, 10 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 10 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); /* poll on the set again, now it should indicate hPipeW is ready. */ int rc; RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPoll(hSet, 100, NULL, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 100, NULL, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, RT_INDEFINITE_WAIT, NULL, NULL), VINF_SUCCESS); uint32_t fEvents = UINT32_MAX; uint32_t id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPoll(hSet, 250, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); } fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 100, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); } /* Write to the pipe. Currently ASSUMING we'll get the read ready now... Good idea? */ RTTESTI_CHECK_RC(rc = RTPipeWriteBlocking(hPipeW, "hello", 5, NULL), VINF_SUCCESS); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPoll(hSet, 256, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); } fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 383, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); if (RT_SUCCESS(rc)) { fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, RT_INDEFINITE_WAIT, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); } } /* Remove the read pipe, do a quick poll check. */ RTTESTI_CHECK_RC_RETV(RTPollSetRemove(hSet, 1), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); /* Add it back and check that we now get the write handle when polling. (Is this FIFOing a good idea?) */ RTTESTI_CHECK_RC_RETV(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 1 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeR); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(rc = RTPollNoResume(hSet, 555, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); /* Remove it again and break the pipe by closing the read end. */ RTTESTI_CHECK_RC_RETV(RTPollSetRemove(hSet, 1), VINF_SUCCESS); RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1); RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND); RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS); RTTESTI_CHECK(Handle.enmType == RTHANDLETYPE_PIPE); RTTESTI_CHECK(Handle.u.hPipe == hPipeW); RTTESTI_CHECK_RC(RTPoll(hSet, 0, NULL, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); fEvents = UINT32_MAX; id = UINT32_MAX; RTTESTI_CHECK_RC(RTPollNoResume(hSet, 0, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 10); RTTESTI_CHECK_MSG( fEvents == RTPOLL_EVT_ERROR \ || fEvents == (RTPOLL_EVT_ERROR | RTPOLL_EVT_WRITE), ("%#x\n", fEvents)); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); /* * Check FIFO order when removing and adding. * * Note! FIFO order is not guaranteed when a handle has more than one entry * in the set. */ RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR, &hPipeW, 0/*fFlags*/), VINF_SUCCESS); RTPIPE hPipeR2, hPipeW2; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR2, &hPipeW2, 0/*fFlags*/), VINF_SUCCESS); RTPIPE hPipeR3, hPipeW3; RTTESTI_CHECK_RC_RETV(RTPipeCreate(&hPipeR3, &hPipeW3, 0/*fFlags*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetCreate(&hSet), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_WRITE, 2 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR2, RTPOLL_EVT_READ, 3 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeW2, RTPOLL_EVT_WRITE, 4 /*id*/), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR3, RTPOLL_EVT_READ, 5 /*id*/), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 2); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW, "hello", 5, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW2, "hello", 5, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeWriteBlocking(hPipeW3, "hello", 5, NULL), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 1); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 1), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 2); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 2), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 3); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 3), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 4); RTTESTI_CHECK(fEvents == RTPOLL_EVT_WRITE); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 4), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VINF_SUCCESS); RTTESTI_CHECK(id == 5); RTTESTI_CHECK(fEvents == RTPOLL_EVT_READ); RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 5), VINF_SUCCESS); id = UINT32_MAX; fEvents = UINT32_MAX; RTTESTI_CHECK_RC(RTPoll(hSet, 5, &fEvents, &id), VERR_TIMEOUT); RTTESTI_CHECK_RC(RTPipeClose(hPipeW), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW2), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR2), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeW3), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPipeClose(hPipeR3), VINF_SUCCESS); RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS); }
/** * Construct a host parallel driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvHostParallelConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL); LogFlowFunc(("iInstance=%d\n", pDrvIns->iInstance)); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Init basic data members and interfaces. * * Must be done before returning any failure because we've got a destructor. */ pThis->hFileDevice = NIL_RTFILE; #ifndef VBOX_WITH_WIN_PARPORT_SUP pThis->hWakeupPipeR = NIL_RTPIPE; pThis->hWakeupPipeW = NIL_RTPIPE; #else pThis->hWinFileDevice = NIL_RTFILE; #endif pThis->pDrvInsR3 = pDrvIns; #ifdef VBOX_WITH_DRVINTNET_IN_R0 pThis->pDrvInsR0 = PDMDRVINS_2_R0PTR(pDrvIns); #endif /* IBase. */ pDrvIns->IBase.pfnQueryInterface = drvHostParallelQueryInterface; /* IHostParallelConnector. */ pThis->IHostParallelConnectorR3.pfnWrite = drvHostParallelWrite; pThis->IHostParallelConnectorR3.pfnRead = drvHostParallelRead; pThis->IHostParallelConnectorR3.pfnSetPortDirection = drvHostParallelSetPortDirection; pThis->IHostParallelConnectorR3.pfnWriteControl = drvHostParallelWriteControl; pThis->IHostParallelConnectorR3.pfnReadControl = drvHostParallelReadControl; pThis->IHostParallelConnectorR3.pfnReadStatus = drvHostParallelReadStatus; /* * Validate the config. */ if (!CFGMR3AreValuesValid(pCfg, "DevicePath\0")) return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, N_("Unknown host parallel configuration option, only supports DevicePath")); /* * Query configuration. */ /* Device */ int rc = CFGMR3QueryStringAlloc(pCfg, "DevicePath", &pThis->pszDevicePath); if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: query for \"DevicePath\" string returned %Rra.\n", rc)); return rc; } /* * Open the device */ rc = RTFileOpen(&pThis->hFileDevice, pThis->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Parallel#%d could not open '%s'"), pDrvIns->iInstance, pThis->pszDevicePath); #ifndef VBOX_WITH_WIN_PARPORT_SUP /* * Try to get exclusive access to parallel port */ rc = ioctl(RTFileToNative(pThis->hFileDevice), PPEXCL); if (rc < 0) return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("Parallel#%d could not get exclusive access for parallel port '%s'" "Be sure that no other process or driver accesses this port"), pDrvIns->iInstance, pThis->pszDevicePath); /* * Claim the parallel port */ rc = ioctl(RTFileToNative(pThis->hFileDevice), PPCLAIM); if (rc < 0) return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS, N_("Parallel#%d could not claim parallel port '%s'" "Be sure that no other process or driver accesses this port"), pDrvIns->iInstance, pThis->pszDevicePath); /* * Get the IHostParallelPort interface of the above driver/device. */ pThis->pDrvHostParallelPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHOSTPARALLELPORT); if (!pThis->pDrvHostParallelPort) return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Parallel#%d has no parallel port interface above"), pDrvIns->iInstance); /* * Create wakeup pipe. */ rc = RTPipeCreate(&pThis->hWakeupPipeR, &pThis->hWakeupPipeW, 0 /*fFlags*/); AssertRCReturn(rc, rc); /* * Start in SPP mode. */ pThis->enmModeCur = PDM_PARALLEL_PORT_MODE_INVALID; rc = drvHostParallelSetMode(pThis, PDM_PARALLEL_PORT_MODE_SPP); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot change mode of parallel mode to SPP"), pDrvIns->iInstance); /* * Start waiting for interrupts. */ rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostParallelMonitorThread, drvHostParallelWakeupMonitorThread, 0, RTTHREADTYPE_IO, "ParMon"); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot create monitor thread"), pDrvIns->iInstance); #else /* VBOX_WITH_WIN_PARPORT_SUP */ pThis->fParportAvail = false; pThis->u32LptAddr = 0; pThis->u32LptAddrControl = 0; pThis->u32LptAddrStatus = 0; rc = drvWinHostGetparportAddr(pThis); /* If we have the char port availabe use it , else I am not getting exclusive access to parallel port. Read and write will be done only if addresses are available */ if (pThis->szParportName) { rc = RTFileOpen(&pThis->hWinFileDevice, (char *)pThis->szParportName, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); } #endif return VINF_SUCCESS; }
/** * Opens the USB device. * * @returns VBox status code. * @param pProxyDev The device instance. * @param pszAddress The unique device identifier. * The format of this string is "VendorId:ProducIt:Release:StaticPath". * @param pvBackend Backend specific pointer, unused for the solaris backend. */ static DECLCALLBACK(int) usbProxySolarisOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend) { PUSBPROXYDEVSOL pDevSol = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVSOL); LogFlowFunc((USBPROXY ":usbProxySolarisOpen pProxyDev=%p pszAddress=%s pvBackend=%p\n", pProxyDev, pszAddress, pvBackend)); /* * Initialize our USB R3 lib. */ int rc = USBLibInit(); if (RT_SUCCESS(rc)) { /* * Allocate and initialize the solaris backend data. */ AssertCompile(PATH_MAX >= MAXPATHLEN); char szDeviceIdent[PATH_MAX+48]; rc = RTStrPrintf(szDeviceIdent, sizeof(szDeviceIdent), "%s", pszAddress); if (RT_SUCCESS(rc)) { rc = RTCritSectInit(&pDevSol->CritSect); if (RT_SUCCESS(rc)) { /* * Create wakeup pipe. */ rc = RTPipeCreate(&pDevSol->hPipeWakeupR, &pDevSol->hPipeWakeupW, 0); if (RT_SUCCESS(rc)) { int Instance; char *pszDevicePath = NULL; rc = USBLibGetClientInfo(szDeviceIdent, &pszDevicePath, &Instance); if (RT_SUCCESS(rc)) { pDevSol->pszDevicePath = pszDevicePath; /* * Open the client driver. */ RTFILE hFile; rc = RTFileOpen(&hFile, pDevSol->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { pDevSol->hFile = hFile; pDevSol->pProxyDev = pProxyDev; /* * Verify client driver version. */ VBOXUSBREQ_GET_VERSION GetVersionReq; bzero(&GetVersionReq, sizeof(GetVersionReq)); rc = usbProxySolarisIOCtl(pDevSol, VBOXUSB_IOCTL_GET_VERSION, &GetVersionReq, sizeof(GetVersionReq)); if (RT_SUCCESS(rc)) { if ( GetVersionReq.u32Major == VBOXUSB_VERSION_MAJOR && GetVersionReq.u32Minor >= VBOXUSB_VERSION_MINOR) { /* * Try & get the current cached config from Solaris. */ usbProxySolarisGetActiveConfig(pDevSol); return VINF_SUCCESS; } else { LogRel((USBPROXY ":version mismatch! driver v%d.%d expecting ~v%d.%d\n", GetVersionReq.u32Major, GetVersionReq.u32Minor, VBOXUSB_VERSION_MAJOR, VBOXUSB_VERSION_MINOR)); rc = VERR_VERSION_MISMATCH; } } else LogRel((USBPROXY ":failed to query driver version. rc=%Rrc\n", rc)); RTFileClose(pDevSol->hFile); pDevSol->hFile = NIL_RTFILE; pDevSol->pProxyDev = NULL; } else LogRel((USBPROXY ":failed to open device. rc=%Rrc pszDevicePath=%s\n", rc, pDevSol->pszDevicePath)); RTStrFree(pDevSol->pszDevicePath); pDevSol->pszDevicePath = NULL; } else { LogRel((USBPROXY ":failed to get client info. rc=%Rrc pszDevicePath=%s\n", rc, pDevSol->pszDevicePath)); if (rc == VERR_NOT_FOUND) rc = VERR_OPEN_FAILED; } RTPipeClose(pDevSol->hPipeWakeupR); RTPipeClose(pDevSol->hPipeWakeupW); } RTCritSectDelete(&pDevSol->CritSect); } else LogRel((USBPROXY ":RTCritSectInit failed. rc=%Rrc pszAddress=%s\n", rc, pszAddress)); } else LogRel((USBPROXY ":RTStrAPrintf failed. rc=%Rrc pszAddress=%s\n", rc, pszAddress)); } else LogRel((USBPROXY ":USBLibInit failed. rc=%Rrc\n", rc)); USBLibTerm(); return rc; }
/** * Runs a process, collecting the standard output and/or standard error. * * * @returns IPRT status code * @retval VERR_NO_TRANSLATION if the output of the program isn't valid UTF-8 * or contains a nul character. * @retval VERR_TOO_MUCH_DATA if the process produced too much data. * * @param pszExec Executable image to use to create the child process. * @param papszArgs Pointer to an array of arguments to the child. The * array terminated by an entry containing NULL. * @param hEnv Handle to the environment block for the child. * @param fFlags A combination of RTPROCEXEC_FLAGS_XXX. The @a * ppszStdOut and @a ppszStdErr parameters takes precedence * over redirection flags. * @param pStatus Where to return the status on success. * @param ppszStdOut Where to return the text written to standard output. If * NULL then standard output will not be collected and go * to the standard output handle of the process. * Free with RTStrFree, regardless of return status. * @param ppszStdErr Where to return the text written to standard error. If * NULL then standard output will not be collected and go * to the standard error handle of the process. * Free with RTStrFree, regardless of return status. */ int RTProcExecToString(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags, PRTPROCSTATUS pStatus, char **ppszStdOut, char **ppszStdErr) { int rc2; /* * Clear output arguments (no returning failure here, simply crash!). */ AssertPtr(pStatus); pStatus->enmReason = RTPROCEXITREASON_ABEND; pStatus->iStatus = RTEXITCODE_FAILURE; AssertPtrNull(ppszStdOut); if (ppszStdOut) *ppszStdOut = NULL; AssertPtrNull(ppszStdOut); if (ppszStdErr) *ppszStdErr = NULL; /* * Check input arguments. */ AssertReturn(!(fFlags & ~RTPROCEXEC_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); /* * Do we need a standard input bitbucket? */ int rc = VINF_SUCCESS; PRTHANDLE phChildStdIn = NULL; RTHANDLE hChildStdIn; hChildStdIn.enmType = RTHANDLETYPE_FILE; hChildStdIn.u.hFile = NIL_RTFILE; if ((fFlags & RTPROCEXEC_FLAGS_STDIN_NULL) && RT_SUCCESS(rc)) { phChildStdIn = &hChildStdIn; rc = RTFileOpenBitBucket(&hChildStdIn.u.hFile, RTFILE_O_READ); } /* * Create the output pipes / bitbuckets. */ RTPIPE hPipeStdOutR = NIL_RTPIPE; PRTHANDLE phChildStdOut = NULL; RTHANDLE hChildStdOut; hChildStdOut.enmType = RTHANDLETYPE_PIPE; hChildStdOut.u.hPipe = NIL_RTPIPE; if (ppszStdOut && RT_SUCCESS(rc)) { phChildStdOut = &hChildStdOut; rc = RTPipeCreate(&hPipeStdOutR, &hChildStdOut.u.hPipe, 0 /*fFlags*/); } else if ((fFlags & RTPROCEXEC_FLAGS_STDOUT_NULL) && RT_SUCCESS(rc)) { phChildStdOut = &hChildStdOut; hChildStdOut.enmType = RTHANDLETYPE_FILE; hChildStdOut.u.hFile = NIL_RTFILE; rc = RTFileOpenBitBucket(&hChildStdOut.u.hFile, RTFILE_O_WRITE); } RTPIPE hPipeStdErrR = NIL_RTPIPE; PRTHANDLE phChildStdErr = NULL; RTHANDLE hChildStdErr; hChildStdErr.enmType = RTHANDLETYPE_PIPE; hChildStdErr.u.hPipe = NIL_RTPIPE; if (ppszStdErr && RT_SUCCESS(rc)) { phChildStdErr = &hChildStdErr; rc = RTPipeCreate(&hPipeStdErrR, &hChildStdErr.u.hPipe, 0 /*fFlags*/); } else if ((fFlags & RTPROCEXEC_FLAGS_STDERR_NULL) && RT_SUCCESS(rc)) { phChildStdErr = &hChildStdErr; hChildStdErr.enmType = RTHANDLETYPE_FILE; hChildStdErr.u.hFile = NIL_RTFILE; rc = RTFileOpenBitBucket(&hChildStdErr.u.hFile, RTFILE_O_WRITE); } if (RT_SUCCESS(rc)) { RTPOLLSET hPollSet; rc = RTPollSetCreate(&hPollSet); if (RT_SUCCESS(rc)) { if (hPipeStdOutR != NIL_RTPIPE && RT_SUCCESS(rc)) rc = RTPollSetAddPipe(hPollSet, hPipeStdOutR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 1); if (hPipeStdErrR != NIL_RTPIPE) rc = RTPollSetAddPipe(hPollSet, hPipeStdErrR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 2); } if (RT_SUCCESS(rc)) { /* * Create the process. */ RTPROCESS hProc; rc = RTProcCreateEx(g_szSvnPath, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL /*phStdIn*/, phChildStdOut, phChildStdErr, NULL /*pszAsUser*/, NULL /*pszPassword*/, &hProc); rc2 = RTHandleClose(&hChildStdErr); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdOut); AssertRC(rc2); if (RT_SUCCESS(rc)) { /* * Process output and wait for the process to finish. */ size_t cbStdOut = 0; size_t offStdOut = 0; size_t cbStdErr = 0; size_t offStdErr = 0; for (;;) { if (hPipeStdOutR != NIL_RTPIPE) rc = rtProcProcessOutput(rc, &hPipeStdOutR, &cbStdOut, &offStdOut, ppszStdOut, hPollSet, 1); if (hPipeStdErrR != NIL_RTPIPE) rc = rtProcProcessOutput(rc, &hPipeStdErrR, &cbStdErr, &offStdErr, ppszStdErr, hPollSet, 2); if (hPipeStdOutR == NIL_RTPIPE && hPipeStdErrR == NIL_RTPIPE) break; if (hProc != NIL_RTPROCESS) { rc2 = RTProcWait(hProc, RTPROCWAIT_FLAGS_NOBLOCK, pStatus); if (rc2 != VERR_PROCESS_RUNNING) { if (RT_FAILURE(rc2)) rc = rc2; hProc = NIL_RTPROCESS; } } rc2 = RTPoll(hPollSet, 10000, NULL, NULL); Assert(RT_SUCCESS(rc2) || rc2 == VERR_TIMEOUT); } if (RT_SUCCESS(rc)) { if ( (ppszStdOut && *ppszStdOut && !RTStrIsValidEncoding(*ppszStdOut)) || (ppszStdErr && *ppszStdErr && !RTStrIsValidEncoding(*ppszStdErr)) ) rc = VERR_NO_TRANSLATION; } /* * No more output, just wait for it to finish. */ if (hProc != NIL_RTPROCESS) { rc2 = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, pStatus); if (RT_FAILURE(rc2)) rc = rc2; } } RTPollSetDestroy(hPollSet); } } rc2 = RTHandleClose(&hChildStdErr); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdOut); AssertRC(rc2); rc2 = RTHandleClose(&hChildStdIn); AssertRC(rc2); rc2 = RTPipeClose(hPipeStdErrR); AssertRC(rc2); rc2 = RTPipeClose(hPipeStdOutR); AssertRC(rc2); return rc; }
/** * Construct a TCP socket stream driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvTCPConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { RT_NOREF(fFlags); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); PDRVTCP pThis = PDMINS_2_DATA(pDrvIns, PDRVTCP); /* * Init the static parts. */ pThis->pDrvIns = pDrvIns; pThis->pszLocation = NULL; pThis->fIsServer = false; pThis->hTcpServ = NULL; pThis->hTcpSock = NIL_RTSOCKET; pThis->hPollSet = NIL_RTPOLLSET; pThis->hPipeWakeR = NIL_RTPIPE; pThis->hPipeWakeW = NIL_RTPIPE; pThis->fTcpSockInPollSet = false; pThis->ListenThread = NIL_RTTHREAD; pThis->fShutdown = false; /* IBase */ pDrvIns->IBase.pfnQueryInterface = drvTCPQueryInterface; /* IStream */ pThis->IStream.pfnPoll = drvTcpPoll; pThis->IStream.pfnPollInterrupt = drvTcpPollInterrupt; pThis->IStream.pfnRead = drvTcpRead; pThis->IStream.pfnWrite = drvTcpWrite; /* * Validate and read the configuration. */ PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "Location|IsServer", ""); int rc = CFGMR3QueryStringAlloc(pCfg, "Location", &pThis->pszLocation); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Configuration error: querying \"Location\" resulted in %Rrc"), rc); rc = CFGMR3QueryBool(pCfg, "IsServer", &pThis->fIsServer); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Configuration error: querying \"IsServer\" resulted in %Rrc"), rc); rc = RTPipeCreate(&pThis->hPipeWakeR, &pThis->hPipeWakeW, 0 /* fFlags */); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d: Failed to create wake pipe"), pDrvIns->iInstance); rc = RTPollSetCreate(&pThis->hPollSet); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d: Failed to create poll set"), pDrvIns->iInstance); rc = RTPollSetAddPipe(pThis->hPollSet, pThis->hPipeWakeR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, DRVTCP_POLLSET_ID_WAKEUP); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d failed to add wakeup pipe for %s to poll set"), pDrvIns->iInstance, pThis->pszLocation); /* * Create/Open the socket. */ if (pThis->fIsServer) { uint32_t uPort = 0; rc = RTStrToUInt32Ex(pThis->pszLocation, NULL, 10, &uPort); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d: The port part of the location is not a numerical value"), pDrvIns->iInstance); /** @todo Allow binding to distinct interfaces. */ rc = RTTcpServerCreateEx(NULL, uPort, &pThis->hTcpServ); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d failed to create server socket"), pDrvIns->iInstance); rc = RTThreadCreate(&pThis->ListenThread, drvTCPListenLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "DrvTCPStream"); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d failed to create listening thread"), pDrvIns->iInstance); } else { char *pszPort = strchr(pThis->pszLocation, ':'); if (!pszPort) return PDMDrvHlpVMSetError(pDrvIns, VERR_NOT_FOUND, RT_SRC_POS, N_("DrvTCP#%d: The location misses the port to connect to"), pDrvIns->iInstance); *pszPort = '\0'; /* Overwrite temporarily to avoid copying the hostname into a temporary buffer. */ uint32_t uPort = 0; rc = RTStrToUInt32Ex(pszPort + 1, NULL, 10, &uPort); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d: The port part of the location is not a numerical value"), pDrvIns->iInstance); rc = RTTcpClientConnect(pThis->pszLocation, uPort, &pThis->hTcpSock); *pszPort = ':'; /* Restore delimiter before checking the status. */ if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d failed to connect to socket %s"), pDrvIns->iInstance, pThis->pszLocation); rc = RTPollSetAddSocket(pThis->hPollSet, pThis->hTcpSock, RTPOLL_EVT_READ | RTPOLL_EVT_WRITE | RTPOLL_EVT_ERROR, DRVTCP_POLLSET_ID_SOCKET); if (RT_FAILURE(rc)) return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("DrvTCP#%d failed to add socket for %s to poll set"), pDrvIns->iInstance, pThis->pszLocation); pThis->fTcpSockInPollSet = true; } LogRel(("DrvTCP: %s, %s\n", pThis->pszLocation, pThis->fIsServer ? "server" : "client")); return VINF_SUCCESS; }