コード例 #1
0
ファイル: DrvHostParallel.cpp プロジェクト: miguelinux/vbox
static DECLCALLBACK(int) drvHostParallelMonitorThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
{
    PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    struct pollfd aFDs[2];

    /*
     * We can wait for interrupts using poll on linux hosts.
     */
    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    {
        int rc;

        aFDs[0].fd      = RTFileToNative(pThis->hFileDevice);
        aFDs[0].events  = POLLIN;
        aFDs[0].revents = 0;
        aFDs[1].fd      = RTPipeToNative(pThis->hWakeupPipeR);
        aFDs[1].events  = POLLIN | POLLERR | POLLHUP;
        aFDs[1].revents = 0;
        rc = poll(aFDs, RT_ELEMENTS(aFDs), -1);
        if (rc < 0)
        {
            AssertMsgFailed(("poll failed with rc=%d\n", RTErrConvertFromErrno(errno)));
            return RTErrConvertFromErrno(errno);
        }

        if (pThread->enmState != PDMTHREADSTATE_RUNNING)
            break;
        if (rc > 0 && aFDs[1].revents)
        {
            if (aFDs[1].revents & (POLLHUP | POLLERR | POLLNVAL))
                break;
            /* notification to terminate -- drain the pipe */
            char ch;
            size_t cbRead;
            RTPipeRead(pThis->hWakeupPipeR, &ch, 1, &cbRead);
            continue;
        }

        /* Interrupt occurred. */
        rc = pThis->pDrvHostParallelPort->pfnNotifyInterrupt(pThis->pDrvHostParallelPort);
        AssertRC(rc);
    }

    return VINF_SUCCESS;
}
コード例 #2
0
ファイル: fileaio-freebsd.cpp プロジェクト: ryenus/vbox
RTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser)
{
    PRTFILEAIOREQINTERNAL pReqInt = (PRTFILEAIOREQINTERNAL)hReq;

    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    Assert(hFile != NIL_RTFILE);
    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);

    pReqInt->fFlush           = true;
    pReqInt->AioCB.aio_fildes = RTFileToNative(hFile);
    pReqInt->AioCB.aio_offset = 0;
    pReqInt->AioCB.aio_nbytes = 0;
    pReqInt->AioCB.aio_buf    = NULL;
    pReqInt->pvUser           = pvUser;
    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);

    return VINF_SUCCESS;
}
コード例 #3
0
int VbCpuRepMsrProberInitPlatform(PVBCPUREPMSRACCESSORS pMsrAccessors)
{
    RTFILE hFile;
    int rc = RTFileOpen(&hFile, MSR_DEV_NAME, RTFILE_O_READWRITE | RTFILE_O_DENY_NONE | RTFILE_O_OPEN);
    if (RT_SUCCESS(rc))
    {
        g_fdMsr = RTFileToNative(hFile);
        Assert(g_fdMsr != -1);

        pMsrAccessors->fAtomic             = false; /* Can't modify/restore MSRs without trip to R3. */
        pMsrAccessors->pfnMsrProberRead    = linuxMsrProberRead;
        pMsrAccessors->pfnMsrProberWrite   = linuxMsrProberWrite;
        pMsrAccessors->pfnMsrProberModify  = linuxMsrProberModify;
        pMsrAccessors->pfnTerm             = linuxMsrProberTerm;
        return VINF_SUCCESS;
    }
    vbCpuRepDebug("warning: Failed to open " MSR_DEV_NAME ": %Rrc\n", rc);
    return rc;
}
コード例 #4
0
/**
 * Destruct a host parallel driver instance.
 *
 * Most VM resources are freed by the VM. This callback is provided so that
 * any non-VM resources can be freed correctly.
 *
 * @param   pDrvIns     The driver instance data.
 */
static DECLCALLBACK(void) drvHostParallelDestruct(PPDMDRVINS pDrvIns)
{
    int rc;
    PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    LogFlowFunc(("iInstance=%d\n", pDrvIns->iInstance));
    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);

#ifndef VBOX_WITH_WIN_PARPORT_SUP
    if (pThis->hFileDevice != NIL_RTFILE)
        ioctl(RTFileToNative(pThis->hFileDevice), PPRELEASE);

    if (pThis->hWakeupPipeW != NIL_RTPIPE)
    {
        rc = RTPipeClose(pThis->hWakeupPipeW); AssertRC(rc);
        pThis->hWakeupPipeW = NIL_RTPIPE;
    }

    if (pThis->hWakeupPipeR != NIL_RTPIPE)
    {
        rc = RTPipeClose(pThis->hWakeupPipeR); AssertRC(rc);
        pThis->hWakeupPipeR = NIL_RTPIPE;
    }

    if (pThis->hFileDevice != NIL_RTFILE)
    {
        rc = RTFileClose(pThis->hFileDevice); AssertRC(rc);
        pThis->hFileDevice = NIL_RTFILE;
    }

    if (pThis->pszDevicePath)
    {
        MMR3HeapFree(pThis->pszDevicePath);
        pThis->pszDevicePath = NULL;
    }
#else  /* VBOX_WITH_WIN_PARPORT_SUP */
    if (pThis->hWinFileDevice != NIL_RTFILE)
    {
        rc = RTFileClose(pThis->hWinFileDevice); AssertRC(rc);
        pThis->hWinFileDevice = NIL_RTFILE;
    }
#endif /* VBOX_WITH_WIN_PARPORT_SUP */
}
コード例 #5
0
RTR3DECL(int)  RTFileSetSize(RTFILE hFile, uint64_t cbSize)
{
    /*
     * Get current file pointer.
     */
    int         rc;
    uint64_t    offCurrent;
    if (MySetFilePointer(hFile, 0, &offCurrent, FILE_CURRENT))
    {
        /*
         * Set new file pointer.
         */
        if (MySetFilePointer(hFile, cbSize, NULL, FILE_BEGIN))
        {
            /* set file pointer */
            if (SetEndOfFile((HANDLE)RTFileToNative(hFile)))
            {
                /*
                 * Restore file pointer and return.
                 * If the old pointer was beyond the new file end, ignore failure.
                 */
                if (    MySetFilePointer(hFile, offCurrent, NULL, FILE_BEGIN)
                    ||  offCurrent > cbSize)
                    return VINF_SUCCESS;
            }

            /*
             * Failed, try restoring the file pointer.
             */
            rc = GetLastError();
            MySetFilePointer(hFile, offCurrent, NULL, FILE_BEGIN);
        }
        else
            rc = GetLastError();
    }
    else
        rc = GetLastError();

    return RTErrConvertFromWin32(rc);
}
コード例 #6
0
/**
 * Changes the current mode of the host parallel port.
 *
 * @returns VBox status code.
 * @param   pThis    The host parallel port instance data.
 * @param   enmMode  The mode to change the port to.
 */
static int drvHostParallelSetMode(PDRVHOSTPARALLEL pThis, PDMPARALLELPORTMODE enmMode)
{
    int iMode = 0;
    int rc = VINF_SUCCESS;
    LogFlowFunc(("mode=%d\n", enmMode));

# ifndef VBOX_WITH_WIN_PARPORT_SUP
    int rcLnx;
    if (pThis->enmModeCur != enmMode)
    {
        switch (enmMode)
        {
            case PDM_PARALLEL_PORT_MODE_SPP:
                iMode = IEEE1284_MODE_COMPAT;
                break;
            case PDM_PARALLEL_PORT_MODE_EPP_DATA:
                iMode = IEEE1284_MODE_EPP | IEEE1284_DATA;
                break;
            case PDM_PARALLEL_PORT_MODE_EPP_ADDR:
                iMode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
                break;
            case PDM_PARALLEL_PORT_MODE_ECP:
            case PDM_PARALLEL_PORT_MODE_INVALID:
            default:
                return VERR_NOT_SUPPORTED;
        }

        rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPSETMODE, &iMode);
        if (RT_UNLIKELY(rcLnx < 0))
            rc = RTErrConvertFromErrno(errno);
        else
            pThis->enmModeCur = enmMode;
    }

    return rc;
# else  /* VBOX_WITH_WIN_PARPORT_SUP */
    return VINF_SUCCESS;
# endif /* VBOX_WITH_WIN_PARPORT_SUP */
}
コード例 #7
0
RTR3DECL(int) RTFileSetTimes(RTFILE hFile, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
                             PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
{
    /*
     * We can only set AccessTime and ModificationTime, so if neither
     * are specified we can return immediately.
     */
    if (!pAccessTime && !pModificationTime)
        return VINF_SUCCESS;

    /*
     * Convert the input to timeval, getting the missing one if necessary,
     * and call the API which does the change.
     */
    struct timeval aTimevals[2];
    if (pAccessTime && pModificationTime)
    {
        RTTimeSpecGetTimeval(pAccessTime,       &aTimevals[0]);
        RTTimeSpecGetTimeval(pModificationTime, &aTimevals[1]);
    }
    else
    {
        RTFSOBJINFO ObjInfo;
        int rc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_UNIX);
        if (RT_FAILURE(rc))
            return rc;
        RTTimeSpecGetTimeval(pAccessTime        ? pAccessTime       : &ObjInfo.AccessTime,       &aTimevals[0]);
        RTTimeSpecGetTimeval(pModificationTime  ? pModificationTime : &ObjInfo.ModificationTime, &aTimevals[1]);
    }

    if (futimes(RTFileToNative(hFile), aTimevals))
    {
        int rc = RTErrConvertFromErrno(errno);
        Log(("RTFileSetTimes(%RTfile,%p,%p,,): returns %Rrc\n", hFile, pAccessTime, pModificationTime, rc));
        return rc;
    }
    return VINF_SUCCESS;
}
コード例 #8
0
/**
 * @interface_method_impl{PDMIBASE,pfnWriteControl}
 */
static DECLCALLBACK(int) drvHostParallelWriteControl(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t fReg)
{
    PDRVHOSTPARALLEL    pThis   = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector));
    int rc = VINF_SUCCESS;
    int rcLnx = 0;

    LogFlowFunc(("fReg=%#x\n", fReg));
# ifndef VBOX_WITH_WIN_PARPORT_SUP
    rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWCONTROL, &fReg);
    if (RT_UNLIKELY(rcLnx < 0))
        rc = RTErrConvertFromErrno(errno);
# else /* VBOX_WITH_WIN_PARPORT_SUP */
    uint64_t u64Data;
    u64Data = (uint8_t)fReg;
    if (pThis->fParportAvail)
    {
        LogFlowFunc(("calling R0 to write CTRL, data=%#x\n", u64Data));
        rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_WRITECONTROL, u64Data);
        AssertRC(rc);
    }
# endif /* VBOX_WITH_WIN_PARPORT_SUP */
    return rc;
}
RTR3DECL(int) RTFileQueryFsSizes(RTFILE hFile, PRTFOFF pcbTotal, RTFOFF *pcbFree,
                                 uint32_t *pcbBlock, uint32_t *pcbSector)
{
    struct statvfs StatVFS;
    RT_ZERO(StatVFS);
    if (fstatvfs(RTFileToNative(hFile), &StatVFS))
        return RTErrConvertFromErrno(errno);

    /*
     * Calc the returned values.
     */
    if (pcbTotal)
        *pcbTotal = (RTFOFF)StatVFS.f_blocks * StatVFS.f_frsize;
    if (pcbFree)
        *pcbFree = (RTFOFF)StatVFS.f_bavail * StatVFS.f_frsize;
    if (pcbBlock)
        *pcbBlock = StatVFS.f_frsize;
    /* no idea how to get the sector... */
    if (pcbSector)
        *pcbSector = 512;

    return VINF_SUCCESS;
}
コード例 #10
0
RTR3DECL(bool) RTFileIsValid(RTFILE hFile)
{
    if (hFile != NIL_RTFILE)
    {
        DWORD dwType = GetFileType((HANDLE)RTFileToNative(hFile));
        switch (dwType)
        {
            case FILE_TYPE_CHAR:
            case FILE_TYPE_DISK:
            case FILE_TYPE_PIPE:
            case FILE_TYPE_REMOTE:
                return true;

            case FILE_TYPE_UNKNOWN:
                if (GetLastError() == NO_ERROR)
                    return true;
                break;

            default:
                break;
        }
    }
    return false;
}
コード例 #11
0
static DECLCALLBACK(int) drvHostParallelSetPortDirection(PPDMIHOSTPARALLELCONNECTOR pInterface, bool fForward)
{
    PDRVHOSTPARALLEL    pThis   = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector));
    int rc = VINF_SUCCESS;
    int iMode = 0;
    if (!fForward)
        iMode = 1;
# ifndef VBOX_WITH_WIN_PARPORT_SUP
    int rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPDATADIR, &iMode);
    if (RT_UNLIKELY(rcLnx < 0))
        rc = RTErrConvertFromErrno(errno);

# else /* VBOX_WITH_WIN_PARPORT_SUP */
    uint64_t u64Data;
    u64Data = (uint8_t)iMode;
    if (pThis->fParportAvail)
    {
        LogFlowFunc(("calling R0 to write CTRL, data=%#x\n", u64Data));
        rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_SETPORTDIRECTION, u64Data);
        AssertRC(rc);
    }
# endif /* VBOX_WITH_WIN_PARPORT_SUP */
    return rc;
}
コード例 #12
0
RTR3DECL(int) RTFileQueryInfo(RTFILE hFile, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
{
    /*
     * Validate input.
     */
    AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pObjInfo, VERR_INVALID_PARAMETER);
    if (    enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
        ||  enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
    {
        AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
        return VERR_INVALID_PARAMETER;
    }

    /*
     * Query file info.
     */
    struct stat Stat;
    if (fstat(RTFileToNative(hFile), &Stat))
    {
        int rc = RTErrConvertFromErrno(errno);
        Log(("RTFileQueryInfo(%RTfile,,%d): returns %Rrc\n", hFile, enmAdditionalAttribs, rc));
        return rc;
    }

    /*
     * Setup the returned data.
     */
    rtFsConvertStatToObjInfo(pObjInfo, &Stat, NULL, 0);

    /*
     * Requested attributes (we cannot provide anything actually).
     */
    switch (enmAdditionalAttribs)
    {
        case RTFSOBJATTRADD_NOTHING:
        case RTFSOBJATTRADD_UNIX:
            /* done */
            break;

        case RTFSOBJATTRADD_UNIX_OWNER:
            rtFsObjInfoAttrSetUnixOwner(pObjInfo, Stat.st_uid);
            break;

        case RTFSOBJATTRADD_UNIX_GROUP:
            rtFsObjInfoAttrSetUnixGroup(pObjInfo, Stat.st_gid);
            break;

        case RTFSOBJATTRADD_EASIZE:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_EASIZE;
            pObjInfo->Attr.u.EASize.cb            = 0;
            break;

        default:
            AssertMsgFailed(("Impossible!\n"));
            return VERR_INTERNAL_ERROR;
    }

    LogFlow(("RTFileQueryInfo(%RTfile,,%d): returns VINF_SUCCESS\n", hFile, enmAdditionalAttribs));
    return VINF_SUCCESS;
}
コード例 #13
0
RTR3DECL(int) RTFileSetTimes(RTFILE hFile, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
                             PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
{
    NOREF(pChangeTime); NOREF(pBirthTime);

    /*
     * We can only set AccessTime and ModificationTime, so if neither
     * are specified we can return immediately.
     */
    if (!pAccessTime && !pModificationTime)
        return VINF_SUCCESS;

#ifdef USE_FUTIMENS
    struct timespec aTimespecs[2];
    if (pAccessTime && pModificationTime)
    {
        memcpy(&aTimespecs[0], pAccessTime, sizeof(struct timespec));
        memcpy(&aTimespecs[1], pModificationTime, sizeof(struct timespec));
    }
    else
    {
        RTFSOBJINFO ObjInfo;
        int rc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_UNIX);
        if (RT_FAILURE(rc))
            return rc;
        memcpy(&aTimespecs[0], pAccessTime ? pAccessTime : &ObjInfo.AccessTime, sizeof(struct timespec));
        memcpy(&aTimespecs[1], pModificationTime ? pModificationTime : &ObjInfo.ModificationTime, sizeof(struct timespec));
    }

    if (futimens(RTFileToNative(hFile), aTimespecs))
    {
        int rc = RTErrConvertFromErrno(errno);
        Log(("RTFileSetTimes(%RTfile,%p,%p,,): returns %Rrc\n", hFile, pAccessTime, pModificationTime, rc));
        return rc;
    }
#else
    /*
     * Convert the input to timeval, getting the missing one if necessary,
     * and call the API which does the change.
     */
    struct timeval aTimevals[2];
    if (pAccessTime && pModificationTime)
    {
        RTTimeSpecGetTimeval(pAccessTime,       &aTimevals[0]);
        RTTimeSpecGetTimeval(pModificationTime, &aTimevals[1]);
    }
    else
    {
        RTFSOBJINFO ObjInfo;
        int rc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_UNIX);
        if (RT_FAILURE(rc))
            return rc;
        RTTimeSpecGetTimeval(pAccessTime        ? pAccessTime       : &ObjInfo.AccessTime,       &aTimevals[0]);
        RTTimeSpecGetTimeval(pModificationTime  ? pModificationTime : &ObjInfo.ModificationTime, &aTimevals[1]);
    }

    /* XXX this falls back to utimes("/proc/self/fd/...",...) for older kernels/glibcs and this
     * will not work for hardened builds where this directory is owned by root.root and mode 0500 */
    if (futimes(RTFileToNative(hFile), aTimevals))
    {
        int rc = RTErrConvertFromErrno(errno);
        Log(("RTFileSetTimes(%RTfile,%p,%p,,): returns %Rrc\n", hFile, pAccessTime, pModificationTime, rc));
        return rc;
    }
#endif
    return VINF_SUCCESS;
}
コード例 #14
0
/**
 * 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;
}
コード例 #15
0
/**
 * Get the size of the given file.
 * Works for block devices too.
 *
 * @returns VBox status code.
 * @param   hFile    The file handle.
 * @param   pcbSize  Where to store the size of the file on success.
 */
static int pdmacFileEpNativeGetSize(RTFILE hFile, uint64_t *pcbSize)
{
    int rc = VINF_SUCCESS;
    uint64_t cbSize = 0;

    rc = RTFileGetSize(hFile, &cbSize);
    if (RT_SUCCESS(rc) && (cbSize != 0))
        *pcbSize = cbSize;
    else
    {
#ifdef RT_OS_WINDOWS
        DISK_GEOMETRY DriveGeo;
        DWORD cbDriveGeo;
        if (DeviceIoControl((HANDLE)RTFileToNative(hFile),
                            IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
                            &DriveGeo, sizeof(DriveGeo), &cbDriveGeo, NULL))
        {
            if (   DriveGeo.MediaType == FixedMedia
                || DriveGeo.MediaType == RemovableMedia)
            {
                cbSize =     DriveGeo.Cylinders.QuadPart
                         *   DriveGeo.TracksPerCylinder
                         *   DriveGeo.SectorsPerTrack
                         *   DriveGeo.BytesPerSector;

                GET_LENGTH_INFORMATION DiskLenInfo;
                DWORD junk;
                if (DeviceIoControl((HANDLE)RTFileToNative(hFile),
                                    IOCTL_DISK_GET_LENGTH_INFO, NULL, 0,
                                    &DiskLenInfo, sizeof(DiskLenInfo), &junk, (LPOVERLAPPED)NULL))
                {
                    /* IOCTL_DISK_GET_LENGTH_INFO is supported -- override cbSize. */
                    cbSize = DiskLenInfo.Length.QuadPart;
                }

                rc = VINF_SUCCESS;
            }
            else
            {
                rc = VERR_INVALID_PARAMETER;
            }
        }
        else
            rc = RTErrConvertFromWin32(GetLastError());

#elif defined(RT_OS_DARWIN)
        struct stat DevStat;
        if (!fstat(RTFileToNative(hFile), &DevStat) && S_ISBLK(DevStat.st_mode))
        {
            uint64_t cBlocks;
            uint32_t cbBlock;
            if (!ioctl(RTFileToNative(hFile), DKIOCGETBLOCKCOUNT, &cBlocks))
            {
                if (!ioctl(RTFileToNative(hFile), DKIOCGETBLOCKSIZE, &cbBlock))
                    cbSize = cBlocks * cbBlock;
                else
                    rc = RTErrConvertFromErrno(errno);
            }
            else
                rc = RTErrConvertFromErrno(errno);
        }
        else
            rc = VERR_INVALID_PARAMETER;

#elif defined(RT_OS_SOLARIS)
        struct stat DevStat;
        if (   !fstat(RTFileToNative(hFile), &DevStat)
            && (   S_ISBLK(DevStat.st_mode)
                || S_ISCHR(DevStat.st_mode)))
        {
            struct dk_minfo mediainfo;
            if (!ioctl(RTFileToNative(hFile), DKIOCGMEDIAINFO, &mediainfo))
                cbSize = mediainfo.dki_capacity * mediainfo.dki_lbsize;
            else
                rc = RTErrConvertFromErrno(errno);
        }
        else
            rc = VERR_INVALID_PARAMETER;

#elif defined(RT_OS_FREEBSD)
        struct stat DevStat;
        if (!fstat(RTFileToNative(hFile), &DevStat) && S_ISCHR(DevStat.st_mode))
        {
            off_t cbMedia = 0;
            if (!ioctl(RTFileToNative(hFile), DIOCGMEDIASIZE, &cbMedia))
            {
                cbSize = cbMedia;
            }
            else
                rc = RTErrConvertFromErrno(errno);
        }
        else
            rc = VERR_INVALID_PARAMETER;
#else
        /* Could be a block device */
        rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, &cbSize);
#endif

        if (RT_SUCCESS(rc) && (cbSize != 0))
            *pcbSize = cbSize;
        else if (RT_SUCCESS(rc))
            rc = VERR_NOT_SUPPORTED;
    }

    return rc;
}
コード例 #16
0
/**
 * Reap URBs in-flight on a device.
 *
 * @returns Pointer to a completed URB.
 * @returns NULL if no URB was completed.
 * @param   pProxyDev   The device.
 * @param   cMillies    Number of milliseconds to wait. Use 0 to not wait at all.
 */
