VirtualBox

source: vbox/trunk/src/VBox/GuestHost/DragAndDrop/DnDURIObject.cpp@ 55556

Last change on this file since 55556 was 55556, checked in by vboxsync, 10 years ago

DnD: Rollback handling, bugfixes, cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1/* $Id: DnDURIObject.cpp 55556 2015-04-30 14:27:39Z vboxsync $ */
2/** @file
3 * DnD: URI object class. For handling creation/reading/writing to files and directories
4 * on host or guest side.
5 */
6
7/*
8 * Copyright (C) 2014-2015 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/******************************************************************************
20 * Header Files *
21 ******************************************************************************/
22
23#include <iprt/dir.h>
24#include <iprt/file.h>
25#include <iprt/fs.h>
26#include <iprt/path.h>
27#include <iprt/uri.h>
28
29#ifdef LOG_GROUP
30 #undef LOG_GROUP
31#endif
32#define LOG_GROUP LOG_GROUP_GUEST_DND
33#include <VBox/log.h>
34
35#include <VBox/GuestHost/DragAndDrop.h>
36
37DnDURIObject::DnDURIObject(void)
38 : m_Type(Unknown)
39 , m_fCreationMode(0)
40 , m_cbSize(0)
41 , m_cbProcessed(0)
42{
43 RT_ZERO(u);
44}
45
46DnDURIObject::DnDURIObject(Type type,
47 const RTCString &strSrcPath /* = 0 */,
48 const RTCString &strDstPath /* = 0 */,
49 uint32_t fMode /* = 0 */, uint64_t cbSize /* = 0 */)
50 : m_Type(type)
51 , m_strSrcPath(strSrcPath)
52 , m_strTgtPath(strDstPath)
53 , m_fCreationMode(fMode)
54 , m_cbSize(cbSize)
55 , m_cbProcessed(0)
56{
57 switch (m_Type)
58 {
59 case File:
60 u.m_hFile = NULL;
61 break;
62
63 case Directory:
64 break;
65
66 default:
67 break;
68 }
69}
70
71DnDURIObject::~DnDURIObject(void)
72{
73 closeInternal();
74}
75
76void DnDURIObject::closeInternal(void)
77{
78 if (m_Type == File)
79 {
80 if (u.m_hFile)
81 {
82 RTFileClose(u.m_hFile);
83 u.m_hFile = NULL;
84 }
85 }
86}
87
88void DnDURIObject::Close(void)
89{
90 switch (m_Type)
91 {
92 case File:
93 {
94 if (u.m_hFile != NULL)
95 {
96 int rc2 = RTFileClose(u.m_hFile);
97 AssertRC(rc2);
98
99 u.m_hFile = NULL;
100 }
101 break;
102 }
103
104 case Directory:
105 break;
106
107 default:
108 break;
109 }
110}
111
112bool DnDURIObject::IsComplete(void) const
113{
114 bool fComplete;
115
116 switch (m_Type)
117 {
118 case File:
119 Assert(m_cbProcessed <= m_cbSize);
120 fComplete = m_cbProcessed == m_cbSize;
121 break;
122
123 case Directory:
124 fComplete = true;
125 break;
126
127 default:
128 fComplete = true;
129 break;
130 }
131
132 return fComplete;
133}
134
135bool DnDURIObject::IsOpen(void) const
136{
137 bool fIsOpen;
138
139 switch (m_Type)
140 {
141 case File:
142 fIsOpen = u.m_hFile != NULL;
143 break;
144
145 case Directory:
146 fIsOpen = true;
147 break;
148
149 default:
150 fIsOpen = false;
151 break;
152 }
153
154 return fIsOpen;
155}
156
157int DnDURIObject::Open(Dest enmDest, uint64_t fOpen)
158{
159 return OpenEx( enmDest == Source
160 ? m_strSrcPath : m_strTgtPath
161 , m_Type, enmDest, fOpen, 0 /* fFlag s*/);
162}
163
164int DnDURIObject::OpenEx(const RTCString &strPath, Type enmType, Dest enmDest,
165 uint64_t fOpen /* = 0 */, uint32_t fFlags /* = 0 */)
166{
167 int rc = VINF_SUCCESS;
168
169 switch (enmDest)
170 {
171 case Source:
172 m_strSrcPath = strPath;
173 break;
174
175 case Target:
176 m_strTgtPath = strPath;
177 break;
178
179 default:
180 rc = VERR_NOT_IMPLEMENTED;
181 break;
182 }
183
184 if ( RT_SUCCESS(rc)
185 && fOpen) /* Opening mode specified? */
186 {
187 switch (enmType)
188 {
189 case File:
190 {
191 if (!u.m_hFile)
192 {
193 /* Open files on the source with RTFILE_O_DENY_WRITE to prevent races
194 * where the OS writes to the file while the destination side transfers
195 * it over. */
196 rc = RTFileOpen(&u.m_hFile, strPath.c_str(), fOpen);
197 LogFlowFunc(("strPath=%s, enmType=%ld, enmDest=%ld, rc=%Rrc\n", strPath.c_str(), enmType, enmDest, rc));
198 if (RT_SUCCESS(rc))
199 rc = RTFileGetSize(u.m_hFile, &m_cbSize);
200 if (RT_SUCCESS(rc))
201 {
202 LogFlowFunc(("cbSize=%RU64, fMode=%RU32\n", m_cbSize, m_fCreationMode));
203 m_cbProcessed = 0;
204 }
205 }
206 else
207 rc = VINF_SUCCESS;
208
209 break;
210 }
211
212 case Directory:
213 rc = VINF_SUCCESS;
214 break;
215
216 default:
217 rc = VERR_NOT_IMPLEMENTED;
218 break;
219 }
220 }
221
222 if (RT_SUCCESS(rc))
223 m_Type = enmType;
224
225 return rc;
226}
227
228/* static */
229/** @todo Put this into an own class like DnDURIPath : public RTCString? */
230int DnDURIObject::RebaseURIPath(RTCString &strPath,
231 const RTCString &strBaseOld /* = "" */,
232 const RTCString &strBaseNew /* = "" */)
233{
234 int rc;
235 const char *pszPath = RTUriPath(strPath.c_str());
236 if (!pszPath)
237 pszPath = strPath.c_str();
238 if (pszPath)
239 {
240 const char *pszPathStart = pszPath;
241 const char *pszBaseOld = strBaseOld.c_str();
242 if ( pszBaseOld
243 && RTPathStartsWith(pszPath, pszBaseOld))
244 {
245 pszPathStart += strlen(pszBaseOld);
246 }
247
248 rc = VINF_SUCCESS;
249
250 if (RT_SUCCESS(rc))
251 {
252 char *pszPathNew = RTPathJoinA(strBaseNew.c_str(), pszPathStart);
253 if (pszPathNew)
254 {
255 char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */,
256 pszPathNew /* pszPath */,
257 NULL /* pszQuery */, NULL /* pszFragment */);
258 if (pszPathURI)
259 {
260 LogFlowFunc(("Rebasing \"%s\" to \"%s\"\n", strPath.c_str(), pszPathURI));
261
262 strPath = RTCString(pszPathURI) + "\r\n";
263 RTStrFree(pszPathURI);
264
265 rc = VINF_SUCCESS;
266 }
267 else
268 rc = VERR_INVALID_PARAMETER;
269
270 RTStrFree(pszPathNew);
271 }
272 else
273 rc = VERR_NO_MEMORY;
274 }
275 }
276 else
277 rc = VERR_INVALID_PARAMETER;
278
279 return rc;
280}
281
282int DnDURIObject::Read(void *pvBuf, size_t cbBuf, uint32_t *pcbRead)
283{
284 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
285 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
286 /* pcbRead is optional. */
287
288 size_t cbRead = 0;
289
290 int rc;
291 switch (m_Type)
292 {
293 case File:
294 {
295 bool fDone = false;
296
297 rc = OpenEx(m_strSrcPath, File, Source,
298 /* Use some sensible defaults. */
299 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fFlags */);
300 if (RT_SUCCESS(rc))
301 {
302 rc = RTFileRead(u.m_hFile, pvBuf, cbBuf, &cbRead);
303 if (RT_SUCCESS(rc))
304 {
305 m_cbProcessed += cbRead;
306 Assert(m_cbProcessed <= m_cbSize);
307
308 /* End of file reached or error occurred? */
309 if (m_cbProcessed == m_cbSize)
310 {
311 rc = VINF_EOF;
312 fDone = true;
313 }
314 }
315 else
316 fDone = true;
317
318 if (fDone)
319 closeInternal();
320 }
321
322 break;
323 }
324
325 case Directory:
326 {
327 rc = VINF_SUCCESS;
328 break;
329 }
330
331 default:
332 rc = VERR_NOT_IMPLEMENTED;
333 break;
334 }
335
336 if (RT_SUCCESS(rc))
337 {
338 if (pcbRead)
339 *pcbRead = (uint32_t)cbRead;
340 }
341
342 LogFlowFunc(("Returning strSourcePath=%s, cbRead=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbRead, rc));
343 return rc;
344}
345
346void DnDURIObject::Reset(void)
347{
348 Close();
349
350 m_Type = Unknown;
351 m_strSrcPath = "";
352 m_strTgtPath = "";
353 m_fCreationMode = 0;
354 m_cbSize = 0;
355 m_cbProcessed = 0;
356}
357
358int DnDURIObject::Write(const void *pvBuf, size_t cbBuf, uint32_t *pcbWritten)
359{
360 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
361 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
362 /* pcbWritten is optional. */
363
364 size_t cbWritten = 0;
365
366 int rc;
367 switch (m_Type)
368 {
369 case File:
370 {
371 bool fDone = false;
372
373 rc = OpenEx(m_strTgtPath, File, Target,
374 /* Use some sensible defaults. */
375 RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE, 0 /* fFlags */);
376 if (RT_SUCCESS(rc))
377 {
378 rc = RTFileWrite(u.m_hFile, pvBuf, cbBuf, &cbWritten);
379 if (RT_SUCCESS(rc))
380 m_cbProcessed += cbWritten;
381 else
382 fDone = true;
383
384 if (fDone)
385 closeInternal();
386 }
387
388 break;
389 }
390
391 case Directory:
392 {
393 rc = VINF_SUCCESS;
394 break;
395 }
396
397 default:
398 rc = VERR_NOT_IMPLEMENTED;
399 break;
400 }
401
402 if (RT_SUCCESS(rc))
403 {
404 if (pcbWritten)
405 *pcbWritten = (uint32_t)cbWritten;
406 }
407
408 LogFlowFunc(("Returning strSourcePath=%s, cbWritten=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbWritten, rc));
409 return rc;
410}
411
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette