VirtualBox

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

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

DnDURIObject.cpp: Use NIL_RTFILE for file objects.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.9 KB
Line 
1/* $Id: DnDURIObject.cpp 59778 2016-02-22 16:44:07Z 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-2016 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 = NIL_RTFILE;
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 LogFlowThisFuncEnter();
80 switch (m_Type)
81 {
82 case File:
83 {
84 if (u.m_hFile != NIL_RTFILE)
85 {
86 int rc2 = RTFileClose(u.m_hFile);
87 AssertRC(rc2);
88
89 u.m_hFile = NIL_RTFILE;
90 }
91 break;
92 }
93
94 case Directory:
95 break;
96
97 default:
98 break;
99 }
100}
101
102void DnDURIObject::Close(void)
103{
104 closeInternal();
105}
106
107bool DnDURIObject::IsComplete(void) const
108{
109 bool fComplete;
110
111 switch (m_Type)
112 {
113 case File:
114 Assert(m_cbProcessed <= m_cbSize);
115 fComplete = m_cbProcessed == m_cbSize;
116 break;
117
118 case Directory:
119 fComplete = true;
120 break;
121
122 default:
123 fComplete = true;
124 break;
125 }
126
127 return fComplete;
128}
129
130bool DnDURIObject::IsOpen(void) const
131{
132 bool fIsOpen;
133
134 switch (m_Type)
135 {
136 case File:
137 fIsOpen = u.m_hFile != NIL_RTFILE;
138 break;
139
140 case Directory:
141 fIsOpen = true;
142 break;
143
144 default:
145 fIsOpen = false;
146 break;
147 }
148
149 return fIsOpen;
150}
151
152int DnDURIObject::Open(Dest enmDest, uint64_t fOpen /* = 0 */, uint32_t fMode /* = 0 */)
153{
154 return OpenEx( enmDest == Source
155 ? m_strSrcPath : m_strTgtPath
156 , m_Type, enmDest, fOpen, fMode, 0 /* fFlags */);
157}
158
159int DnDURIObject::OpenEx(const RTCString &strPath, Type enmType, Dest enmDest,
160 uint64_t fOpen /* = 0 */, uint32_t fMode /* = 0 */, uint32_t fFlags /* = 0 */)
161{
162 int rc = VINF_SUCCESS;
163
164 switch (enmDest)
165 {
166 case Source:
167 m_strSrcPath = strPath;
168 break;
169
170 case Target:
171 m_strTgtPath = strPath;
172 break;
173
174 default:
175 rc = VERR_NOT_IMPLEMENTED;
176 break;
177 }
178
179 if ( RT_SUCCESS(rc)
180 && fOpen) /* Opening mode specified? */
181 {
182 LogFlowThisFunc(("strPath=%s, fOpen=0x%x, enmType=%RU32, enmDest=%RU32\n",
183 strPath.c_str(), fOpen, enmType, enmDest));
184 switch (enmType)
185 {
186 case File:
187 {
188 if (u.m_hFile == NIL_RTFILE)
189 {
190 /*
191 * Open files on the source with RTFILE_O_DENY_WRITE to prevent races
192 * where the OS writes to the file while the destination side transfers
193 * it over.
194 */
195 LogFlowThisFunc(("Opening ...\n"));
196 rc = RTFileOpen(&u.m_hFile, strPath.c_str(), fOpen);
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 LogFlowThisFuncEnter();
367
368 Close();
369
370 m_Type = Unknown;
371 m_strSrcPath = "";
372 m_strTgtPath = "";
373 m_fMode = 0;
374 m_cbSize = 0;
375 m_cbProcessed = 0;
376}
377
378int DnDURIObject::Write(const void *pvBuf, size_t cbBuf, uint32_t *pcbWritten)
379{
380 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
381 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
382 /* pcbWritten is optional. */
383
384 size_t cbWritten = 0;
385
386 int rc;
387 switch (m_Type)
388 {
389 case File:
390 {
391 rc = OpenEx(m_strTgtPath, File, Target,
392 /* Use some sensible defaults. */
393 RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE, 0 /* fFlags */);
394 if (RT_SUCCESS(rc))
395 {
396 rc = RTFileWrite(u.m_hFile, pvBuf, cbBuf, &cbWritten);
397 if (RT_SUCCESS(rc))
398 m_cbProcessed += cbWritten;
399 }
400 break;
401 }
402
403 case Directory:
404 {
405 rc = VINF_SUCCESS;
406 break;
407 }
408
409 default:
410 rc = VERR_NOT_IMPLEMENTED;
411 break;
412 }
413
414 if (RT_SUCCESS(rc))
415 {
416 if (pcbWritten)
417 *pcbWritten = (uint32_t)cbWritten;
418 }
419
420 LogFlowThisFunc(("Returning strSourcePath=%s, cbWritten=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbWritten, rc));
421 return rc;
422}
423
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