RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered)
{
    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED);
    AssertPtrNull(pcbTransfered);

    int rcSol = aio_error(&pReqInt->AioCB);
    Assert(rcSol != EINPROGRESS); /* Handled by our own state handling. */

    if (rcSol == 0)
    {
        if (pcbTransfered)
            *pcbTransfered = aio_return(&pReqInt->AioCB);
        return VINF_SUCCESS;
    }

    /* An error occurred. */
    return RTErrConvertFromErrno(rcSol);
}
Beispiel #2
0
/**
 * Rewinds the stream.
 *
 * Stream errors will be reset on success.
 *
 * @returns IPRT status code.
 *
 * @param   pStream         The stream.
 *
 * @remarks Not all streams are rewindable and that behavior is currently
 *          undefined for those.
 */
RTR3DECL(int) RTStrmRewind(PRTSTREAM pStream)
{
    AssertPtrReturn(pStream, VERR_INVALID_HANDLE);
    AssertReturn(pStream->u32Magic == RTSTREAM_MAGIC, VERR_INVALID_HANDLE);

    int rc;
    clearerr(pStream->pFile);
    errno = 0;
    if (!fseek(pStream->pFile, 0, SEEK_SET))
    {
        ASMAtomicWriteS32(&pStream->i32Error, VINF_SUCCESS);
        rc = VINF_SUCCESS;
    }
    else
    {
        rc = RTErrConvertFromErrno(errno);
        ASMAtomicWriteS32(&pStream->i32Error, rc);
    }

    return rc;
}
Beispiel #3
0
RTDECL(int) RTPathSetCurrent(const char *pszPath)
{
    /*
     * Validate input.
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);

    /*
     * Change the directory.
     */
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        if (chdir(pszNativePath))
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativePath, pszPath);
    }
    return rc;
}
RTR3DECL(int) RTThreadSetAffinity(PCRTCPUSET pCpuSet)
{
    /* convert */
    cpu_set_t LnxCpuSet;
    CPU_ZERO(&LnxCpuSet);
    if (!pCpuSet)
        for (unsigned iCpu = 0; iCpu < CPU_SETSIZE; iCpu++)
            CPU_SET(iCpu, &LnxCpuSet);
    else
        for (unsigned iCpu = 0; iCpu < RT_MIN(CPU_SETSIZE, RTCPUSET_MAX_CPUS); iCpu++)
            if (RTCpuSetIsMemberByIndex(pCpuSet, iCpu))
                CPU_SET(iCpu, &LnxCpuSet);

    int rc = pthread_setaffinity_np(pthread_self(), sizeof(LnxCpuSet), &LnxCpuSet);
    if (!rc)
        return VINF_SUCCESS;
    rc = errno;
    if (rc == ENOENT)
        return VERR_CPU_NOT_FOUND;
    return RTErrConvertFromErrno(errno);
}
/**
 * @interface_method_impl{PDMIBASE,pfnRead}
 */
static DECLCALLBACK(int) drvHostParallelRead(PPDMIHOSTPARALLELCONNECTOR pInterface, void *pvBuf, size_t cbRead, PDMPARALLELPORTMODE enmMode)
{
    PDRVHOSTPARALLEL    pThis   = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector));
    int rc = VINF_SUCCESS;

# ifndef VBOX_WITH_WIN_PARPORT_SUP
    int rcLnx = 0;
    LogFlowFunc(("pvBuf=%#p cbRead=%d\n", pvBuf, cbRead));

    rc = drvHostParallelSetMode(pThis, enmMode);
    if (RT_FAILURE(rc))
        return rc;

    if (enmMode == PDM_PARALLEL_PORT_MODE_SPP)
    {
        /* Set the data lines directly. */
        rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWDATA, pvBuf);
    }
    else
    {
        /* Use write interface. */
        rcLnx = read(RTFileToNative(pThis->hFileDevice), pvBuf, cbRead);
    }
    if (RT_UNLIKELY(rcLnx < 0))
        rc = RTErrConvertFromErrno(errno);
# else  /* VBOX_WITH_WIN_PARPORT_SUP */
    if (pThis->fParportAvail)
    {
        *((uint8_t*)(pvBuf)) = 0; /* Initialize the buffer. */
        for (size_t i = 0; i < cbRead; i++)
        {
            LogFlowFunc(("calling R0 to read from parallel port\n"));
            int rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_READ, 0);
            AssertRC(rc);
            *((uint8_t *)pvBuf + i) = (uint8_t)pThis->u8ReadIn;
        }
    }
# endif /* VBOX_WITH_WIN_PARPORT_SUP */
    return rc;
}
/** @copydoc PDMICHARCONNECTOR::pfnWrite */
static DECLCALLBACK(int) drvHostParallelWrite(PPDMIHOSTPARALLELCONNECTOR pInterface, const void *pvBuf, size_t cbWrite, PDMPARALLELPORTMODE enmMode)
{
    PPDMDRVINS          pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    //PDRVHOSTPARALLEL    pThis   = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    PDRVHOSTPARALLEL    pThis   = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector));
    int rc = VINF_SUCCESS;
    int rcLnx = 0;

    LogFlowFunc(("pvBuf=%#p cbWrite=%d\n", pvBuf, cbWrite));

    rc = drvHostParallelSetMode(pThis, enmMode);
    if (RT_FAILURE(rc))
        return rc;
# ifndef VBOX_WITH_WIN_PARPORT_SUP
    if (enmMode == PDM_PARALLEL_PORT_MODE_SPP)
    {
        /* Set the data lines directly. */
        rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWDATA, pvBuf);
    }
    else
    {
        /* Use write interface. */
        rcLnx = write(RTFileToNative(pThis->hFileDevice), pvBuf, cbWrite);
    }
    if (RT_UNLIKELY(rcLnx < 0))
        rc = RTErrConvertFromErrno(errno);
# else /* VBOX_WITH_WIN_PARPORT_SUP */
    if (pThis->fParportAvail)
    {
        for (size_t i = 0; i < cbWrite; i++)
        {
            uint64_t u64Data = (uint8_t) *((uint8_t *)(pvBuf) + i);
            LogFlowFunc(("calling R0 to write to parallel port, data=%#x\n", u64Data));
            rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_WRITE, u64Data);
            AssertRC(rc);
        }
    }
