/**
 * Open the object with a specific file type, and, depending on the type, specifying additional parameters.
 *
 * @return  IPRT status code.
 * @param   strPathAbs          Absolute path of the object (file / directory / ...).
 * @param   enmView             View of the object.
 * @param   fOpen               Open mode to use; only valid for file objects.
 * @param   fMode               File mode to use; only valid for file objects.
 * @param   fFlags              Additional DnD URI object flags.
 */
int DnDURIObject::OpenEx(const RTCString &strPathAbs, View enmView,
                         uint64_t fOpen /* = 0 */, RTFMODE fMode /* = 0 */, DNDURIOBJECTFLAGS fFlags /* = DNDURIOBJECT_FLAGS_NONE */)
{
    AssertReturn(!(fFlags & ~DNDURIOBJECT_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
    RT_NOREF1(fFlags);

    int rc = VINF_SUCCESS;

    switch (enmView)
    {
        case View_Source:
            m_strSrcPathAbs = strPathAbs;
            break;

        case View_Target:
            m_strTgtPathAbs = strPathAbs;
            break;

        default:
            rc = VERR_NOT_IMPLEMENTED;
            break;
    }

    if (   RT_SUCCESS(rc)
        && fOpen) /* Opening mode specified? */
    {
        LogFlowThisFunc(("strPath=%s, enmView=%RU32, fOpen=0x%x, fMode=0x%x, fFlags=0x%x\n",
                         strPathAbs.c_str(), enmView, fOpen, fMode, fFlags));
        switch (m_enmType)
        {
            case Type_File:
            {
                /*
                 * 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.
                 */
                LogFlowThisFunc(("Opening ...\n"));
                rc = RTFileOpen(&u.File.hFile, strPathAbs.c_str(), fOpen);
                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.File.hFile, fMode);
                    }
                    else if (fOpen & RTFILE_O_READ)
                    {
                        rc = queryInfoInternal(enmView);
                    }
                }

                if (RT_SUCCESS(rc))
                {
                    LogFlowThisFunc(("File cbObject=%RU64, fMode=0x%x\n",
                                     u.File.objInfo.cbObject, u.File.objInfo.Attr.fMode));
                    u.File.cbToProcess = u.File.objInfo.cbObject;
                    u.File.cbProcessed = 0;
                }

                break;
            }

            case Type_Directory:
            {
                rc = RTDirOpen(&u.Dir.hDir, strPathAbs.c_str());
                if (RT_SUCCESS(rc))
                    rc = queryInfoInternal(enmView);
                break;
            }

            default:
                rc = VERR_NOT_IMPLEMENTED;
                break;
        }
    }

    if (RT_SUCCESS(rc))
    {
        m_enmView = enmView;
    }

    LogFlowFuncLeaveRC(rc);
    return rc;
}
Пример #2
0
static int vbglR3DnDHGProcessURIMessages(uint32_t   uClientId,
                                         uint32_t  *puScreenId,
                                         char      *pszFormat,
                                         uint32_t   cbFormat,
                                         uint32_t  *pcbFormatRecv,
                                         void     **ppvData,
                                         uint32_t   cbData,
                                         size_t    *pcbDataRecv)
{
    /* Make a string list out of the uri data. */
    RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n");
    if (uriList.isEmpty())
        return VINF_SUCCESS;

    uint32_t cbTmpData = _1M * 10;
    void *pvTmpData = RTMemAlloc(cbTmpData);
    if (!pvTmpData)
        return VERR_NO_MEMORY;

    /* Create and query the drop target directory. */
    char pszDropDir[RTPATH_MAX];
    int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir));
    if (RT_FAILURE(rc))
    {
        RTMemFree(pvTmpData);
        return rc;
    }

    /* Patch the old drop data with the new drop directory, so the drop target
     * can find the files. */
    RTCList<RTCString> guestUriList;
    for (size_t i = 0; i < uriList.size(); ++i)
    {
        const RTCString &strUri = uriList.at(i);
        /* Query the path component of a file URI. If this hasn't a
         * file scheme, null is returned. */
        if (char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO))
        {
            RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath);
            char *pszNewUri = RTUriFileCreate(strFullPath.c_str());
            if (pszNewUri)
            {
                guestUriList.append(pszNewUri);
                RTStrFree(pszNewUri);
            }
        }
        else
            guestUriList.append(strUri);
    }

    /* Cleanup the old data and write the new data back to the event. */
    RTMemFree(*ppvData);
    RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n";
    *ppvData = RTStrDupN(newData.c_str(), newData.length());
    *pcbDataRecv = newData.length() + 1;

    /* Lists for holding created files & directories in the case of a
     * rollback. */
    RTCList<RTCString> guestDirList;
    RTCList<RTCString> guestFileList;
    char pszPathname[RTPATH_MAX];
    uint32_t cbPathname = 0;
    bool fLoop = true;
    do
    {
        uint32_t uNextMsg;
        uint32_t cNextParms;
        rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false);
        DO(("%Rrc - %d\n", rc , uNextMsg));
        if (RT_SUCCESS(rc))
        {
            switch(uNextMsg)
            {
                case DragAndDropSvc::HOST_DND_HG_SND_DIR:
                {
                    uint32_t fMode = 0;
                    rc = vbglR3DnDHGProcessSendDirMessage(uClientId,
                                                          pszPathname,
                                                          sizeof(pszPathname),
                                                          &cbPathname,
                                                          &fMode);
                    if (RT_SUCCESS(rc))
                    {
                        DO(("Got drop dir: %s - %o - %Rrc\n", pszPathname, fMode, rc));
                        char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname);
                        rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0);
                        if (!guestDirList.contains(pszNewDir))
                            guestDirList.append(pszNewDir);
                    }
                    break;
                }
                case DragAndDropSvc::HOST_DND_HG_SND_FILE:
                {
                    uint32_t cbDataRecv;
                    uint32_t fMode = 0;
                    rc = vbglR3DnDHGProcessSendFileMessage(uClientId,
                                                           pszPathname,
                                                           sizeof(pszPathname),
                                                           &cbPathname,
                                                           pvTmpData,
                                                           cbTmpData,
                                                           &cbDataRecv,
                                                           &fMode);
                    if (RT_SUCCESS(rc))
                    {
                        char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname);
                        DO(("Got drop file: %s - %d - %o - %Rrc\n", pszPathname, cbDataRecv, fMode, rc));
                        RTFILE hFile;
                        rc = RTFileOpen(&hFile, pszNewFile, RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE);
                        if (RT_SUCCESS(rc))
                        {
                            rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL);
                            if (RT_SUCCESS(rc))
                            {
                                rc = RTFileWrite(hFile, pvTmpData, cbDataRecv, 0);
                                /* Valid UNIX mode? */
                                if (   RT_SUCCESS(rc)
                                    && (fMode & RTFS_UNIX_MASK))
                                    rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
                            }
                            RTFileClose(hFile);
                            if (!guestFileList.contains(pszNewFile))
                                guestFileList.append(pszNewFile);
                        }
                    }
                    break;
                }
                case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:
                {
                    rc = vbglR3DnDHGProcessCancelMessage(uClientId);
                    if (RT_SUCCESS(rc))
                        rc = VERR_CANCELLED;
                    /* Break out of the loop. */
                }
                default: fLoop = false; break;
            }
        } else
        {
            if (rc == VERR_NO_DATA)
                rc = VINF_SUCCESS;
            break;
        }
    }while(fLoop);

    RTMemFree(pvTmpData);
    /* Cleanup on failure or if the user has canceled. */
    if (RT_FAILURE(rc))
    {
        /* Remove any stuff created. */
        for (size_t i = 0; i < guestFileList.size(); ++i)
            RTFileDelete(guestFileList.at(i).c_str());
        for (size_t i = 0; i < guestDirList.size(); ++i)
            RTDirRemove(guestDirList.at(i).c_str());
        RTDirRemove(pszDropDir);
    }

    return rc;
}
Пример #3
0
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;
}