static DECLCALLBACK(PVUSBURB) usbProxySolarisUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
{
    //LogFlowFunc((USBPROXY ":usbProxySolarisUrbReap pProxyDev=%p cMillies=%u\n", pProxyDev, cMillies));

    PUSBPROXYDEVSOL pDevSol = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVSOL);

    /*
     * Don't block if nothing is in the air.
     */
    if (!pDevSol->pInFlightHead)
        return NULL;

    /*
     * Deque URBs inflight or those landed.
     */
    if (cMillies > 0)
    {
        for (;;)
        {
            int cMilliesWait = cMillies == RT_INDEFINITE_WAIT ? -1 : cMillies;
            struct pollfd pfd[2];

            pfd[0].fd = RTFileToNative(pDevSol->hFile);
            pfd[0].events = POLLIN;
            pfd[0].revents = 0;

            pfd[1].fd = RTPipeToNative(pDevSol->hPipeWakeupR);
            pfd[1].events = POLLIN;
            pfd[1].revents = 0;

            int rc = poll(&pfd[0], 2, cMilliesWait);
            if (rc > 0)
            {
                if (pfd[0].revents & POLLHUP)
                {
                    LogRel((USBPROXY ":Reaping failed, USB Device '%s' disconnected!\n", pDevSol->pProxyDev->pUsbIns->pszName));
                    pProxyDev->fDetached = true;
                    usbProxySolarisCloseFile(pDevSol);
                }

                if (pfd[1].revents & POLLIN)
                {
                    /* Got woken up, drain pipe. */
                    uint8_t bRead;
                    size_t cbIgnored = 0;
                    RTPipeRead(pDevSol->hPipeWakeupR, &bRead, 1, &cbIgnored);

                    /*
                     * It is possible that we got woken up and have an URB pending
                     * for completion. Do it on the way out. Otherwise return
                     * immediately to the caller.
                     */
                    if (!(pfd[0].revents & POLLIN))
                        return NULL;
                }

                break;
            }

            if (rc == 0)
            {
                //LogFlow((USBPROXY ":usbProxySolarisUrbReap: Timed out\n"));
                return NULL;
            }
            else if (rc != EAGAIN)
            {
                LogFlow((USBPROXY ":usbProxySolarisUrbReap Poll rc=%d errno=%d\n", rc, errno));
                return NULL;
            }
        }
    }

    usbProxySolarisUrbComplete(pDevSol);

    /*
     * Any URBs pending delivery?
     */
    PVUSBURB pUrb = NULL;
    while (pDevSol->pTaxingHead)
    {
        RTCritSectEnter(&pDevSol->CritSect);

        PUSBPROXYURBSOL pUrbSol = pDevSol->pTaxingHead;
        if (pUrbSol)
        {
            pUrb = pUrbSol->pVUsbUrb;
            if (pUrb)
            {
                pUrb->Dev.pvPrivate = NULL;
                usbProxySolarisUrbFree(pDevSol, pUrbSol);
            }
        }
        RTCritSectLeave(&pDevSol->CritSect);
    }

    return pUrb;
}
コード例 #17
0
DECLHIDDEN(int) drvHostBaseScsiCmdOs(PDRVHOSTBASE pThis, const uint8_t *pbCmd, size_t cbCmd, PDMMEDIATXDIR enmTxDir,
                                     void *pvBuf, uint32_t *pcbBuf, uint8_t *pbSense, size_t cbSense, uint32_t cTimeoutMillies)
{
    /*
     * Minimal input validation.
     */
    Assert(enmTxDir == PDMMEDIATXDIR_NONE || enmTxDir == PDMMEDIATXDIR_FROM_DEVICE || enmTxDir == PDMMEDIATXDIR_TO_DEVICE);
    Assert(!pvBuf || pcbBuf);
    Assert(pvBuf || enmTxDir == PDMMEDIATXDIR_NONE);
    Assert(pbSense || !cbSense);
    RT_NOREF(cbSense);
    AssertPtr(pbCmd);
    Assert(cbCmd <= 16 && cbCmd >= 1);

    /* Allocate the temporary buffer lazily. */
    if(RT_UNLIKELY(!pThis->Os.pbDoubleBuffer))
    {
        pThis->Os.pbDoubleBuffer = (uint8_t *)RTMemAlloc(SCSI_MAX_BUFFER_SIZE);
        if (!pThis->Os.pbDoubleBuffer)
            return VERR_NO_MEMORY;
    }

    int rc = VERR_GENERAL_FAILURE;
    int direction;
    struct cdrom_generic_command cgc;

    switch (enmTxDir)
    {
    case PDMMEDIATXDIR_NONE:
        Assert(*pcbBuf == 0);
        direction = CGC_DATA_NONE;
        break;
    case PDMMEDIATXDIR_FROM_DEVICE:
        Assert(*pcbBuf != 0);
        Assert(*pcbBuf <= SCSI_MAX_BUFFER_SIZE);
        /* Make sure that the buffer is clear for commands reading
         * data. The actually received data may be shorter than what
         * we expect, and due to the unreliable feedback about how much
         * data the ioctl actually transferred, it's impossible to
         * prevent that. Returning previous buffer contents may cause
         * security problems inside the guest OS, if users can issue
         * commands to the CDROM device. */
        memset(pThis->Os.pbDoubleBuffer, '\0', *pcbBuf);
        direction = CGC_DATA_READ;
        break;
    case PDMMEDIATXDIR_TO_DEVICE:
        Assert(*pcbBuf != 0);
        Assert(*pcbBuf <= SCSI_MAX_BUFFER_SIZE);
        memcpy(pThis->Os.pbDoubleBuffer, pvBuf, *pcbBuf);
        direction = CGC_DATA_WRITE;
        break;
    default:
        AssertMsgFailed(("enmTxDir invalid!\n"));
        direction = CGC_DATA_NONE;
    }
    memset(&cgc, '\0', sizeof(cgc));
    memcpy(cgc.cmd, pbCmd, RT_MIN(CDROM_PACKET_SIZE, cbCmd));
    cgc.buffer = (unsigned char *)pThis->Os.pbDoubleBuffer;
    cgc.buflen = *pcbBuf;
    cgc.stat = 0;
    Assert(cbSense >= sizeof(struct request_sense));
    cgc.sense = (struct request_sense *)pbSense;
    cgc.data_direction = direction;
    cgc.quiet = false;
    cgc.timeout = cTimeoutMillies;
    rc = ioctl(RTFileToNative(pThis->Os.hFileDevice), CDROM_SEND_PACKET, &cgc);
    if (rc < 0)
    {
        if (errno == EBUSY)
            rc = VERR_PDM_MEDIA_LOCKED;
        else if (errno == ENOSYS)
            rc = VERR_NOT_SUPPORTED;
        else
        {
            rc = RTErrConvertFromErrno(errno);
            if (rc == VERR_ACCESS_DENIED && cgc.sense->sense_key == SCSI_SENSE_NONE)
                cgc.sense->sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
            Log2(("%s: error status %d, rc=%Rrc\n", __FUNCTION__, cgc.stat, rc));
        }
    }
    switch (enmTxDir)
    {
    case PDMMEDIATXDIR_FROM_DEVICE:
        memcpy(pvBuf, pThis->Os.pbDoubleBuffer, *pcbBuf);
        break;
    default:
        ;
    }
    Log2(("%s: after ioctl: cgc.buflen=%d txlen=%d\n", __FUNCTION__, cgc.buflen, *pcbBuf));
    /* The value of cgc.buflen does not reliably reflect the actual amount
     * of data transferred (for packet commands with little data transfer
     * it's 0). So just assume that everything worked ok. */

    return rc;
}
コード例 #18
0
static int drvscsihostProcessRequestOne(PDRVSCSIHOST pThis, PPDMSCSIREQUEST pRequest)
{
    int rc = VINF_SUCCESS;
    unsigned uTxDir;

    LogFlowFunc(("Entered\n"));

#ifdef DEBUG
    drvscsihostDumpScsiRequest(pRequest);
#endif

    /* We implement only one device. */
    if (pRequest->uLogicalUnit != 0)
    {
        switch (pRequest->pbCDB[0])
        {
            case SCSI_INQUIRY:
            {
                SCSIINQUIRYDATA ScsiInquiryReply;

                memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply));

                ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN;
                ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
                drvscsihostScatterGatherListCopyFromBuffer(pRequest, &ScsiInquiryReply, sizeof(SCSIINQUIRYDATA));
                drvscsihostCmdOk(pRequest);
                break;
            }
            default:
                AssertMsgFailed(("Command not implemented for attached device\n"));
                drvscsiCmdError(pRequest, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_NONE);
        }
    }
    else
    {
#if defined(RT_OS_LINUX)
        sg_io_hdr_t ScsiIoReq;
        sg_iovec_t  *paSG = NULL;

        /* Setup SCSI request. */
        memset(&ScsiIoReq, 0, sizeof(sg_io_hdr_t));
        ScsiIoReq.interface_id = 'S';

        if (pRequest->uDataDirection == PDMSCSIREQUESTTXDIR_UNKNOWN)
            uTxDir = drvscsihostGetTransferDirectionFromCommand(pRequest->pbCDB[0]);
        else
            uTxDir = pRequest->uDataDirection;

        if (uTxDir == PDMSCSIREQUESTTXDIR_NONE)
            ScsiIoReq.dxfer_direction = SG_DXFER_NONE;
        else if (uTxDir == PDMSCSIREQUESTTXDIR_TO_DEVICE)
            ScsiIoReq.dxfer_direction = SG_DXFER_TO_DEV;
        else if (uTxDir == PDMSCSIREQUESTTXDIR_FROM_DEVICE)
            ScsiIoReq.dxfer_direction = SG_DXFER_FROM_DEV;
        else
            AssertMsgFailed(("Invalid transfer direction %u\n", uTxDir));

        ScsiIoReq.cmd_len     = pRequest->cbCDB;
        ScsiIoReq.mx_sb_len   = pRequest->cbSenseBuffer;
        ScsiIoReq.dxfer_len   = pRequest->cbScatterGather;

        if (pRequest->cScatterGatherEntries > 0)
        {
            if (pRequest->cScatterGatherEntries == 1)
            {
                ScsiIoReq.iovec_count = 0;
                ScsiIoReq.dxferp      = pRequest->paScatterGatherHead[0].pvSeg;
            }
            else
            {
                ScsiIoReq.iovec_count = pRequest->cScatterGatherEntries;

                paSG = (sg_iovec_t *)RTMemAllocZ(pRequest->cScatterGatherEntries * sizeof(sg_iovec_t));
                AssertReturn(paSG, VERR_NO_MEMORY);

                for (unsigned i = 0; i < pRequest->cScatterGatherEntries; i++)
                {
                    paSG[i].iov_base = pRequest->paScatterGatherHead[i].pvSeg;
                    paSG[i].iov_len  = pRequest->paScatterGatherHead[i].cbSeg;
                }
                ScsiIoReq.dxferp = paSG;
            }
        }

        ScsiIoReq.cmdp    = pRequest->pbCDB;
        ScsiIoReq.sbp     = pRequest->pbSenseBuffer;
        ScsiIoReq.timeout = UINT_MAX;
        ScsiIoReq.flags  |= SG_FLAG_DIRECT_IO;

        /* Issue command. */
        rc = ioctl(RTFileToNative(pThis->hDeviceFile), SG_IO, &ScsiIoReq);
        if (rc < 0)
        {
            AssertMsgFailed(("Ioctl failed with rc=%d\n", rc));
        }

        /* Request processed successfully. */
        Log(("Command successfully processed\n"));
        if (ScsiIoReq.iovec_count > 0)
            RTMemFree(paSG);
#endif
    }
    /* Notify device that request finished. */
    rc = pThis->pDevScsiPort->pfnSCSIRequestCompleted(pThis->pDevScsiPort, pRequest, SCSI_STATUS_OK, false, VINF_SUCCESS);
    AssertMsgRC(rc, ("Notifying device above failed rc=%Rrc\n", rc));

    return rc;

}
コード例 #19
0
RTR3DECL(int)  RTFileRead(RTFILE hFile, void *pvBuf, size_t cbToRead, size_t *pcbRead)
{
    if (cbToRead <= 0)
        return VINF_SUCCESS;
    ULONG cbToReadAdj = (ULONG)cbToRead;
    AssertReturn(cbToReadAdj == cbToRead, VERR_NUMBER_TOO_BIG);

    ULONG cbRead = 0;
    if (ReadFile((HANDLE)RTFileToNative(hFile), pvBuf, cbToReadAdj, &cbRead, NULL))
    {
        if (pcbRead)
            /* Caller can handle partial reads. */
            *pcbRead = cbRead;
        else
        {
            /* Caller expects everything to be read. */
            while (cbToReadAdj > cbRead)
            {
                ULONG cbReadPart = 0;
                if (!ReadFile((HANDLE)RTFileToNative(hFile), (char*)pvBuf + cbRead, cbToReadAdj - cbRead, &cbReadPart, NULL))
                    return RTErrConvertFromWin32(GetLastError());
                if (cbReadPart == 0)
                    return VERR_EOF;
                cbRead += cbReadPart;
            }
        }
        return VINF_SUCCESS;
    }

    /*
     * If it's a console, we might bump into out of memory conditions in the
     * ReadConsole call.
     */
    DWORD dwErr = GetLastError();
    if (dwErr == ERROR_NOT_ENOUGH_MEMORY)
    {
        ULONG cbChunk = cbToReadAdj / 2;
        if (cbChunk > 16*_1K)
            cbChunk = 16*_1K;
        else
            cbChunk = RT_ALIGN_32(cbChunk, 256);

        cbRead = 0;
        while (cbToReadAdj > cbRead)
        {
            ULONG cbToRead   = RT_MIN(cbChunk, cbToReadAdj - cbRead);
            ULONG cbReadPart = 0;
            if (!ReadFile((HANDLE)RTFileToNative(hFile), (char *)pvBuf + cbRead, cbToRead, &cbReadPart, NULL))
            {
                /* If we failed because the buffer is too big, shrink it and
                   try again. */
                dwErr = GetLastError();
                if (   dwErr == ERROR_NOT_ENOUGH_MEMORY
                    && cbChunk > 8)
                {
                    cbChunk /= 2;
                    continue;
                }
                return RTErrConvertFromWin32(dwErr);
            }
            cbRead += cbReadPart;

            /* Return if the caller can handle partial reads, otherwise try
               fill the buffer all the way up. */
            if (pcbRead)
            {
                *pcbRead = cbRead;
                break;
            }
            if (cbReadPart == 0)
                return VERR_EOF;
        }
        return VINF_SUCCESS;
    }

    return RTErrConvertFromWin32(dwErr);
}
コード例 #20
0
DECLHIDDEN(int) drvHostBaseScsiCmdOs(PDRVHOSTBASE pThis, const uint8_t *pbCmd, size_t cbCmd, PDMMEDIATXDIR enmTxDir,
                                     void *pvBuf, uint32_t *pcbBuf, uint8_t *pbSense, size_t cbSense, uint32_t cTimeoutMillies)
{
    /*
     * Minimal input validation.
     */
    Assert(enmTxDir == PDMMEDIATXDIR_NONE || enmTxDir == PDMMEDIATXDIR_FROM_DEVICE || enmTxDir == PDMMEDIATXDIR_TO_DEVICE);
    Assert(!pvBuf || pcbBuf);
    Assert(pvBuf || enmTxDir == PDMMEDIATXDIR_NONE);
    Assert(pbSense || !cbSense);
    AssertPtr(pbCmd);
    Assert(cbCmd <= 16 && cbCmd >= 1);
    const uint32_t cbBuf = pcbBuf ? *pcbBuf : 0;
    if (pcbBuf)
        *pcbBuf = 0;

    int rc = VINF_SUCCESS;
    int rcBSD = 0;
    union ccb DeviceCCB;
    union ccb *pDeviceCCB = &DeviceCCB;
    u_int32_t fFlags;

    memset(pDeviceCCB, 0, sizeof(DeviceCCB));
    pDeviceCCB->ccb_h.path_id   = pThis->Os.ScsiBus;
    pDeviceCCB->ccb_h.target_id = pThis->Os.ScsiTargetID;
    pDeviceCCB->ccb_h.target_lun = pThis->Os.ScsiLunID;

    /* The SCSI INQUIRY command can't be passed through directly. */
    if (pbCmd[0] == SCSI_INQUIRY)
    {
        pDeviceCCB->ccb_h.func_code = XPT_GDEV_TYPE;

        rcBSD = ioctl(RTFileToNative(pThis->Os.hFileDevice), CAMIOCOMMAND, pDeviceCCB);
        if (!rcBSD)
        {
            uint32_t cbCopy =   cbBuf < sizeof(struct scsi_inquiry_data)
                              ? cbBuf
                              : sizeof(struct scsi_inquiry_data);;
            memcpy(pvBuf, &pDeviceCCB->cgd.inq_data, cbCopy);
            memset(pbSense, 0, cbSense);

            if (pcbBuf)
                *pcbBuf = cbCopy;
        }
        else
            rc = RTErrConvertFromErrno(errno);
    }
    else
    {
        /* Copy the CDB. */
        memcpy(&pDeviceCCB->csio.cdb_io.cdb_bytes, pbCmd, cbCmd);

        /* Set direction. */
        if (enmTxDir == PDMMEDIATXDIR_NONE)
            fFlags = CAM_DIR_NONE;
        else if (enmTxDir == PDMMEDIATXDIR_FROM_DEVICE)
            fFlags = CAM_DIR_IN;
        else
            fFlags = CAM_DIR_OUT;

        fFlags |= CAM_DEV_QFRZDIS;

        cam_fill_csio(&pDeviceCCB->csio, 1, NULL, fFlags, MSG_SIMPLE_Q_TAG,
                      (u_int8_t *)pvBuf, cbBuf, cbSense, cbCmd,
                      cTimeoutMillies ? cTimeoutMillies : 30000/* timeout */);

        /* Send command */
        rcBSD = ioctl(RTFileToNative(pThis->Os.hFileDevice), CAMIOCOMMAND, pDeviceCCB);
        if (!rcBSD)
        {
            switch (pDeviceCCB->ccb_h.status & CAM_STATUS_MASK)
            {
                case CAM_REQ_CMP:
                    rc = VINF_SUCCESS;
                    break;
                case CAM_SEL_TIMEOUT:
                    rc = VERR_DEV_IO_ERROR;
                    break;
                case CAM_CMD_TIMEOUT:
                    rc = VERR_TIMEOUT;
                    break;
                default:
                    rc = VERR_DEV_IO_ERROR;
            }

            if (pcbBuf)
                *pcbBuf = cbBuf - pDeviceCCB->csio.resid;

            if (pbSense)
                memcpy(pbSense, &pDeviceCCB->csio.sense_data,
                       cbSense - pDeviceCCB->csio.sense_resid);
        }
        else
            rc = RTErrConvertFromErrno(errno);
    }
}
コード例 #21
0
/**
 * Reap URBs in-flight on a device.
 *
 * @returns Pointer to a completed URB.
 * @returns NULL if no URB was completed.
 * @param   pProxyDev   The device.
 * @param   cMillies    Number of milliseconds to wait. Use 0 to not wait at all.
 */
