VirtualBox

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

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

DnD: DnDURIObject: Only set file mode on write, retrieve file mode on read, simplified some code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: DnDURIObject.cpp 56911 2015-07-10 09:21:10Z 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 switch (m_Type)
79 {
80 case File:
81 {
82 if (u.m_hFile)
83 {
84 int rc2 = RTFileClose(u.m_hFile);
85 AssertRC(rc2);
86
87 u.m_hFile = NULL;
88 }
89 break;
90 }
91
92 case Directory:
93 break;
94
95 default:
96 break;
97 }
98
99 LogFlowThisFuncLeave();
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 != NULL;
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 switch (enmType)
183 {
184 case File:
185 {
186 if (!u.m_hFile)
187 {
188 /*
189 * Open files on the source with RTFILE_O_DENY_WRITE to prevent races
190 * where the OS writes to the file while the destination side transfers
191 * it over.
192 */
193 rc = RTFileOpen(&u.m_hFile, strPath.c_str(), fOpen);
194 LogFlowThisFunc(("strPath=%s, fOpen=0x%x, enmType=%RU32, enmDest=%RU32, rc=%Rrc\n",
195 strPath.c_str(), fOpen, enmType, enmDest, rc));
196 if (RT_SUCCESS(rc))
197 rc = RTFileGetSize(u.m_hFile, &m_cbSize);
198
199 if (RT_SUCCESS(rc))
200 {
201 if ( (fOpen & RTFILE_O_WRITE) /* Only set the file mode on write. */
202 && fMode /* Some file mode to set specified? */)
203 {
204 rc = RTFileSetMode(u.m_hFile, fMode);
205 if (RT_SUCCESS(rc))
206 m_fMode = fMode;
207 }
208 else if (fOpen & RTFILE_O_READ)
209 {
210#if 0 /** @todo Enable this as soon as RTFileGetMode is implemented. */
211 rc = RTFileGetMode(u.m_hFile, &m_fMode);
212#else
213 RTFSOBJINFO ObjInfo;
214 rc = RTFileQueryInfo(u.m_hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING);
215 if (RT_SUCCESS(rc))
216 m_fMode = ObjInfo.Attr.fMode;
217#endif
218 }
219 }
220
221 if (RT_SUCCESS(rc))
222 {
223 LogFlowThisFunc(("cbSize=%RU64, fMode=0x%x\n", m_cbSize, m_fMode));
224 m_cbProcessed = 0;
225 }
226 }
227 else
228 rc = VINF_SUCCESS;
229
230 break;
231 }
232
233 case Directory:
234 rc = VINF_SUCCESS;
235 break;
236
237 default:
238 rc = VERR_NOT_IMPLEMENTED;
239 break;
240 }
241 }
242
243 if (RT_SUCCESS(rc))
244 m_Type = enmType;
245
246 LogFlowFuncLeaveRC(rc);
247 return rc;
248}
249
250/* static */
251/** @todo Put this into an own class like DnDURIPath : public RTCString? */
252int DnDURIObject::RebaseURIPath(RTCString &strPath,
253 const RTCString &strBaseOld /* = "" */,
254 const RTCString &strBaseNew /* = "" */)
255{
256 int rc;
257 const char *pszPath = RTUriPath(strPath.c_str());
258 if (!pszPath)
259 pszPath = strPath.c_str();
260 if (pszPath)
261 {
262 const char *pszPathStart = pszPath;
263 const char *pszBaseOld = strBaseOld.c_str();
264 if ( pszBaseOld
265 && RTPathStartsWith(pszPath, pszBaseOld))
266 {
267 pszPathStart += strlen(pszBaseOld);
268 }
269
270 rc = VINF_SUCCESS;
271
272 if (RT_SUCCESS(rc))
273 {
274 char *pszPathNew = RTPathJoinA(strBaseNew.c_str(), pszPathStart);
275 if (pszPathNew)
276 {
277 char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */,
278 pszPathNew /* pszPath */,
279 NULL /* pszQuery */, NULL /* pszFragment */);
280 if (pszPathURI)
281 {
282 LogFlowFunc(("Rebasing \"%s\" to \"%s\"\n", strPath.c_str(), pszPathURI));
283
284 strPath = RTCString(pszPathURI) + "\r\n";
285 RTStrFree(pszPathURI);
286
287 rc = VINF_SUCCESS;
288 }
289 else
290 rc = VERR_INVALID_PARAMETER;
291
292 RTStrFree(pszPathNew);
293 }
294 else
295 rc = VERR_NO_MEMORY;
296 }
297 }
298 else
299 rc = VERR_INVALID_PARAMETER;
300
301 return rc;
302}
303
304int DnDURIObject::Read(void *pvBuf, size_t cbBuf, uint32_t *pcbRead)
305{
306 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
307 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
308 /* pcbRead is optional. */
309
310 size_t cbRead = 0;
311
312 int rc;
313 switch (m_Type)
314 {
315 case File:
316 {
317 rc = OpenEx(m_strSrcPath, File, Source,
318 /* Use some sensible defaults. */
319 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, 0 /* fFlags */);
320 if (RT_SUCCESS(rc))
321 {
322 rc = RTFileRead(u.m_hFile, pvBuf, cbBuf, &cbRead);
323 if (RT_SUCCESS(rc))
324 {
325 m_cbProcessed += cbRead;
326 Assert(m_cbProcessed <= m_cbSize);
327
328 /* End of file reached or error occurred? */
329 if ( m_cbSize
330 && m_cbProcessed == m_cbSize)
331 {
332 rc = VINF_EOF;
333 }
334 }
335 }
336
337 break;
338 }
339
340 case Directory:
341 {
342 rc = VINF_SUCCESS;
343 break;
344 }
345
346 default:
347 rc = VERR_NOT_IMPLEMENTED;
348 break;
349 }
350
351 if (RT_SUCCESS(rc))
352 {
353 if (pcbRead)
354 *pcbRead = (uint32_t)cbRead;
355 }
356
357 LogFlowFunc(("Returning strSourcePath=%s, cbRead=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbRead, rc));
358 return rc;
359}
360
361void DnDURIObject::Reset(void)
362{
363 Close();
364
365 m_Type = Unknown;
366 m_strSrcPath = "";
367 m_strTgtPath = "";
368 m_fMode = 0;
369 m_cbSize = 0;
370 m_cbProcessed = 0;
371}
372
373int DnDURIObject::Write(const void *pvBuf, size_t cbBuf, uint32_t *pcbWritten)
374{
375 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
376 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
377 /* pcbWritten is optional. */
378
379 size_t cbWritten = 0;
380
381 int rc;
382 switch (m_Type)
383 {
384 case File:
385 {
386 rc = OpenEx(m_strTgtPath, File, Target,
387 /* Use some sensible defaults. */
388 RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE, 0 /* fFlags */);
389 if (RT_SUCCESS(rc))
390 {
391 rc = RTFileWrite(u.m_hFile, pvBuf, cbBuf, &cbWritten);
392 if (RT_SUCCESS(rc))
393 m_cbProcessed += cbWritten;
394 }
395
396 break;
397 }
398
399 case Directory:
400 {
401 rc = VINF_SUCCESS;
402 break;
403 }
404
405 default:
406 rc = VERR_NOT_IMPLEMENTED;
407 break;
408 }
409
410 if (RT_SUCCESS(rc))
411 {
412 if (pcbWritten)
413 *pcbWritten = (uint32_t)cbWritten;
414 }
415
416 LogFlowFunc(("Returning strSourcePath=%s, cbWritten=%zu, rc=%Rrc\n", m_strSrcPath.c_str(), cbWritten, rc));
417 return rc;
418}
419
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