/**
 * Queries information about the object using a specific view, internal version.
 *
 * @return  IPRT status code.
 * @param   enmView             View to use for querying information. Currently ignored.
 */
int DnDURIObject::queryInfoInternal(View enmView)
{
    RT_NOREF(enmView);

    int rc;

    switch (m_enmType)
    {
        case Type_File:
            AssertMsgReturn(RTFileIsValid(u.File.hFile), ("Object has invalid file handle\n"), VERR_INVALID_STATE);
            rc = RTFileQueryInfo(u.File.hFile, &u.File.objInfo, RTFSOBJATTRADD_NOTHING);
            break;

        case Type_Directory:
            AssertMsgReturn(RTDirIsValid(u.Dir.hDir), ("Object has invalid directory handle\n"), VERR_INVALID_STATE);
            rc = RTDirQueryInfo(u.Dir.hDir, &u.Dir.objInfo, RTFSOBJATTRADD_NOTHING);
            break;

        default:
            rc = VERR_NOT_IMPLEMENTED;
            break;
    }

    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;
}
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;
}
int DnDURIObject::OpenEx(const RTCString &strPath, Type enmType, Dest enmDest,
                         uint64_t fOpen /* = 0 */, uint32_t fMode /* = 0 */, uint32_t fFlags /* = 0 */)
{
    int rc = VINF_SUCCESS;

    switch (enmDest)
    {
        case Source:
            m_strSrcPath = strPath;
            break;

        case Target:
            m_strTgtPath = strPath;
            break;

        default:
            rc = VERR_NOT_IMPLEMENTED;
            break;
    }

    if (   RT_SUCCESS(rc)
        && fOpen) /* Opening mode specified? */
    {
        switch (enmType)
        {
            case File:
            {
                if (!u.m_hFile)
                {
                    /*
                     * Open files on the source with RTFILE_O_DENY_WRITE to prevent races
                     * where the OS writes to the file while the destination side transfers
                     * it over.
                     */
                    rc = RTFileOpen(&u.m_hFile, strPath.c_str(), fOpen);
                    LogFlowThisFunc(("strPath=%s, fOpen=0x%x, enmType=%RU32, enmDest=%RU32, rc=%Rrc\n",
                                     strPath.c_str(), fOpen, enmType, enmDest, rc));
                    if (RT_SUCCESS(rc))
                        rc = RTFileGetSize(u.m_hFile, &m_cbSize);

                    if (RT_SUCCESS(rc))
                    {
                        if (   (fOpen & RTFILE_O_WRITE) /* Only set the file mode on write. */
                            &&  fMode                   /* Some file mode to set specified? */)
                        {
                            rc = RTFileSetMode(u.m_hFile, fMode);
                            if (RT_SUCCESS(rc))
                                m_fMode = fMode;
                        }
                        else if (fOpen & RTFILE_O_READ)
                        {
#if 0 /** @todo Enable this as soon as RTFileGetMode is implemented. */
                            rc = RTFileGetMode(u.m_hFile, &m_fMode);
#else
                            RTFSOBJINFO ObjInfo;
                            rc = RTFileQueryInfo(u.m_hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
                            if (RT_SUCCESS(rc))
                                m_fMode = ObjInfo.Attr.fMode;
#endif
                        }
                    }

                    if (RT_SUCCESS(rc))
                    {
                        LogFlowThisFunc(("cbSize=%RU64, fMode=0x%x\n", m_cbSize, m_fMode));
                        m_cbProcessed = 0;
                    }
                }
                else
                    rc = VINF_SUCCESS;

                break;
            }

            case Directory:
                rc = VINF_SUCCESS;
                break;

            default:
                rc = VERR_NOT_IMPLEMENTED;
                break;
        }
    }

    if (RT_SUCCESS(rc))
        m_Type = enmType;

    LogFlowFuncLeaveRC(rc);
    return rc;
}