static PVUSBURB usbProxyFreeBSDUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
{
    struct usb_fs_endpoint *pXferEndpoint;
    PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv;
    PUSBENDPOINTFBSD pEndpointFBSD;
    PVUSBURB pUrb;
    struct usb_fs_complete UsbFsComplete;
    struct pollfd PollFd;
    int rc;

    LogFlow(("usbProxyFreeBSDUrbReap: pProxyDev=%p, cMillies=%u\n",
             pProxyDev, cMillies));

repeat:

    pUrb = NULL;

    /* check for cancelled transfers */
    if (pDevFBSD->fCancelling)
    {
        for (unsigned n = 0; n < USBFBSD_MAXENDPOINTS; n++)
        {
            pEndpointFBSD = &pDevFBSD->aSwEndpoint[n];
            if (pEndpointFBSD->fCancelling)
            {
                pEndpointFBSD->fCancelling = false;
                pUrb = pEndpointFBSD->pUrb;
                pEndpointFBSD->pUrb = NULL;

                if (pUrb != NULL)
                    break;
            }
        }

        if (pUrb != NULL)
        {
            pUrb->enmStatus = VUSBSTATUS_INVALID;
            pUrb->Dev.pvPrivate = NULL;

            switch (pUrb->enmType)
            {
                case VUSBXFERTYPE_MSG:
                    pUrb->cbData = 0;
                    break;
                case VUSBXFERTYPE_ISOC:
                    pUrb->cbData = 0;
                    for (int n = 0; n < (int)pUrb->cIsocPkts; n++)
                        pUrb->aIsocPkts[n].cb = 0;
                    break;
                default:
                    pUrb->cbData = 0;
                    break;
            }
            return pUrb;
        }
        pDevFBSD->fCancelling = false;
    }
    /* Zero default */

    memset(&UsbFsComplete, 0, sizeof(UsbFsComplete));

    /* Check if any endpoints are complete */
    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true);
    if (RT_SUCCESS(rc))
    {
        pXferEndpoint = &pDevFBSD->aHwEndpoint[UsbFsComplete.ep_index];
        pEndpointFBSD = &pDevFBSD->aSwEndpoint[UsbFsComplete.ep_index];

        LogFlow(("usbProxyFreeBSDUrbReap: Reaped "
                 "URB %#p\n", pEndpointFBSD->pUrb));

        if (pXferEndpoint->status == USB_ERR_CANCELLED)
            goto repeat;

        pUrb = pEndpointFBSD->pUrb;
        pEndpointFBSD->pUrb = NULL;
        if (pUrb == NULL)
            goto repeat;

        switch (pXferEndpoint->status)
        {
            case USB_ERR_NORMAL_COMPLETION:
                pUrb->enmStatus = VUSBSTATUS_OK;
                break;
            case USB_ERR_STALLED:
                pUrb->enmStatus = VUSBSTATUS_STALL;
                break;
            default:
                pUrb->enmStatus = VUSBSTATUS_INVALID;
                break;
        }

        pUrb->Dev.pvPrivate = NULL;

        switch (pUrb->enmType)
        {
            case VUSBXFERTYPE_MSG:
                pUrb->cbData = pEndpointFBSD->acbData[0] + pEndpointFBSD->acbData[1];
                break;
            case VUSBXFERTYPE_ISOC:
            {
                int n;

                if (pUrb->enmDir == VUSBDIRECTION_OUT)
                    break;
                pUrb->cbData = 0;
                for (n = 0; n < (int)pUrb->cIsocPkts; n++)
                {
                    if (n >= (int)pEndpointFBSD->cMaxFrames)
                        break;
                    pUrb->cbData += pEndpointFBSD->acbData[n];
                    pUrb->aIsocPkts[n].cb = pEndpointFBSD->acbData[n];
                }
                for (; n < (int)pUrb->cIsocPkts; n++)
                    pUrb->aIsocPkts[n].cb = 0;

                break;
            }
            default:
                pUrb->cbData = pEndpointFBSD->acbData[0];
                break;
        }

        LogFlow(("usbProxyFreeBSDUrbReap: Status=%d epindex=%u "
                 "len[0]=%d len[1]=%d\n",
                 (int)pXferEndpoint->status,
                 (unsigned)UsbFsComplete.ep_index,
                 (unsigned)pEndpointFBSD->acbData[0],
                 (unsigned)pEndpointFBSD->acbData[1]));

    }
    else if (cMillies && rc == VERR_RESOURCE_BUSY)
    {
        /* Poll for finished transfers */
        PollFd.fd = RTFileToNative(pDevFBSD->hFile);
        PollFd.events = POLLIN | POLLRDNORM;
        PollFd.revents = 0;

        rc = poll(&PollFd, 1, (cMillies == RT_INDEFINITE_WAIT) ? INFTIM : cMillies);
        if (rc >= 1)
        {
            goto repeat;
        }
        else
        {
            LogFlow(("usbProxyFreeBSDUrbReap: "
                     "poll returned rc=%d\n", rc));
        }
    }
    return pUrb;
}
コード例 #22
0
/**
 * Internal wrapper around various OS specific ioctl implementations.
 *
 * @returns VBox status code as returned by VBoxGuestCommonIOCtl, or
 *          an failure returned by the OS specific ioctl APIs.
 *
 * @param   iFunction   The requested function.
 * @param   pvData      The input and output data buffer.
 * @param   cbData      The size of the buffer.
 *
 * @remark  Exactly how the VBoxGuestCommonIOCtl is ferried back
 *          here is OS specific. On BSD and Darwin we can use errno,
 *          while on OS/2 we use the 2nd buffer of the IOCtl.
 */