# endif /* VBOX_WITH_WIN_PARPORT_SUP */
    return rc;
}
Beispiel #7
0
RTDECL(int) RTSemRWDestroy(RTSEMRW hRWSem)
{
    /*
     * Validate input, nil handle is fine.
     */
    struct RTSEMRWINTERNAL *pThis = hRWSem;
    if (pThis == NIL_RTSEMRW)
        return VINF_SUCCESS;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
                    VERR_INVALID_HANDLE);
    Assert(pThis->Writer == (pthread_t)-1);
    Assert(!pThis->cReaders);
    Assert(!pThis->cWrites);
    Assert(!pThis->cWriterReads);

    /*
     * Try destroy it.
     */
    AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTSEMRW_MAGIC, RTSEMRW_MAGIC), VERR_INVALID_HANDLE);
    int rc = pthread_rwlock_destroy(&pThis->RWLock);
    if (!rc)
    {
#ifdef RTSEMRW_STRICT
        RTLockValidatorRecSharedDelete(&pThis->ValidatorRead);
        RTLockValidatorRecExclDelete(&pThis->ValidatorWrite);
#endif
        RTMemFree(pThis);
        rc = VINF_SUCCESS;
    }
    else
    {
        ASMAtomicWriteU32(&pThis->u32Magic, RTSEMRW_MAGIC);
        AssertMsgFailed(("Failed to destroy read-write sem %p, rc=%d.\n", hRWSem, rc));
        rc = RTErrConvertFromErrno(rc);
    }

    return rc;
}
/**
 * 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 */
}
Beispiel #9
0
RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
{
    /*
     * Validate.
     */
    AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);
    AssertMsgReturn(VALID_PTR(pProperties), ("%p", pProperties), VERR_INVALID_PARAMETER);

    /*
     * Convert the path and query the information.
     */
    char const *pszNativeFsPath;
    int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
    if (RT_SUCCESS(rc))
    {
        struct statvfs StatVFS;
        RT_ZERO(StatVFS);
        if (!statvfs(pszNativeFsPath, &StatVFS))
        {
            /*
             * Calc/fake the returned values.
             */
            pProperties->cbMaxComponent = StatVFS.f_namemax;
            pProperties->fCaseSensitive = true;
            pProperties->fCompressed = false;
            pProperties->fFileCompression = false;
            pProperties->fReadOnly = !!(StatVFS.f_flag & ST_RDONLY);
            pProperties->fRemote = false;
            pProperties->fSupportsUnicode = true;
        }
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativeFsPath, pszFsPath);
    }

    LogFlow(("RTFsQueryProperties(%p:{%s}, %p:{.cbMaxComponent=%u, .fCaseSensitive=%RTbool}): returns %Rrc\n",
             pszFsPath, pszFsPath, pProperties, pProperties->cbMaxComponent, pProperties->fReadOnly));
    return VINF_SUCCESS;
}
RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq)
{
    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED);

    ASMAtomicXchgBool(&pReqInt->fCanceled, true);

    int rcPosix = aio_cancel(pReqInt->AioCB.aio_fildes, &pReqInt->AioCB);

    if (rcPosix == AIO_CANCELED)
    {
        PRTFILEAIOCTXINTERNAL pCtxInt = pReqInt->pCtxInt;
        /*
         * Notify the waiting thread that the request was canceled.
         */
        AssertMsg(VALID_PTR(pCtxInt),
                  ("Invalid state. Request was canceled but wasn't submitted\n"));

        Assert(!pCtxInt->pReqToCancel);
        ASMAtomicWritePtr(&pCtxInt->pReqToCancel, pReqInt);
        rtFileAioCtxWakeup(pCtxInt);

        /* Wait for acknowledge. */
        int rc = RTSemEventWait(pCtxInt->SemEventCancel, RT_INDEFINITE_WAIT);
        AssertRC(rc);

        ASMAtomicWriteNullPtr(&pCtxInt->pReqToCancel);
        pReqInt->Rc = VERR_FILE_AIO_CANCELED;
        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
        return VINF_SUCCESS;
    }
    else if (rcPosix == AIO_ALLDONE)
        return VERR_FILE_AIO_COMPLETED;
    else if (rcPosix == AIO_NOTCANCELED)
        return VERR_FILE_AIO_IN_PROGRESS;
    else
        return RTErrConvertFromErrno(errno);
}
Beispiel #11
0
RTDECL(int) RTEnvSetBad(const char *pszVar, const char *pszValue)
{
    AssertMsgReturn(strchr(pszVar, '=') == NULL, ("'%s'\n", pszVar), VERR_ENV_INVALID_VAR_NAME);

    /* make a local copy and feed it to putenv. */
    const size_t cchVar = strlen(pszVar);
    const size_t cchValue = strlen(pszValue);
    char *pszTmp = (char *)alloca(cchVar + cchValue + 2 + !*pszValue);
    memcpy(pszTmp, pszVar, cchVar);
    pszTmp[cchVar] = '=';
    if (*pszValue)
        memcpy(pszTmp + cchVar + 1, pszValue, cchValue + 1);
    else
    {
        pszTmp[cchVar + 1] = ' '; /* wrong, but putenv will remove it otherwise. */
        pszTmp[cchVar + 2] = '\0';
    }

    if (!putenv(pszTmp))
        return 0;
    return RTErrConvertFromErrno(errno);
}
Beispiel #12
0
/**
 * interface_method_impl{SUPDRVTRACERREG,pfnProviderRegister}
 */
static DECLCALLBACK(int) vboxDtTOps_ProviderRegister(PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore)
{
    LOG_DTRACE(("%s: %p %s/%s\n", __FUNCTION__, pThis, pCore->pszModName, pCore->pszName));
    AssertReturn(pCore->TracerData.DTrace.idProvider == 0, VERR_INTERNAL_ERROR_3);

    PVTGDESCPROVIDER    pDesc = pCore->pDesc;
    dtrace_pattr_t      DtAttrs;
    vboxDtVtgConvAttr(&DtAttrs.dtpa_provider, &pDesc->AttrSelf);
    vboxDtVtgConvAttr(&DtAttrs.dtpa_mod,      &pDesc->AttrModules);
    vboxDtVtgConvAttr(&DtAttrs.dtpa_func,     &pDesc->AttrFunctions);
    vboxDtVtgConvAttr(&DtAttrs.dtpa_name,     &pDesc->AttrNames);
    vboxDtVtgConvAttr(&DtAttrs.dtpa_args,     &pDesc->AttrArguments);

    /* Note! DTrace may call us back before dtrace_register returns, so we
             have to point it to pCore->TracerData.DTrace.idProvider. */
    AssertCompile(sizeof(dtrace_provider_id_t) == sizeof(pCore->TracerData.DTrace.idProvider));
    int rc = dtrace_register(pCore->pszName,
                             &DtAttrs,
                             DTRACE_PRIV_KERNEL,
                             NULL /* cred */,
                             &g_vboxDtVtgProvOps,
                             pCore,
                             &pCore->TracerData.DTrace.idProvider);
    if (!rc)
    {
        LOG_DTRACE(("%s: idProvider=%p\n", __FUNCTION__, pCore->TracerData.DTrace.idProvider));
        AssertPtr(pCore->TracerData.DTrace.idProvider);
        rc = VINF_SUCCESS;
    }
    else
    {
        pCore->TracerData.DTrace.idProvider = 0;
        rc = RTErrConvertFromErrno(FIX_UEK_RC(rc));
    }

    LOG_DTRACE(("%s: returns %Rrc\n", __FUNCTION__, rc));
    return rc;
}
Beispiel #13
0
RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
{
    LogFlow(("RTThreadSleep: cMillies=%d\n", cMillies));
    if (!cMillies)
    {
        /* pthread_yield() isn't part of SuS, thus this fun. */
#ifdef RT_OS_DARWIN
        pthread_yield_np();
#elif defined(RT_OS_FREEBSD) /* void pthread_yield */
        pthread_yield();
#elif defined(RT_OS_SOLARIS) || defined(RT_OS_HAIKU)
        sched_yield();
#else
        if (!pthread_yield())
#endif
        {
            LogFlow(("RTThreadSleep: returning %Rrc (cMillies=%d)\n", VINF_SUCCESS, cMillies));
            return VINF_SUCCESS;
        }
    }
    else
    {
        struct timespec ts;
        struct timespec tsrem = {0,0};

        ts.tv_nsec = (cMillies % 1000) * 1000000;
        ts.tv_sec  = cMillies / 1000;
        if (!nanosleep(&ts, &tsrem))
        {
            LogFlow(("RTThreadSleep: returning %Rrc (cMillies=%d)\n", VINF_SUCCESS, cMillies));
            return VINF_SUCCESS;
        }
    }

    int rc = RTErrConvertFromErrno(errno);
    LogFlow(("RTThreadSleep: returning %Rrc (cMillies=%d)\n", rc, cMillies));
    return rc;
}
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;
}
DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread)
{
    /*
     * Default stack size.
     */
    if (!pThread->cbStack)
        pThread->cbStack = 512*1024;

    /*
     * Create the thread.
     */
    int iThreadId = _beginthread(rtThreadNativeMain, NULL, pThread->cbStack, pThread);
    if (iThreadId > 0)
    {
#ifdef fibGetTidPid
        *pNativeThread = iThreadId | (fibGetPid() << 16);
#else
        *pNativeThread = iThreadId;
#endif
        return VINF_SUCCESS;
    }
    return RTErrConvertFromErrno(errno);
}
/**
 * @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;
}
Beispiel #18
0
RTDECL(int) RTEnvSetUtf8(const char *pszVar, const char *pszValue)
{
    AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME);

    size_t cwcVar;
    int rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcVar);
    if (RT_SUCCESS(rc))
    {
        size_t cwcValue;
        rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcValue);
        if (RT_SUCCESS(rc))
        {
            PRTUTF16 pwszTmp = (PRTUTF16)RTMemTmpAlloc((cwcVar + 1 + cwcValue + 1) * sizeof(RTUTF16));
            if (pwszTmp)
            {
                rc = RTStrToUtf16Ex(pszVar, RTSTR_MAX, &pwszTmp, cwcVar + 1, NULL);
                if (RT_SUCCESS(rc))
                {
                    PRTUTF16 pwszTmpValue = &pwszTmp[cwcVar];
                    *pwszTmpValue++ = '=';
                    rc = RTStrToUtf16Ex(pszValue, RTSTR_MAX, &pwszTmpValue, cwcValue + 1, NULL);
                    if (RT_SUCCESS(rc))
                    {
                        if (!_wputenv(pwszTmp))
                            rc = VINF_SUCCESS;
                        else
                            rc = RTErrConvertFromErrno(errno);
                    }
                }
                RTMemTmpFree(pwszTmp);
            }
            else
                rc = VERR_NO_TMP_MEMORY;
        }
    }
    return rc;
}
Beispiel #19
0
int vboxNetAdpOsCreate(PVBOXNETADP pThis, PCRTMAC pMACAddress)
{
    int rc = VINF_SUCCESS;
    struct net_device *pNetDev;

    /* No need for private data. */
    pNetDev = alloc_netdev(sizeof(VBOXNETADPPRIV),
                           pThis->szName[0] ? pThis->szName : VBOXNETADP_LINUX_NAME,
                           vboxNetAdpNetDevInit);
    if (pNetDev)
    {
        int err;

        if (pNetDev->dev_addr)
        {
            memcpy(pNetDev->dev_addr, pMACAddress, ETH_ALEN);
            Log2(("vboxNetAdpOsCreate: pNetDev->dev_addr = %.6Rhxd\n", pNetDev->dev_addr));
            err = register_netdev(pNetDev);
            if (!err)
            {
                strncpy(pThis->szName, pNetDev->name, sizeof(pThis->szName));
                pThis->szName[sizeof(pThis->szName) - 1] = '\0';
                pThis->u.s.pNetDev = pNetDev;
                Log2(("vboxNetAdpOsCreate: pThis=%p pThis->szName = %p\n", pThis, pThis->szName));
                return VINF_SUCCESS;
            }
        }
        else
        {
            LogRel(("VBoxNetAdp: failed to set MAC address (dev->dev_addr == NULL)\n"));
            err = EFAULT;
        }
        free_netdev(pNetDev);
        rc = RTErrConvertFromErrno(err);
    }
    return rc;
}
RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
{
    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    AssertPtrReturn(phKrnlModInfo, VERR_INVALID_POINTER);

    int rc = VERR_NOT_FOUND;
    int iId = -1;
    struct modinfo ModInfo;

    ModInfo.mi_info   = MI_INFO_ALL | MI_INFO_CNT;
    ModInfo.mi_id     = iId;
    ModInfo.mi_nextid = iId;
    do
    {
        int rcSol = modctl(MODINFO, iId, &ModInfo);
        if (rcSol < 0)
        {
            rc = RTErrConvertFromErrno(errno);
            break;
        }

        if (ModInfo.mi_id != -1)
        {
            ModInfo.mi_name[MODMAXNAMELEN - 1] = '\0'; /* Paranoia. */
            if (!RTStrCmp(pszName, &ModInfo.mi_name[0]))
            {
                rc = rtKrnlModSolInfoCreate(&ModInfo, phKrnlModInfo);
                break;
            }
        }

        iId = ModInfo.mi_id;
    } while (iId != -1);

    return rc;
}
Beispiel #21
0
RTDECL(int) RTSymlinkCreate(const char *pszSymlink, const char *pszTarget, RTSYMLINKTYPE enmType, uint32_t fCreate)
{
    /*
     * Validate the input.
     */
    AssertReturn(enmType > RTSYMLINKTYPE_INVALID && enmType < RTSYMLINKTYPE_END, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszSymlink, VERR_INVALID_POINTER);
    AssertPtrReturn(pszTarget, VERR_INVALID_POINTER);

    /*
     * Convert the paths.
     */
    char const *pszNativeSymlink;
    int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
    if (RT_SUCCESS(rc))
    {
        const char *pszNativeTarget;
        rc = rtPathToNative(&pszNativeTarget, pszTarget, NULL);
        if (RT_SUCCESS(rc))
        {
            /*
             * Create the link.
             */
            if (symlink(pszNativeTarget, pszNativeSymlink) == 0)
                rc = VINF_SUCCESS;
            else
                rc = RTErrConvertFromErrno(errno);

            rtPathFreeNative(pszNativeTarget, pszTarget);
        }
        rtPathFreeNative(pszNativeSymlink, pszSymlink);
    }

    LogFlow(("RTSymlinkCreate(%p={%s}, %p={%s}, %d, %#x): returns %Rrc\n", pszSymlink, pszSymlink, pszTarget, pszTarget, enmType, fCreate, rc));
    return rc;
}
Beispiel #22
0
RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable)
{
    RTPIPEINTERNAL *pThis = hPipe;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
    AssertReturn(pThis->fRead, VERR_PIPE_NOT_READ);
    AssertPtrReturn(pcbReadable, VERR_INVALID_POINTER);

    int cb = 0;
    int rc = ioctl(pThis->fd, FIONREAD, &cb);
    if (rc != -1)
    {
        AssertStmt(cb >= 0, cb = 0);
        *pcbReadable = cb;
        return VINF_SUCCESS;
    }

    rc = errno;
    if (rc == ENOTTY)
        rc = VERR_NOT_SUPPORTED;
    else
        rc = RTErrConvertFromErrno(rc);
    return rc;
}
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;
}
Beispiel #24
0
DECL_FORCE_INLINE(int) rtSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMillies, bool fAutoResume, PCRTLOCKVALSRCPOS pSrcPos)
{
    /*
     * Validate input.
     */
    struct RTSEMMUTEXINTERNAL *pThis = hMutexSem;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);

    /*
     * Check if nested request.
     */
    pthread_t Self = pthread_self();
    if (    pThis->Owner == Self
            &&  pThis->cNestings > 0)
    {
#ifdef RTSEMMUTEX_STRICT
        int rc9 = RTLockValidatorRecExclRecursion(&pThis->ValidatorRec, pSrcPos);
        if (RT_FAILURE(rc9))
            return rc9;
#endif
        ASMAtomicIncU32(&pThis->cNestings);
        return VINF_SUCCESS;
    }

