VirtualBox

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

Last change on this file since 56533 was 55805, checked in by vboxsync, 9 years ago

DnDURIList: Implemented resolving symlinks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/* $Id: DnDURIObject.cpp 55805 2015-05-11 15:00:35Z 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_fMode(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_fMode(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 /* = 0 */, uint32_t fMode /* = 0 */)
158{
159 return OpenEx( enmDest == Source
160 ? m_strSrcPath : m_strTgtPath
161 , m_Type, enmDest, fOpen, fMode, 0 /* fFlags */);
162}
163
164int DnDURIObject::OpenEx(const RTCString &strPath, Type enmType, Dest enmDest,
165 uint64_t fOpen /* = 0 */, uint32_t fMode /* = 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=%RU32, enmDest=%RU32, 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 && fMode)
202 {
203 rc = RTFileSetMode(u.m_hFile, fMode);
204 }
205 if (RT_SUCCESS(rc))
206 {
207 LogFlowFunc(("cbSize=%RU64, fMode=%RU32\n", m_cbSize, m_fMode));
208 m_cbProcessed = 0;
209 }
210 }
211 else
212 rc = VINF_SUCCESS;
213
214 break;
215 }
216
217 case Directory:
218 rc = VINF_SUCCESS;
219 break;
220
221 default:
222 rc = VERR_NOT_IMPLEMENTED;
223 break;
224 }
225 }
226
227 if (RT_SUCCESS(rc))
228 m_Type = enmType;
229
230 return rc;
231}
232
233/* static */
234/** @todo Put this into an own class like DnDURIPath : public RTCString? */
235int DnDURIObject::RebaseURIPath(RTCString &strPath,
236 const RTCString &strBaseOld /* = "" */,
237 const RTCString &strBaseNew /* = "" */)
238{
239 int rc;
240 const char *pszPath = RTUriPath(strPath.c_str());
241 if (!pszPath)
242 pszPath = strPath.c_str();
243 if (pszPath)
244 {
245 const char *pszPathStart = pszPath;
246 const char *pszBaseOld = strBaseOld.c_str();
247 if ( pszBaseOld
248 && RTPathStartsWith(pszPath, pszBaseOld))
249 {
250 pszPathStart += strlen(pszBaseOld);
251 }
252
253 rc = VINF_SUCCESS;
254
255 if (RT_SUCCESS(rc))
256 {
257 char *pszPathNew = RTPathJoinA(strBaseNew.c_str(), pszPathStart);
258 if (pszPathNew)
259 {
260 char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */,
261 pszPathNew /* pszPath */,
262 NULL /* pszQuery */, NULL /* pszFragment */);
263 if (pszPathURI)
264 {
265 LogFlowFunc(("Rebasing \"%s\" to \"%s\"\n", strPath.c_str(), pszPathURI));
266
267 strPath = RTCString(pszPathURI) + "\r\n";
268 RTStrFree(pszPathURI);
269
270 rc = VINF_SUCCESS;
271 }
272 else
273 rc = VERR_INVALID_PARAMETER;
274
275 RTStrFree(pszPathNew);
276 }
277 else
278 rc = VERR_NO_MEMORY;
279 }
280 }
281 else
282 rc = VERR_INVALID_PARAMETER;
283
284 return rc;
285}
286
287int DnDURIObject::Read(void *pvBuf, size_t cbBuf, uint32_t *pcbRead)
288{
289 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
290 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
291 /* pcbRead is optional. */
292
293 size_t cbRead = 0;
294
295 int rc;
296 switch (m_Type)
297 {
298 case File:
299 {
300 rc = OpenEx(m_strSrcPath, File, Source,
301 /* Use some sensible defaults. */
302 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fFlags */);
303 if (RT_SUCCESS(rc))
304 {
305 rc = RTFileRead(u.m_hFile, pvBuf, cbBuf, &cbRead);
306 if (RT_SUCCESS(rc))
307 {
308 m_cbProcessed += cbRead;
309 Assert(m_cbProcessed <= m_cbSize);
310
311 /* End of file reached or error occurred? */
312 if ( m_cbSize
313 && m_cbProcessed == m_cbSize)
314 {
315 rc = VINF_EOF;
316 }
317 }
318 }
319
320 break;
321 }
322
323 case Directory:
324 {
325 rc = VINF_SUCCESS;
326 break;
327 }
328
329 default:
330 rc = VERR_NOT_IMPLEMENTED;
331 break;
332 }
333
334 if (RT_SUCCESS(rc))
335 {
336 if (pcbRead)
337 *pcbRead = (uint32_t)cbRead;
338 }
339
340 LogFlowFunc(("Returning strSourcePath=%s, cbRead=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbRead, rc));
341 return rc;
342}
343
344void DnDURIObject::Reset(void)
345{
346 Close();
347
348 m_Type = Unknown;
349 m_strSrcPath = "";
350 m_strTgtPath = "";
351 m_fMode = 0;
352 m_cbSize = 0;
353 m_cbProcessed = 0;
354}
355
356int DnDURIObject::Write(const void *pvBuf, size_t cbBuf, uint32_t *pcbWritten)
357{
358 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
359 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
360 /* pcbWritten is optional. */
361
362 size_t cbWritten = 0;
363
364 int rc;
365 switch (m_Type)
366 {
367 case File:
368 {
369 rc = OpenEx(m_strTgtPath, File, Target,
370 /* Use some sensible defaults. */
371 RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE, 0 /* fFlags */);
372 if (RT_SUCCESS(rc))
373 {
374 rc = RTFileWrite(u.m_hFile, pvBuf, cbBuf, &cbWritten);
375 if (RT_SUCCESS(rc))
376 m_cbProcessed += cbWritten;
377 }
378
379 break;
380 }
381
382 case Directory:
383 {
384 rc = VINF_SUCCESS;
385 break;
386 }
387
388 default:
389 rc = VERR_NOT_IMPLEMENTED;
390 break;
391 }
392
393 if (RT_SUCCESS(rc))
394 {
395 if (pcbWritten)
396 *pcbWritten = (uint32_t)cbWritten;
397 }
398
399 LogFlowFunc(("Returning strSourcePath=%s, cbWritten=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbWritten, rc));
400 return rc;
401}
402
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