int vbglR3DoIOCtl(unsigned iFunction, void *pvData, size_t cbData)
{
#if defined(RT_OS_WINDOWS)
    DWORD cbReturned = 0;
    if (!DeviceIoControl(g_hFile, iFunction, pvData, (DWORD)cbData, pvData, (DWORD)cbData, &cbReturned, NULL))
    {
/** @todo The passing of error codes needs to be tested and fixed (as does *all* the other hosts except for
 * OS/2).  The idea is that the VBox status codes in ring-0 should be transferred without loss down to
 * ring-3. However, it's not vitally important right now (obviously, since the other guys has been
 * ignoring it for 1+ years now).  On Linux and Solaris the transfer is done, but it is currently not
 * lossless, so still needs fixing. */
        DWORD LastErr = GetLastError();
        return RTErrConvertFromWin32(LastErr);
    }

    return VINF_SUCCESS;

#elif defined(RT_OS_OS2)
    ULONG cbOS2Parm = cbData;
    int32_t vrc = VERR_INTERNAL_ERROR;
    ULONG cbOS2Data = sizeof(vrc);
    APIRET rc = DosDevIOCtl((uintptr_t)g_File, VBOXGUEST_IOCTL_CATEGORY, iFunction,
                            pvData, cbData, &cbOS2Parm,
                            &vrc, sizeof(vrc), &cbOS2Data);
    if (RT_LIKELY(!rc))
        return vrc;
    return RTErrConvertFromOS2(rc);

#elif defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
    VBGLBIGREQ Hdr;
    Hdr.u32Magic = VBGLBIGREQ_MAGIC;
    Hdr.cbData = cbData;
    Hdr.pvDataR3 = pvData;
# if HC_ARCH_BITS == 32
    Hdr.u32Padding = 0;
# endif

/** @todo test status code passing! Check that the kernel doesn't do any
 *        error checks using specific errno values, and just pass an VBox
 *        error instead of an errno.h one. Alternatively, extend/redefine the
 *        header with an error code return field (much better alternative
 *        actually). */
#ifdef VBOX_VBGLR3_XFREE86
    int rc = xf86ioctl(g_File, iFunction, &Hdr);
#else
    int rc = ioctl(RTFileToNative(g_File), iFunction, &Hdr);
#endif
    if (rc == -1)
    {
        rc = errno;
        return RTErrConvertFromErrno(rc);
    }
    return VINF_SUCCESS;

#elif defined(RT_OS_LINUX)
# ifdef VBOX_VBGLR3_XFREE86
    int rc = xf86ioctl((int)g_File, iFunction, pvData);
# else
    if (g_File == NIL_RTFILE)
        return VERR_INVALID_HANDLE;
    int rc = ioctl(RTFileToNative(g_File), iFunction, pvData);
# endif
    if (RT_LIKELY(rc == 0))
        return VINF_SUCCESS;

    /* Positive values are negated VBox error status codes. */
    if (rc > 0)
        rc = -rc;
    else
# ifdef VBOX_VBGLR3_XFREE86
        rc = VERR_FILE_IO_ERROR;
#  else
        rc = RTErrConvertFromErrno(errno);
# endif
    NOREF(cbData);
    return rc;

#elif defined(VBOX_VBGLR3_XFREE86)
    /* PORTME - This is preferred over the RTFileIOCtl variant below, just be careful with the (int). */
/** @todo test status code passing! */
    int rc = xf86ioctl(g_File, iFunction, pvData);
    if (rc == -1)
        return VERR_FILE_IO_ERROR;  /* This is purely legacy stuff, it has to work and no more. */
    return VINF_SUCCESS;

#else
    /* Default implementation - PORTME: Do not use this without testings that passing errors works! */
/** @todo test status code passing! */
    int rc2 = VERR_INTERNAL_ERROR;
    int rc = RTFileIoCtl(g_File, (int)iFunction, pvData, cbData, &rc2);
    if (RT_SUCCESS(rc))
        rc = rc2;
    return rc;
#endif
}
コード例 #23
0
RTR3DECL(int)  RTFileWrite(RTFILE hFile, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
{
    if (cbToWrite <= 0)
        return VINF_SUCCESS;
    ULONG cbToWriteAdj = (ULONG)cbToWrite;
    AssertReturn(cbToWriteAdj == cbToWrite, VERR_NUMBER_TOO_BIG);

    ULONG cbWritten = 0;
    if (WriteFile((HANDLE)RTFileToNative(hFile), pvBuf, cbToWriteAdj, &cbWritten, NULL))
    {
        if (pcbWritten)
            /* Caller can handle partial writes. */
            *pcbWritten = cbWritten;
        else
        {
            /* Caller expects everything to be written. */
            while (cbToWriteAdj > cbWritten)
            {
                ULONG cbWrittenPart = 0;
                if (!WriteFile((HANDLE)RTFileToNative(hFile), (char*)pvBuf + cbWritten,
                               cbToWriteAdj - cbWritten, &cbWrittenPart, NULL))
                {
                    int rc = RTErrConvertFromWin32(GetLastError());
                    if (   rc == VERR_DISK_FULL
                        && IsBeyondLimit(hFile, cbToWriteAdj - cbWritten, FILE_CURRENT)
                       )
                        rc = VERR_FILE_TOO_BIG;
                    return rc;
                }
                if (cbWrittenPart == 0)
                    return VERR_WRITE_ERROR;
                cbWritten += cbWrittenPart;
            }
        }
        return VINF_SUCCESS;
    }

    /*
     * If it's a console, we might bump into out of memory conditions in the
     * WriteConsole call.
     */
    DWORD dwErr = GetLastError();
    if (dwErr == ERROR_NOT_ENOUGH_MEMORY)
    {
        ULONG cbChunk = cbToWriteAdj / 2;
        if (cbChunk > _32K)
            cbChunk = _32K;
        else
            cbChunk = RT_ALIGN_32(cbChunk, 256);

        cbWritten = 0;
        while (cbToWriteAdj > cbWritten)
        {
            ULONG cbToWrite     = RT_MIN(cbChunk, cbToWriteAdj - cbWritten);
            ULONG cbWrittenPart = 0;
            if (!WriteFile((HANDLE)RTFileToNative(hFile), (const char *)pvBuf + cbWritten, cbToWrite, &cbWrittenPart, NULL))
            {
                /* If we failed because the buffer is too big, shrink it and
                   try again. */
                dwErr = GetLastError();
                if (   dwErr == ERROR_NOT_ENOUGH_MEMORY
                    && cbChunk > 8)
                {
                    cbChunk /= 2;
                    continue;
                }
                int rc = RTErrConvertFromWin32(dwErr);
                if (   rc == VERR_DISK_FULL
                    && IsBeyondLimit(hFile, cbToWriteAdj - cbWritten, FILE_CURRENT))
                    rc = VERR_FILE_TOO_BIG;
                return rc;
            }
            cbWritten += cbWrittenPart;

            /* Return if the caller can handle partial writes, otherwise try
               write out everything. */
            if (pcbWritten)
            {
                *pcbWritten = cbWritten;
                break;
            }
            if (cbWrittenPart == 0)
                return VERR_WRITE_ERROR;
        }
        return VINF_SUCCESS;
    }

    int rc = RTErrConvertFromWin32(dwErr);
    if (   rc == VERR_DISK_FULL
        && IsBeyondLimit(hFile, cbToWriteAdj - cbWritten, FILE_CURRENT))
        rc = VERR_FILE_TOO_BIG;
    return rc;
}
コード例 #24
0
RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
                               PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
                               const char *pszPassword, PRTPROCESS phProcess)
{
    int rc;

    /*
     * Input validation
     */
    AssertPtrReturn(pszExec, VERR_INVALID_POINTER);
    AssertReturn(*pszExec, VERR_INVALID_PARAMETER);
    AssertReturn(!(fFlags & ~RTPROC_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
    AssertReturn(!(fFlags & RTPROC_FLAGS_DETACHED) || !phProcess, VERR_INVALID_PARAMETER);
    AssertReturn(hEnv != NIL_RTENV, VERR_INVALID_PARAMETER);
    AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER);
    AssertPtrNullReturn(pszAsUser, VERR_INVALID_POINTER);
    AssertReturn(!pszAsUser || *pszAsUser, VERR_INVALID_PARAMETER);
    AssertReturn(!pszPassword || pszAsUser, VERR_INVALID_PARAMETER);
    AssertPtrNullReturn(pszPassword, VERR_INVALID_POINTER);
#if defined(RT_OS_OS2)
    if (fFlags & RTPROC_FLAGS_DETACHED)
        return VERR_PROC_DETACH_NOT_SUPPORTED;
#endif

    /*
     * Get the file descriptors for the handles we've been passed.
     */
    PCRTHANDLE  paHandles[3] = { phStdIn, phStdOut, phStdErr };
    int         aStdFds[3]   = {      -1,       -1,       -1 };
    for (int i = 0; i < 3; i++)
    {
        if (paHandles[i])
        {
            AssertPtrReturn(paHandles[i], VERR_INVALID_POINTER);
            switch (paHandles[i]->enmType)
            {
                case RTHANDLETYPE_FILE:
                    aStdFds[i] = paHandles[i]->u.hFile != NIL_RTFILE
                               ? (int)RTFileToNative(paHandles[i]->u.hFile)
                               : -2 /* close it */;
                    break;

                case RTHANDLETYPE_PIPE:
                    aStdFds[i] = paHandles[i]->u.hPipe != NIL_RTPIPE
                               ? (int)RTPipeToNative(paHandles[i]->u.hPipe)
                               : -2 /* close it */;
                    break;

                case RTHANDLETYPE_SOCKET:
                    aStdFds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET
                               ? (int)RTSocketToNative(paHandles[i]->u.hSocket)
                               : -2 /* close it */;
                    break;

                default:
                    AssertMsgFailedReturn(("%d: %d\n", i, paHandles[i]->enmType), VERR_INVALID_PARAMETER);
            }
            /** @todo check the close-on-execness of these handles?  */
        }
    }

    for (int i = 0; i < 3; i++)
        if (aStdFds[i] == i)
            aStdFds[i] = -1;

    for (int i = 0; i < 3; i++)
        AssertMsgReturn(aStdFds[i] < 0 || aStdFds[i] > i,
                        ("%i := %i not possible because we're lazy\n", i, aStdFds[i]),
                        VERR_NOT_SUPPORTED);

    /*
     * Resolve the user id if specified.
     */
    uid_t uid = ~(uid_t)0;
    gid_t gid = ~(gid_t)0;
    if (pszAsUser)
    {
        rc = rtCheckCredentials(pszAsUser, pszPassword, &gid, &uid);
        if (RT_FAILURE(rc))
            return rc;
    }

    /*
     * Create the child environment if either RTPROC_FLAGS_PROFILE or
     * RTPROC_FLAGS_ENV_CHANGE_RECORD are in effect.
     */
    RTENV hEnvToUse = hEnv;
    if (   (fFlags & (RTPROC_FLAGS_ENV_CHANGE_RECORD | RTPROC_FLAGS_PROFILE))
        && (   (fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD)
            || hEnv == RTENV_DEFAULT) )
    {
        if (fFlags & RTPROC_FLAGS_PROFILE)
            rc = rtProcPosixCreateProfileEnv(&hEnvToUse, pszAsUser);
        else
            rc = RTEnvClone(&hEnvToUse, RTENV_DEFAULT);
        if (RT_SUCCESS(rc))
        {
            if ((fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD) && hEnv != RTENV_DEFAULT)
                rc = RTEnvApplyChanges(hEnvToUse, hEnv);
            if (RT_FAILURE(rc))
                RTEnvDestroy(hEnvToUse);
        }
        if (RT_FAILURE(rc))
            return rc;
    }

    /*
     * Check for execute access to the file.
     */
    char szRealExec[RTPATH_MAX];
    if (access(pszExec, X_OK))
    {
        rc = errno;
        if (   !(fFlags & RTPROC_FLAGS_SEARCH_PATH)
            || rc != ENOENT
            || RTPathHavePath(pszExec) )
            rc = RTErrConvertFromErrno(rc);
        else
        {
            /* search */
            char *pszPath = RTEnvDupEx(hEnvToUse, "PATH");
            rc = RTPathTraverseList(pszPath, ':', rtPathFindExec, (void *)pszExec, &szRealExec[0]);
            RTStrFree(pszPath);
            if (RT_SUCCESS(rc))
                pszExec = szRealExec;
            else
                rc = rc == VERR_END_OF_STRING ? VERR_FILE_NOT_FOUND : rc;
        }

        if (RT_FAILURE(rc))
            return rtProcPosixCreateReturn(rc, hEnvToUse, hEnv);
    }

    pid_t pid = -1;
    const char * const *papszEnv = RTEnvGetExecEnvP(hEnvToUse);
    AssertPtrReturn(papszEnv, rtProcPosixCreateReturn(VERR_INVALID_HANDLE, hEnvToUse, hEnv));


    /*
     * Take care of detaching the process.
     *
     * HACK ALERT! Put the process into a new process group with pgid = pid
     * to make sure it differs from that of the parent process to ensure that
     * the IPRT waitpid call doesn't race anyone (read XPCOM) doing group wide
     * waits. setsid() includes the setpgid() functionality.
     * 2010-10-11 XPCOM no longer waits for anything, but it cannot hurt.
     */
#ifndef RT_OS_OS2
    if (fFlags & RTPROC_FLAGS_DETACHED)
    {
# ifdef RT_OS_SOLARIS
        int templateFd = -1;
        if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
        {
            templateFd = rtSolarisContractPreFork();
            if (templateFd == -1)
                return rtProcPosixCreateReturn(VERR_OPEN_FAILED, hEnvToUse, hEnv);
        }
# endif /* RT_OS_SOLARIS */
        pid = fork();
        if (!pid)
        {
# ifdef RT_OS_SOLARIS
            if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
                rtSolarisContractPostForkChild(templateFd);
# endif
            setsid(); /* see comment above */

            pid = -1;
            /* Child falls through to the actual spawn code below. */
        }
        else
        {
# ifdef RT_OS_SOLARIS
            if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
                rtSolarisContractPostForkParent(templateFd, pid);
# endif
            if (pid > 0)
            {
                /* Must wait for the temporary process to avoid a zombie. */
                int status = 0;
                pid_t pidChild = 0;

                /* Restart if we get interrupted. */
                do
                {
                    pidChild = waitpid(pid, &status, 0);
                } while (   pidChild == -1
                         && errno == EINTR);

                /* Assume that something wasn't found. No detailed info. */
                if (status)
                    return rtProcPosixCreateReturn(VERR_PROCESS_NOT_FOUND, hEnvToUse, hEnv);
                if (phProcess)
                    *phProcess = 0;
                return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv);
            }
            return rtProcPosixCreateReturn(RTErrConvertFromErrno(errno), hEnvToUse, hEnv);
        }
    }
#endif

    /*
     * Spawn the child.
     *
     * Any spawn code MUST not execute any atexit functions if it is for a
     * detached process. It would lead to running the atexit functions which
     * make only sense for the parent. libORBit e.g. gets confused by multiple
     * execution. Remember, there was only a fork() so far, and until exec()
     * is successfully run there is nothing which would prevent doing anything
     * silly with the (duplicated) file descriptors.
     */
#ifdef HAVE_POSIX_SPAWN
    /** @todo OS/2: implement DETACHED (BACKGROUND stuff), see VbglR3Daemonize.  */
    if (   uid == ~(uid_t)0
        && gid == ~(gid_t)0)
    {
        /* Spawn attributes. */
        posix_spawnattr_t Attr;
        rc = posix_spawnattr_init(&Attr);
        if (!rc)
        {
            /* Indicate that process group and signal mask are to be changed,
               and that the child should use default signal actions. */
            rc = posix_spawnattr_setflags(&Attr, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF);
            Assert(rc == 0);

            /* The child starts in its own process group. */
            if (!rc)
            {
                rc = posix_spawnattr_setpgroup(&Attr, 0 /* pg == child pid */);
                Assert(rc == 0);
            }

            /* Unmask all signals. */
            if (!rc)
            {
                sigset_t SigMask;
                sigemptyset(&SigMask);
                rc = posix_spawnattr_setsigmask(&Attr, &SigMask); Assert(rc == 0);
            }

            /* File changes. */
            posix_spawn_file_actions_t  FileActions;
            posix_spawn_file_actions_t *pFileActions = NULL;
            if ((aStdFds[0] != -1 || aStdFds[1] != -1 || aStdFds[2] != -1) && !rc)
            {
                rc = posix_spawn_file_actions_init(&FileActions);
                if (!rc)
                {
                    pFileActions = &FileActions;
                    for (int i = 0; i < 3; i++)
                    {
                        int fd = aStdFds[i];
                        if (fd == -2)
                            rc = posix_spawn_file_actions_addclose(&FileActions, i);
                        else if (fd >= 0 && fd != i)
                        {
                            rc = posix_spawn_file_actions_adddup2(&FileActions, fd, i);
                            if (!rc)
                            {
                                for (int j = i + 1; j < 3; j++)
                                    if (aStdFds[j] == fd)
                                    {
                                        fd = -1;
                                        break;
                                    }
                                if (fd >= 0)
                                    rc = posix_spawn_file_actions_addclose(&FileActions, fd);
                            }
                        }
                        if (rc)
                            break;
                    }
                }
            }

            if (!rc)
                rc = posix_spawn(&pid, pszExec, pFileActions, &Attr, (char * const *)papszArgs,
                                 (char * const *)papszEnv);

            /* cleanup */
            int rc2 = posix_spawnattr_destroy(&Attr); Assert(rc2 == 0); NOREF(rc2);
            if (pFileActions)
            {
                rc2 = posix_spawn_file_actions_destroy(pFileActions);
                Assert(rc2 == 0);
            }

            /* return on success.*/
            if (!rc)
            {
                /* For a detached process this happens in the temp process, so
                 * it's not worth doing anything as this process must exit. */
                if (fFlags & RTPROC_FLAGS_DETACHED)
                    _Exit(0);
                if (phProcess)
                    *phProcess = pid;
                return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv);
            }
        }
        /* For a detached process this happens in the temp process, so
         * it's not worth doing anything as this process must exit. */
        if (fFlags & RTPROC_FLAGS_DETACHED)
            _Exit(124);
    }
    else
#endif
    {
#ifdef RT_OS_SOLARIS
        int templateFd = -1;
        if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
        {
            templateFd = rtSolarisContractPreFork();
            if (templateFd == -1)
                return rtProcPosixCreateReturn(VERR_OPEN_FAILED, hEnvToUse, hEnv);
        }
#endif /* RT_OS_SOLARIS */
        pid = fork();
        if (!pid)
        {
#ifdef RT_OS_SOLARIS
            if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
                rtSolarisContractPostForkChild(templateFd);
#endif /* RT_OS_SOLARIS */
            if (!(fFlags & RTPROC_FLAGS_DETACHED))
                setpgid(0, 0); /* see comment above */

            /*
             * Change group and user if requested.
             */
#if 1 /** @todo This needs more work, see suplib/hardening. */
            if (pszAsUser)
            {
                int ret = initgroups(pszAsUser, gid);
                if (ret)
                {
                    if (fFlags & RTPROC_FLAGS_DETACHED)
                        _Exit(126);
                    else
                        exit(126);
                }
            }
            if (gid != ~(gid_t)0)
            {
                if (setgid(gid))
                {
                    if (fFlags & RTPROC_FLAGS_DETACHED)
                        _Exit(126);
                    else
                        exit(126);
                }
            }

            if (uid != ~(uid_t)0)
            {
                if (setuid(uid))
                {
                    if (fFlags & RTPROC_FLAGS_DETACHED)
                        _Exit(126);
                    else
                        exit(126);
                }
            }
#endif

            /*
             * Some final profile environment tweaks, if running as user.
             */
            if (   (fFlags & RTPROC_FLAGS_PROFILE)
                && pszAsUser
                && (   (fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD)
                    || hEnv == RTENV_DEFAULT) )
            {
                rc = rtProcPosixAdjustProfileEnvFromChild(hEnvToUse, fFlags, hEnv);
                papszEnv = RTEnvGetExecEnvP(hEnvToUse);
                if (RT_FAILURE(rc) || !papszEnv)
                {
                    if (fFlags & RTPROC_FLAGS_DETACHED)
                        _Exit(126);
                    else
                        exit(126);
                }
            }

            /*
             * Unset the signal mask.
             */
            sigset_t SigMask;
            sigemptyset(&SigMask);
            rc = sigprocmask(SIG_SETMASK, &SigMask, NULL);
            Assert(rc == 0);

            /*
             * Apply changes to the standard file descriptor and stuff.
             */
            for (int i = 0; i < 3; i++)
            {
                int fd = aStdFds[i];
                if (fd == -2)
                    close(i);
                else if (fd >= 0)
                {
                    int rc2 = dup2(fd, i);
                    if (rc2 != i)
                    {
                        if (fFlags & RTPROC_FLAGS_DETACHED)
                            _Exit(125);
                        else
                            exit(125);
                    }
                    for (int j = i + 1; j < 3; j++)
                        if (aStdFds[j] == fd)
                        {
                            fd = -1;
                            break;
                        }
                    if (fd >= 0)
                        close(fd);
                }
            }

            /*
             * Finally, execute the requested program.
             */
            rc = execve(pszExec, (char * const *)papszArgs, (char * const *)papszEnv);
            if (errno == ENOEXEC)
            {
                /* This can happen when trying to start a shell script without the magic #!/bin/sh */
                RTAssertMsg2Weak("Cannot execute this binary format!\n");
            }
            else
                RTAssertMsg2Weak("execve returns %d errno=%d\n", rc, errno);
            RTAssertReleasePanic();
            if (fFlags & RTPROC_FLAGS_DETACHED)
                _Exit(127);
            else
                exit(127);
        }
#ifdef RT_OS_SOLARIS
        if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
            rtSolarisContractPostForkParent(templateFd, pid);
#endif /* RT_OS_SOLARIS */
        if (pid > 0)
        {
            /* For a detached process this happens in the temp process, so
             * it's not worth doing anything as this process must exit. */
            if (fFlags & RTPROC_FLAGS_DETACHED)
                _Exit(0);
            if (phProcess)
                *phProcess = pid;
            return rtProcPosixCreateReturn(VINF_SUCCESS, hEnvToUse, hEnv);
        }
        /* For a detached process this happens in the temp process, so
         * it's not worth doing anything as this process must exit. */
        if (fFlags & RTPROC_FLAGS_DETACHED)
            _Exit(124);
        return rtProcPosixCreateReturn(RTErrConvertFromErrno(errno), hEnvToUse, hEnv);
    }

    return rtProcPosixCreateReturn(VERR_NOT_IMPLEMENTED, hEnvToUse, hEnv);
}
コード例 #25
0
RTR3DECL(int) RTFileQueryInfo(RTFILE hFile, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
{
    /*
     * Validate input.
     */
    if (hFile == NIL_RTFILE)
    {
        AssertMsgFailed(("Invalid hFile=%RTfile\n", hFile));
        return VERR_INVALID_PARAMETER;
    }
    if (!pObjInfo)
    {
        AssertMsgFailed(("Invalid pObjInfo=%p\n", pObjInfo));
        return VERR_INVALID_PARAMETER;
    }
    if (    enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
        ||  enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
    {
        AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
        return VERR_INVALID_PARAMETER;
    }

    /*
     * Query file info.
     */
    BY_HANDLE_FILE_INFORMATION Data;
    if (!GetFileInformationByHandle((HANDLE)RTFileToNative(hFile), &Data))
    {
        DWORD dwErr = GetLastError();
        /* Only return if we *really* don't have a valid handle value,
         * everything else is fine here ... */
        if (dwErr == ERROR_INVALID_HANDLE)
            return RTErrConvertFromWin32(dwErr);
        RT_ZERO(Data);
        Data.dwFileAttributes = RTFS_DOS_NT_DEVICE;
    }

    /*
     * Setup the returned data.
     */
    pObjInfo->cbObject    = ((uint64_t)Data.nFileSizeHigh << 32)
                          |  (uint64_t)Data.nFileSizeLow;
    pObjInfo->cbAllocated = pObjInfo->cbObject;

    Assert(sizeof(uint64_t) == sizeof(Data.ftCreationTime));
    RTTimeSpecSetNtTime(&pObjInfo->BirthTime,         *(uint64_t *)&Data.ftCreationTime);
    RTTimeSpecSetNtTime(&pObjInfo->AccessTime,        *(uint64_t *)&Data.ftLastAccessTime);
    RTTimeSpecSetNtTime(&pObjInfo->ModificationTime,  *(uint64_t *)&Data.ftLastWriteTime);
    pObjInfo->ChangeTime  = pObjInfo->ModificationTime;

    pObjInfo->Attr.fMode  = rtFsModeFromDos((Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, "", 0);

    /*
     * Requested attributes (we cannot provide anything actually).
     */
    switch (enmAdditionalAttribs)
    {
        case RTFSOBJATTRADD_NOTHING:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_NOTHING;
            break;

        case RTFSOBJATTRADD_UNIX:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_UNIX;
            pObjInfo->Attr.u.Unix.uid             = ~0U;
            pObjInfo->Attr.u.Unix.gid             = ~0U;
            pObjInfo->Attr.u.Unix.cHardlinks      = Data.nNumberOfLinks ? Data.nNumberOfLinks : 1;
            pObjInfo->Attr.u.Unix.INodeIdDevice   = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */
            pObjInfo->Attr.u.Unix.INodeId         = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */
            pObjInfo->Attr.u.Unix.fFlags          = 0;
            pObjInfo->Attr.u.Unix.GenerationId    = 0;
            pObjInfo->Attr.u.Unix.Device          = 0;
            break;

        case RTFSOBJATTRADD_UNIX_OWNER:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_UNIX_OWNER;
            pObjInfo->Attr.u.UnixOwner.uid        = ~0U;
            pObjInfo->Attr.u.UnixOwner.szName[0]  = '\0'; /** @todo return something sensible here. */
            break;

        case RTFSOBJATTRADD_UNIX_GROUP:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_UNIX_GROUP;
            pObjInfo->Attr.u.UnixGroup.gid        = ~0U;
            pObjInfo->Attr.u.UnixGroup.szName[0]  = '\0';
            break;

        case RTFSOBJATTRADD_EASIZE:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_EASIZE;
            pObjInfo->Attr.u.EASize.cb            = 0;
            break;

        default:
            AssertMsgFailed(("Impossible!\n"));
            return VERR_INTERNAL_ERROR;
    }

    return VINF_SUCCESS;
}
コード例 #26
0
/**
 * Reap URBs in-flight on a device.
 *
 * @returns Pointer to a completed URB.
 * @returns NULL if no URB was completed.
 * @param   pProxyDev   The device.
 * @param   cMillies    Number of milliseconds to wait. Use 0 to not wait at all.
 */
static DECLCALLBACK(PVUSBURB) usbProxyFreeBSDUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
{
    struct usb_fs_endpoint *pXferEndpoint;
    PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD);
    PUSBENDPOINTFBSD pEndpointFBSD;
    PVUSBURB pUrb;
    struct usb_fs_complete UsbFsComplete;
    struct pollfd pfd[2];
    int rc;

    LogFlow(("usbProxyFreeBSDUrbReap: pProxyDev=%p, cMillies=%u\n",
             pProxyDev, cMillies));

repeat:

    pUrb = NULL;

    /* check for cancelled transfers */
    if (pDevFBSD->fCancelling)
    {
        for (unsigned n = 0; n < USBFBSD_MAXENDPOINTS; n++)
        {
            pEndpointFBSD = &pDevFBSD->aSwEndpoint[n];
            if (pEndpointFBSD->fCancelling)
            {
                pEndpointFBSD->fCancelling = false;
                pUrb = pEndpointFBSD->pUrb;
                pEndpointFBSD->pUrb = NULL;

                if (pUrb != NULL)
                    break;
            }
        }

        if (pUrb != NULL)
        {
            pUrb->enmStatus = VUSBSTATUS_INVALID;
            pUrb->Dev.pvPrivate = NULL;

            switch (pUrb->enmType)
            {
                case VUSBXFERTYPE_MSG:
                    pUrb->cbData = 0;
                    break;
                case VUSBXFERTYPE_ISOC:
                    pUrb->cbData = 0;
                    for (int n = 0; n < (int)pUrb->cIsocPkts; n++)
                        pUrb->aIsocPkts[n].cb = 0;
                    break;
                default:
                    pUrb->cbData = 0;
                    break;
            }
            return pUrb;
        }
        pDevFBSD->fCancelling = false;
    }
    /* Zero default */

    memset(&UsbFsComplete, 0, sizeof(UsbFsComplete));

    /* Check if any endpoints are complete */
    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true);
    if (RT_SUCCESS(rc))
    {
        pXferEndpoint = &pDevFBSD->aHwEndpoint[UsbFsComplete.ep_index];
        pEndpointFBSD = &pDevFBSD->aSwEndpoint[UsbFsComplete.ep_index];

        LogFlow(("usbProxyFreeBSDUrbReap: Reaped "
                 "URB %#p\n", pEndpointFBSD->pUrb));

        if (pXferEndpoint->status == USB_ERR_CANCELLED)
            goto repeat;

        pUrb = pEndpointFBSD->pUrb;
        pEndpointFBSD->pUrb = NULL;
        if (pUrb == NULL)
            goto repeat;

        switch (pXferEndpoint->status)
        {
            case USB_ERR_NORMAL_COMPLETION:
                pUrb->enmStatus = VUSBSTATUS_OK;
                break;
            case USB_ERR_STALLED:
                pUrb->enmStatus = VUSBSTATUS_STALL;
                break;
            default:
                pUrb->enmStatus = VUSBSTATUS_INVALID;
                break;
        }

        pUrb->Dev.pvPrivate = NULL;

        switch (pUrb->enmType)
        {
            case VUSBXFERTYPE_MSG:
                pUrb->cbData = pEndpointFBSD->acbData[0] + pEndpointFBSD->acbData[1];
                break;
            case VUSBXFERTYPE_ISOC:
            {
                int n;

                if (pUrb->enmDir == VUSBDIRECTION_OUT)
                    break;
                pUrb->cbData = 0;
                for (n = 0; n < (int)pUrb->cIsocPkts; n++)
                {
                    if (n >= (int)pEndpointFBSD->cMaxFrames)
                        break;
                    pUrb->cbData += pEndpointFBSD->acbData[n];
                    pUrb->aIsocPkts[n].cb = pEndpointFBSD->acbData[n];
                }
                for (; n < (int)pUrb->cIsocPkts; n++)
                    pUrb->aIsocPkts[n].cb = 0;

                break;
            }
            default:
                pUrb->cbData = pEndpointFBSD->acbData[0];
                break;
        }

        LogFlow(("usbProxyFreeBSDUrbReap: Status=%d epindex=%u "
                 "len[0]=%d len[1]=%d\n",
                 (int)pXferEndpoint->status,
                 (unsigned)UsbFsComplete.ep_index,
                 (unsigned)pEndpointFBSD->acbData[0],
                 (unsigned)pEndpointFBSD->acbData[1]));

    }
    else if (cMillies != 0 && rc == VERR_RESOURCE_BUSY)
    {
        for (;;)
        {
            pfd[0].fd = RTFileToNative(pDevFBSD->hFile);
            pfd[0].events = POLLIN | POLLRDNORM;
            pfd[0].revents = 0;

            pfd[1].fd = RTPipeToNative(pDevFBSD->hPipeWakeupR);
            pfd[1].events = POLLIN | POLLRDNORM;
            pfd[1].revents = 0;

            rc = poll(pfd, 2, (cMillies == RT_INDEFINITE_WAIT) ? INFTIM : cMillies);
            if (rc > 0)
            {
                if (pfd[1].revents & POLLIN)
                {
                    /* Got woken up, drain pipe. */
                    uint8_t bRead;
                    size_t cbIgnored = 0;
                    RTPipeRead(pDevFBSD->hPipeWakeupR, &bRead, 1, &cbIgnored);
                    /* Make sure we return from this function */
                    cMillies = 0;
                }
                break;
            }
            if (rc == 0)
                return NULL;
            if (errno != EAGAIN)
                return NULL;
        }
        goto repeat;
    }
    return pUrb;
}
コード例 #27
0
DECLHIDDEN(int) drvHostBaseOpenOs(PDRVHOSTBASE pThis, bool fReadOnly)
{
    RT_NOREF(fReadOnly);
    RTFILE hFileDevice;
    int rc = RTFileOpen(&hFileDevice, pThis->pszDevice, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    if (RT_FAILURE(rc))
        return rc;

    /*
     * The current device handle can't passthrough SCSI commands.
     * We have to get he passthrough device path and open this.
     */
    union ccb DeviceCCB;
    memset(&DeviceCCB, 0, sizeof(DeviceCCB));

    DeviceCCB.ccb_h.func_code = XPT_GDEVLIST;
    int rcBSD = ioctl(RTFileToNative(hFileDevice), CAMGETPASSTHRU, &DeviceCCB);
    if (!rcBSD)
    {
        char *pszPassthroughDevice = NULL;
        rc = RTStrAPrintf(&pszPassthroughDevice, "/dev/%s%u",
                          DeviceCCB.cgdl.periph_name, DeviceCCB.cgdl.unit_number);
        if (rc >= 0)
        {
            RTFILE hPassthroughDevice;
            rc = RTFileOpen(&hPassthroughDevice, pszPassthroughDevice, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
            RTStrFree(pszPassthroughDevice);
            if (RT_SUCCESS(rc))
            {
                /* Get needed device parameters. */

                /*
                 * The device path, target id and lun id. Those are
                 * needed for the SCSI passthrough ioctl.
                 */
                memset(&DeviceCCB, 0, sizeof(DeviceCCB));
                DeviceCCB.ccb_h.func_code = XPT_GDEVLIST;

                rcBSD = ioctl(RTFileToNative(hPassthroughDevice), CAMGETPASSTHRU, &DeviceCCB);
                if (!rcBSD)
                {
                    if (DeviceCCB.cgdl.status != CAM_GDEVLIST_ERROR)
                    {
                        pThis->Os.ScsiBus      = DeviceCCB.ccb_h.path_id;
                        pThis->Os.ScsiTargetID = DeviceCCB.ccb_h.target_id;
                        pThis->Os.ScsiLunID    = DeviceCCB.ccb_h.target_lun;
                        pThis->Os.hFileDevice  = hPassthroughDevice;
                    }
                    else
                    {
                        /* The passthrough device wasn't found. */
                        rc = VERR_NOT_FOUND;
                    }
                }
                else
                    rc = RTErrConvertFromErrno(errno);

                if (RT_FAILURE(rc))
                    RTFileClose(hPassthroughDevice);
            }
        }
        else
            rc = VERR_NO_STR_MEMORY;
    }
    else
        rc = RTErrConvertFromErrno(errno);

    RTFileClose(hFileDevice);
    return rc;
}