#ifdef RTSEMMUTEX_STRICT
    RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
    if (cMillies)
    {
        int rc9 = RTLockValidatorRecExclCheckOrder(&pThis->ValidatorRec, hThreadSelf, pSrcPos, cMillies);
        if (RT_FAILURE(rc9))
            return rc9;
    }
#else
    RTTHREAD hThreadSelf = RTThreadSelf();
#endif

    /*
     * Convert timeout value.
     */
    struct timespec ts;
    struct timespec *pTimeout = NULL;
    uint64_t u64End = 0; /* shut up gcc */
    if (cMillies != RT_INDEFINITE_WAIT)
    {
        ts.tv_sec  = cMillies / 1000;
        ts.tv_nsec = (cMillies % 1000) * UINT32_C(1000000);
        u64End = RTTimeSystemNanoTS() + cMillies * UINT64_C(1000000);
        pTimeout = &ts;
    }

    /*
     * Lock the mutex.
     * Optimize for the uncontended case (makes 1-2 ns difference).
     */
    if (RT_UNLIKELY(!ASMAtomicCmpXchgS32(&pThis->iState, 1, 0)))
    {
        for (;;)
        {
            int32_t iOld = ASMAtomicXchgS32(&pThis->iState, 2);

            /*
             * Was the lock released in the meantime? This is unlikely (but possible)
             */
            if (RT_UNLIKELY(iOld == 0))
                break;

            /*
             * Go to sleep.
             */
            if (pTimeout && ( pTimeout->tv_sec || pTimeout->tv_nsec ))
            {
#ifdef RTSEMMUTEX_STRICT
                int rc9 = RTLockValidatorRecExclCheckBlocking(&pThis->ValidatorRec, hThreadSelf, pSrcPos, true,
                          cMillies, RTTHREADSTATE_MUTEX, true);
                if (RT_FAILURE(rc9))
                    return rc9;
#else
                RTThreadBlocking(hThreadSelf, RTTHREADSTATE_MUTEX, true);
#endif
            }

            long rc = sys_futex(&pThis->iState, FUTEX_WAIT, 2, pTimeout, NULL, 0);

            RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_MUTEX);
            if (RT_UNLIKELY(pThis->u32Magic != RTSEMMUTEX_MAGIC))
                return VERR_SEM_DESTROYED;

            /*
             * Act on the wakup code.
             */
            if (rc == -ETIMEDOUT)
            {
                Assert(pTimeout);
                return VERR_TIMEOUT;
            }
            if (rc == 0)
                /* we'll leave the loop now unless another thread is faster */;
            else if (rc == -EWOULDBLOCK)
                /* retry with new value. */;
            else if (rc == -EINTR)
            {
                if (!fAutoResume)
                    return VERR_INTERRUPTED;
            }
            else
            {
                /* this shouldn't happen! */
                AssertMsgFailed(("rc=%ld errno=%d\n", rc, errno));
                return RTErrConvertFromErrno(rc);
            }

            /* adjust the relative timeout */
            if (pTimeout)
            {
                int64_t i64Diff = u64End - RTTimeSystemNanoTS();
                if (i64Diff < 1000)
                {
                    rc = VERR_TIMEOUT;
                    break;
                }
                ts.tv_sec  = (uint64_t)i64Diff / UINT32_C(1000000000);
                ts.tv_nsec = (uint64_t)i64Diff % UINT32_C(1000000000);
            }
        }

        /*
         * When leaving this loop, iState is set to 2. This means that we gained the
         * lock and there are _possibly_ some waiters. We don't know exactly as another
         * thread might entered this loop at nearly the same time. Therefore we will
         * call futex_wakeup once too often (if _no_ other thread entered this loop).
         * The key problem is the simple futex_wait test for x != y (iState != 2) in
         * our case).
         */
    }

    /*
     * Set the owner and nesting.
     */
    pThis->Owner = Self;
    ASMAtomicWriteU32(&pThis->cNestings, 1);
#ifdef RTSEMMUTEX_STRICT
    RTLockValidatorRecExclSetOwner(&pThis->ValidatorRec, hThreadSelf, pSrcPos, true);
#endif
    return VINF_SUCCESS;
}
/**
 * Daemonize the process for running in the background.
 *
 * This is supposed to do the same job as the BSD daemon() call.
 *
 * @returns 0 on success
 *
 * @param   fNoChDir    Pass false to change working directory to root.
 * @param   fNoClose    Pass false to redirect standard file streams to /dev/null.
 * @param   fRespawn    Restart the daemonised process after five seconds if it
 *                      terminates abnormally.
 * @param   pcRespawn   Where to store a count of how often we have respawned,
 *                      intended for avoiding error spamming.  Optional.
 *
 * @todo    Use RTProcDaemonize instead of this.
 * @todo    Implement fRespawn on OS/2.
 * @todo    Make the respawn interval configurable.  But not until someone
 *          actually needs that.
 */
VBGLR3DECL(int) VbglR3Daemonize(bool fNoChDir, bool fNoClose, bool fRespawn, unsigned *pcRespawn)
{
#if defined(RT_OS_OS2)
    PPIB pPib;
    PTIB pTib;
    DosGetInfoBlocks(&pTib, &pPib);

    AssertRelease(!fRespawn);
    /* Get the full path to the executable. */
    char szExe[CCHMAXPATH];
    APIRET rc = DosQueryModuleName(pPib->pib_hmte, sizeof(szExe), szExe);
    if (rc)
        return RTErrConvertFromOS2(rc);

    /* calc the length of the command line. */
    char *pch = pPib->pib_pchcmd;
    size_t cch0 = strlen(pch);
    pch += cch0 + 1;
    size_t cch1 = strlen(pch);
    pch += cch1 + 1;
    char *pchArgs;
    if (cch1 && *pch)
    {
        do  pch = strchr(pch, '\0') + 1;
        while (*pch);

        size_t cchTotal = pch - pPib->pib_pchcmd;
        pchArgs = (char *)alloca(cchTotal + sizeof("--daemonized\0\0"));
        memcpy(pchArgs, pPib->pib_pchcmd, cchTotal - 1);
        memcpy(pchArgs + cchTotal - 1, "--daemonized\0\0", sizeof("--daemonized\0\0"));
    }
    else
    {
        size_t cchTotal = pch - pPib->pib_pchcmd + 1;
        pchArgs = (char *)alloca(cchTotal + sizeof(" --daemonized "));
        memcpy(pchArgs, pPib->pib_pchcmd, cch0 + 1);
        pch = pchArgs + cch0 + 1;
        memcpy(pch, " --daemonized ", sizeof(" --daemonized ") - 1);
        pch += sizeof(" --daemonized ") - 1;
        if (cch1)
            memcpy(pch, pPib->pib_pchcmd + cch0 + 1, cch1 + 2);
        else
            pch[0] = pch[1] = '\0';
    }

    /* spawn a detach process  */
    char szObj[128];
    RESULTCODES ResCodes = { 0, 0 };
    szObj[0] = '\0';
    rc = DosExecPgm(szObj, sizeof(szObj), EXEC_BACKGROUND, (PCSZ)pchArgs, NULL, &ResCodes, (PCSZ)szExe);
    if (rc)
    {
        /** @todo Change this to some standard log/print error?? */
        /* VBoxServiceError("DosExecPgm failed with rc=%d and szObj='%s'\n", rc, szObj); */
        return RTErrConvertFromOS2(rc);
    }
    DosExit(EXIT_PROCESS, 0);
    return VERR_GENERAL_FAILURE;

#elif defined(RT_OS_WINDOWS)
# error "PORTME"

#else /* the unices */
    /*
     * Fork the child process in a new session and quit the parent.
     *
     * - fork once and create a new session (setsid). This will detach us
     *   from the controlling tty meaning that we won't receive the SIGHUP
     *   (or any other signal) sent to that session.
     * - The SIGHUP signal is ignored because the session/parent may throw
     *   us one before we get to the setsid.
     * - When the parent exit(0) we will become an orphan and re-parented to
     *   the init process.
     * - Because of the Linux / System V semantics of assigning the controlling
     *   tty automagically when a session leader first opens a tty, we will
     *   fork() once more on Linux to get rid of the session leadership role.
     */

    struct sigaction OldSigAct;
    struct sigaction SigAct;
    RT_ZERO(SigAct);
    SigAct.sa_handler = SIG_IGN;
    int rcSigAct = sigaction(SIGHUP, &SigAct, &OldSigAct);

    pid_t pid = fork();
    if (pid == -1)
        return RTErrConvertFromErrno(errno);
    if (pid != 0)
        exit(0);

    /*
     * The orphaned child becomes is reparented to the init process.
     * We create a new session for it (setsid), point the standard
     * file descriptors to /dev/null, and change to the root directory.
     */
    pid_t newpgid = setsid();
    int SavedErrno = errno;
    if (rcSigAct != -1)
        sigaction(SIGHUP, &OldSigAct, NULL);
    if (newpgid == -1)
        return RTErrConvertFromErrno(SavedErrno);

    if (!fNoClose)
    {
        /* Open stdin(0), stdout(1) and stderr(2) as /dev/null. */
        int fd = open("/dev/null", O_RDWR);
        if (fd == -1) /* paranoia */
        {
            close(STDIN_FILENO);
            close(STDOUT_FILENO);
            close(STDERR_FILENO);
            fd = open("/dev/null", O_RDWR);
        }
        if (fd != -1)
        {
            dup2(fd, STDIN_FILENO);
            dup2(fd, STDOUT_FILENO);
            dup2(fd, STDERR_FILENO);
            if (fd > 2)
                close(fd);
        }
    }

    if (!fNoChDir)
        chdir("/");

    /*
     * Change the umask - this is non-standard daemon() behavior.
     */
    umask(027);

# ifdef RT_OS_LINUX
    /*
     * And fork again to lose session leader status (non-standard daemon()
     * behaviour).
     */
    pid = fork();
    if (pid == -1)
        return RTErrConvertFromErrno(errno);
    if (pid != 0)
        exit(0);
# endif /* RT_OS_LINUX */

    if (fRespawn)
    {
        /* We implement re-spawning as a third fork(), with the parent process
         * monitoring the child and re-starting it after a delay if it exits
         * abnormally. */
        unsigned cRespawn = 0;
        for (;;)
        {
            int iStatus, rcWait;

            if (pcRespawn != NULL)
                *pcRespawn = cRespawn;
            pid = fork();
            if (pid == -1)
                return RTErrConvertFromErrno(errno);
            if (pid == 0)
                return VINF_SUCCESS;
            do
                rcWait = waitpid(pid, &iStatus, 0);
            while (rcWait == -1 && errno == EINTR);
            if (rcWait == -1)
                exit(1);
            if (WIFEXITED(iStatus) && WEXITSTATUS(iStatus) == 0)
                exit(0);
            sleep(5);
            ++cRespawn;
        }
    }
    return VINF_SUCCESS;
#endif
}
/**
 * Run once function that initializes the kstats we need here.
 *
 * @returns IPRT status code.
 * @param   pvUser      Unused.
 */
static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser)
{
    int rc = VINF_SUCCESS;
    NOREF(pvUser);

    /*
     * Open kstat and find the cpu_info entries for each of the CPUs.
     */
    g_pKsCtl = kstat_open();
    if (g_pKsCtl)
    {
        g_capCpuInfo = RTMpGetCount();
        g_papCpuInfo = (kstat_t **)RTMemAllocZ(g_capCpuInfo * sizeof(kstat_t *));
        if (g_papCpuInfo)
        {
            g_cu64CoreIds = g_capCpuInfo;
            g_pu64CoreIds = (uint64_t *)RTMemAllocZ(g_cu64CoreIds * sizeof(uint64_t));
            if (g_pu64CoreIds)
            {
                rc = RTCritSectInit(&g_MpSolarisCritSect);
                if (RT_SUCCESS(rc))
                {
                    RTCPUID i = 0;
                    for (kstat_t *pKsp = g_pKsCtl->kc_chain; pKsp != NULL; pKsp = pKsp->ks_next)
                    {
                        if (!RTStrCmp(pKsp->ks_module, "cpu_info"))
                        {
                            AssertBreak(i < g_capCpuInfo);
                            g_papCpuInfo[i++] = pKsp;
                            /** @todo ks_instance == cpu_id (/usr/src/uts/common/os/cpu.c)? Check this and fix it ASAP. */
                        }
                    }

                    rc = rtMpSolarisGetCoreIds();
                    if (RT_SUCCESS(rc))
                        return VINF_SUCCESS;
                    else
                        Log(("rtMpSolarisGetCoreIds failed. rc=%Rrc\n", rc));
                }

                RTMemFree(g_pu64CoreIds);
                g_pu64CoreIds = NULL;
            }
            else
                rc = VERR_NO_MEMORY;

            /* bail out, we failed. */
            RTMemFree(g_papCpuInfo);
            g_papCpuInfo = NULL;
        }
        else
            rc = VERR_NO_MEMORY;
        kstat_close(g_pKsCtl);
        g_pKsCtl = NULL;
    }
    else
    {
        rc = RTErrConvertFromErrno(errno);
        if (RT_SUCCESS(rc))
            rc = VERR_INTERNAL_ERROR;
        Log(("kstat_open() -> %d (%Rrc)\n", errno, rc));
    }

    return rc;
}
Beispiel #27
0
RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags,
                            RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
{
    AssertReturn(!(fFlags & ~RTSEMRW_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);

    /*
     * Allocate handle.
     */
    int rc;
    struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL));
    if (pThis)
    {
        /*
         * Create the rwlock.
         */
        pthread_rwlockattr_t Attr;
        rc = pthread_rwlockattr_init(&Attr);
        if (!rc)
        {
            rc = pthread_rwlock_init(&pThis->RWLock, &Attr);
            if (!rc)
            {
                pThis->u32Magic     = RTSEMRW_MAGIC;
                pThis->cReaders     = 0;
                pThis->cWrites      = 0;
                pThis->cWriterReads = 0;
                pThis->Writer       = (pthread_t)-1;
#ifdef RTSEMRW_STRICT
                bool const fLVEnabled = !(fFlags & RTSEMRW_FLAGS_NO_LOCK_VAL);
                if (!pszNameFmt)
                {
                    static uint32_t volatile s_iSemRWAnon = 0;
                    uint32_t i = ASMAtomicIncU32(&s_iSemRWAnon) - 1;
                    RTLockValidatorRecExclInit(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                               fLVEnabled, "RTSemRW-%u", i);
                    RTLockValidatorRecSharedInit(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                                 false /*fSignaller*/, fLVEnabled, "RTSemRW-%u", i);
                }
                else
                {
                    va_list va;
                    va_start(va, pszNameFmt);
                    RTLockValidatorRecExclInitV(&pThis->ValidatorWrite, hClass, uSubClass, pThis,
                                                fLVEnabled, pszNameFmt, va);
                    va_end(va);
                    va_start(va, pszNameFmt);
                    RTLockValidatorRecSharedInitV(&pThis->ValidatorRead, hClass, uSubClass, pThis,
                                                  false /*fSignaller*/, fLVEnabled, pszNameFmt, va);
                    va_end(va);
                }
                RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core);
#endif
                *phRWSem = pThis;
                return VINF_SUCCESS;
            }
        }

        rc = RTErrConvertFromErrno(rc);
        RTMemFree(pThis);
    }
    else
        rc = VERR_NO_MEMORY;

    return rc;
}
Beispiel #28
0
DECL_FORCE_INLINE(int) rtSemRWRequestWrite(RTSEMRW hRWSem, RTMSINTERVAL cMillies, PCRTLOCKVALSRCPOS pSrcPos)
{
    /*
     * Validate input.
     */
    struct RTSEMRWINTERNAL *pThis = hRWSem;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertMsgReturn(pThis->u32Magic == RTSEMRW_MAGIC,
                    ("pThis=%p u32Magic=%#x\n", pThis, pThis->u32Magic),
                    VERR_INVALID_HANDLE);

    /*
     * Recursion?
     */
    pthread_t Self = pthread_self();
    pthread_t Writer;
    ATOMIC_GET_PTHREAD_T(&pThis->Writer, &Writer);
    if (Writer == Self)
    {
#ifdef RTSEMRW_STRICT
        int rc9 = RTLockValidatorRecExclRecursion(&pThis->ValidatorWrite, pSrcPos);
        if (RT_FAILURE(rc9))
            return rc9;
#endif
        Assert(pThis->cWrites < INT32_MAX);
        pThis->cWrites++;
        return VINF_SUCCESS;
    }

    /*
     * Try lock it.
     */
    RTTHREAD hThreadSelf = NIL_RTTHREAD;
    if (cMillies)
    {
#ifdef RTSEMRW_STRICT
        hThreadSelf = RTThreadSelfAutoAdopt();
        int rc9 = RTLockValidatorRecExclCheckOrderAndBlocking(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true,
                                                              cMillies, RTTHREADSTATE_RW_WRITE, true);
        if (RT_FAILURE(rc9))
            return rc9;
#else
        hThreadSelf = RTThreadSelf();
        RTThreadBlocking(hThreadSelf, RTTHREADSTATE_RW_WRITE, true);
#endif
    }

    if (cMillies == RT_INDEFINITE_WAIT)
    {
        /* take rwlock */
        int rc = pthread_rwlock_wrlock(&pThis->RWLock);
        RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
        if (rc)
        {
            AssertMsgFailed(("Failed write lock read-write sem %p, rc=%d.\n", hRWSem, rc));
            return RTErrConvertFromErrno(rc);
        }
    }
    else
    {
#ifdef RT_OS_DARWIN
        AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
        return VERR_NOT_IMPLEMENTED;
#else /* !RT_OS_DARWIN */
        /*
         * Get current time and calc end of wait time.
         */
        struct timespec     ts = {0,0};
        clock_gettime(CLOCK_REALTIME, &ts);
        if (cMillies != 0)
        {
            ts.tv_nsec += (cMillies % 1000) * 1000000;
            ts.tv_sec  += cMillies / 1000;
            if (ts.tv_nsec >= 1000000000)
            {
                ts.tv_nsec -= 1000000000;
                ts.tv_sec++;
            }
        }

        /* take rwlock */
        int rc = pthread_rwlock_timedwrlock(&pThis->RWLock, &ts);
        RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_RW_WRITE);
        if (rc)
        {
            AssertMsg(rc == ETIMEDOUT, ("Failed read lock read-write sem %p, rc=%d.\n", hRWSem, rc));
            return RTErrConvertFromErrno(rc);
        }
#endif /* !RT_OS_DARWIN */
    }

    ATOMIC_SET_PTHREAD_T(&pThis->Writer, Self);
    pThis->cWrites = 1;
    Assert(!pThis->cReaders);
