VirtualBox

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

Last change on this file since 58312 was 58069, checked in by vboxsync, 9 years ago

IPRT,*: Simplified RTUriFilePath by removing the uFormat parameter. It now defaults to the host path style just like RTUriFileCreate.

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