/** * 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; }
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; }
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; }