#ifdef RTSEMRW_STRICT
    RTLockValidatorRecExclSetOwner(&pThis->ValidatorWrite, hThreadSelf, pSrcPos, true);
#endif
    return VINF_SUCCESS;
}
RTR3DECL(int)   RTProcDaemonizeUsingFork(bool fNoChDir, bool fNoClose, const char *pszPidfile)
{
    /*
     * Fork the child process in a new session and quit the parent.
     *
     * - fork once and create a new session (setsid). This will detach us
     *   from the controlling tty meaning that we won't receive the SIGHUP
     *   (or any other signal) sent to that session.
     * - The SIGHUP signal is ignored because the session/parent may throw
     *   us one before we get to the setsid.
     * - When the parent exit(0) we will become an orphan and re-parented to
     *   the init process.
     * - Because of the sometimes unexpected semantics of assigning the
     *   controlling tty automagically when a session leader first opens a tty,
     *   we will fork() once more to get rid of the session leadership role.
     */

    /* We start off by opening the pidfile, so that we can fail straight away
     * if it already exists. */
    int fdPidfile = -1;
    if (pszPidfile != NULL)
    {
        /* @note the exclusive create is not guaranteed on all file
         * systems (e.g. NFSv2) */
        if ((fdPidfile = open(pszPidfile, O_RDWR | O_CREAT | O_EXCL, 0644)) == -1)
            return RTErrConvertFromErrno(errno);
    }

    /* Ignore SIGHUP straight away. */
    struct sigaction OldSigAct;
    struct sigaction SigAct;
    memset(&SigAct, 0, sizeof(SigAct));
    SigAct.sa_handler = SIG_IGN;
    int rcSigAct = sigaction(SIGHUP, &SigAct, &OldSigAct);

    /* First fork, to become independent process. */
    pid_t pid = fork();
    if (pid == -1)
    {
        if (fdPidfile != -1)
            close(fdPidfile);
        return RTErrConvertFromErrno(errno);
    }
    if (pid != 0)
    {
        /* Parent exits, no longer necessary. The child gets reparented
         * to the init process. */
        exit(0);
    }

    /* Create new session, fix up the standard file descriptors and the
     * current working directory. */
    /** @todo r=klaus the webservice uses this function and assumes that the
     * contract id of the daemon is the same as that of the original process.
     * Whenever this code is changed this must still remain possible. */
    pid_t newpgid = setsid();
    int SavedErrno = errno;
    if (rcSigAct != -1)
        sigaction(SIGHUP, &OldSigAct, NULL);
    if (newpgid == -1)
    {
        if (fdPidfile != -1)
            close(fdPidfile);
        return RTErrConvertFromErrno(SavedErrno);
    }

    if (!fNoClose)
    {
        /* Open stdin(0), stdout(1) and stderr(2) as /dev/null. */
        int fd = open("/dev/null", O_RDWR);
        if (fd == -1) /* paranoia */
        {
            close(STDIN_FILENO);
            close(STDOUT_FILENO);
            close(STDERR_FILENO);
            fd = open("/dev/null", O_RDWR);
        }
        if (fd != -1)
        {
            dup2(fd, STDIN_FILENO);
            dup2(fd, STDOUT_FILENO);
            dup2(fd, STDERR_FILENO);
            if (fd > 2)
                close(fd);
        }
    }

    if (!fNoChDir)
    {
        int rcIgnored = chdir("/");
        NOREF(rcIgnored);
    }

    /* Second fork to lose session leader status. */
    pid = fork();
    if (pid == -1)
    {
        if (fdPidfile != -1)
            close(fdPidfile);
        return RTErrConvertFromErrno(errno);
    }

    if (pid != 0)
    {
        /* Write the pid file, this is done in the parent, before exiting. */
        if (fdPidfile != -1)
        {
            char szBuf[256];
            size_t cbPid = RTStrPrintf(szBuf, sizeof(szBuf), "%d\n", pid);
            ssize_t cbIgnored = write(fdPidfile, szBuf, cbPid); NOREF(cbIgnored);
            close(fdPidfile);
        }
        exit(0);
    }

    if (fdPidfile != -1)
        close(fdPidfile);

    return VINF_SUCCESS;
}
Beispiel #30
0
RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType)
{
    *penmType = RTFSTYPE_UNKNOWN;

    /*
     * Validate input.
     */
    AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
    AssertReturn(*pszFsPath, VERR_INVALID_PARAMETER);

    /*
     * Convert the path and query the stats.
     * We're simply return the device id.
     */
    char const *pszNativeFsPath;
    int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat Stat;
        if (!stat(pszNativeFsPath, &Stat))
        {
#if defined(RT_OS_LINUX)
            FILE *mounted = setmntent("/proc/mounts", "r");
            if (!mounted)
                mounted = setmntent("/etc/mtab", "r");
            if (mounted)
            {
                char            szBuf[1024];
                struct stat     mntStat;
                struct mntent   mntEnt;
                while (getmntent_r(mounted, &mntEnt, szBuf, sizeof(szBuf)))
                {
                    if (!stat(mntEnt.mnt_dir, &mntStat))
                    {
                        if (mntStat.st_dev == Stat.st_dev)
                        {
                            if (!strcmp("ext4", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_EXT4;
                            else if (!strcmp("ext3", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_EXT3;
                            else if (!strcmp("ext2", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_EXT2;
                            else if (!strcmp("jfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_JFS;
                            else if (!strcmp("xfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_XFS;
                            else if (   !strcmp("vfat", mntEnt.mnt_type)
                                     || !strcmp("msdos", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_FAT;
                            else if (!strcmp("ntfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_NTFS;
                            else if (!strcmp("hpfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_HPFS;
                            else if (!strcmp("ufs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_UFS;
                            else if (!strcmp("tmpfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_TMPFS;
                            else if (!strcmp("hfsplus", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_HFS;
                            else if (!strcmp("udf", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_UDF;
                            else if (!strcmp("iso9660", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_ISO9660;
                            else if (!strcmp("smbfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_SMBFS;
                            else if (!strcmp("cifs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_CIFS;
                            else if (!strcmp("nfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_NFS;
                            else if (!strcmp("nfs4", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_NFS;
                            else if (!strcmp("sysfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_SYSFS;
                            else if (!strcmp("proc", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_PROC;
                            else if (   !strcmp("fuse", mntEnt.mnt_type)
                                     || !strncmp("fuse.", mntEnt.mnt_type, 5)
                                     || !strcmp("fuseblk", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_FUSE;
                            else
                            {
                                /* sometimes there are more than one entry for the same partition */
                                continue;
                            }
                            break;
                        }
                    }
                }
                endmntent(mounted);
            }

#elif defined(RT_OS_SOLARIS)
            if (!strcmp("zfs", Stat.st_fstype))
                *penmType = RTFSTYPE_ZFS;
            else if (!strcmp("ufs", Stat.st_fstype))
                *penmType = RTFSTYPE_UFS;
            else if (!strcmp("nfs", Stat.st_fstype))
                *penmType = RTFSTYPE_NFS;

#elif defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
            struct statfs statfsBuf;
            if (!statfs(pszNativeFsPath, &statfsBuf))
            {
                if (!strcmp("hfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_HFS;
                else if (   !strcmp("fat", statfsBuf.f_fstypename)
                         || !strcmp("msdos", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_FAT;
                else if (!strcmp("ntfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_NTFS;
                else if (!strcmp("autofs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_AUTOFS;
                else if (!strcmp("devfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_DEVFS;
                else if (!strcmp("nfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_NFS;
                else if (!strcmp("ufs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_UFS;
                else if (!strcmp("zfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_ZFS;
            }
            else
                rc = RTErrConvertFromErrno(errno);
#endif
        }
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativeFsPath, pszFsPath);
    }

    return rc;
}