VirtualBox

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

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

warning

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

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