VirtualBox

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

最後變更 在這個檔案從78020是 78020,由 vboxsync 提交於 6 年 前

DnD/DnDURIObject: Got rid of internal m_fIsOpen member, which is superfluous.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.0 KB
 
1/* $Id: DnDURIObject.cpp 78020 2019-04-05 08:23:13Z vboxsync $ */
2/** @file
3 * DnD - URI object class. For handling creation/reading/writing to files and directories on host or guest side.
4 */
5
6/*
7 * Copyright (C) 2014-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_GUEST_DND
23#include <VBox/GuestHost/DragAndDrop.h>
24
25#include <iprt/dir.h>
26#include <iprt/err.h>
27#include <iprt/file.h>
28#include <iprt/fs.h>
29#include <iprt/path.h>
30#include <iprt/uri.h>
31
32#include <VBox/log.h>
33
34
35DnDURIObject::DnDURIObject(void)
36 : m_enmType(Type_Unknown)
37 , m_enmView(View_Unknown)
38{
39 RT_ZERO(u);
40}
41
42DnDURIObject::DnDURIObject(Type enmType,
43 const RTCString &strSrcPathAbs /* = 0 */,
44 const RTCString &strDstPathAbs /* = 0 */)
45 : m_enmType(enmType)
46 , m_enmView(View_Unknown)
47 , m_strSrcPathAbs(strSrcPathAbs)
48 , m_strTgtPathAbs(strDstPathAbs)
49{
50 RT_ZERO(u);
51}
52
53DnDURIObject::~DnDURIObject(void)
54{
55 closeInternal();
56}
57
58/**
59 * Closes the object's internal handles (to files / ...).
60 *
61 */
62void DnDURIObject::closeInternal(void)
63{
64 LogFlowThisFuncEnter();
65
66 switch (m_enmType)
67 {
68 case Type_File:
69 {
70 RTFileClose(u.File.hFile);
71 u.File.hFile = NIL_RTFILE;
72 RT_ZERO(u.File.objInfo);
73 break;
74 }
75
76 case Type_Directory:
77 {
78 RTDirClose(u.Dir.hDir);
79 u.Dir.hDir = NIL_RTDIR;
80 RT_ZERO(u.Dir.objInfo);
81 break;
82 }
83
84 default:
85 break;
86 }
87}
88
89/**
90 * Closes the object.
91 * This also closes the internal handles associated with the object (to files / ...).
92 */
93void DnDURIObject::Close(void)
94{
95 closeInternal();
96}
97
98/**
99 * Returns the directory / file mode of the object.
100 *
101 * @return File / directory mode.
102 */
103RTFMODE DnDURIObject::GetMode(void) const
104{
105 switch (m_enmType)
106 {
107 case Type_File:
108 return u.File.objInfo.Attr.fMode;
109
110 case Type_Directory:
111 return u.Dir.objInfo.Attr.fMode;
112
113 default:
114 break;
115 }
116
117 AssertFailed();
118 return 0;
119}
120
121/**
122 * Returns the bytes already processed (read / written).
123 *
124 * Note: Only applies if the object is of type DnDURIObject::Type_File.
125 *
126 * @return Bytes already processed (read / written).
127 */
128uint64_t DnDURIObject::GetProcessed(void) const
129{
130 if (m_enmType == Type_File)
131 return u.File.cbProcessed;
132
133 return 0;
134}
135
136/**
137 * Returns the file's logical size (in bytes).
138 *
139 * Note: Only applies if the object is of type DnDURIObject::Type_File.
140 *
141 * @return The file's logical size (in bytes).
142 */
143uint64_t DnDURIObject::GetSize(void) const
144{
145 if (m_enmType == Type_File)
146 return u.File.cbToProcess;
147
148 return 0;
149}
150
151/**
152 * Returns whether the processing of the object is complete or not.
153 * For file objects this means that all bytes have been processed.
154 *
155 * @return True if complete, False if not.
156 */
157bool DnDURIObject::IsComplete(void) const
158{
159 bool fComplete;
160
161 switch (m_enmType)
162 {
163 case Type_File:
164 Assert(u.File.cbProcessed <= u.File.cbToProcess);
165 fComplete = u.File.cbProcessed == u.File.cbToProcess;
166 break;
167
168 case Type_Directory:
169 fComplete = true;
170 break;
171
172 default:
173 fComplete = true;
174 break;
175 }
176
177 return fComplete;
178}
179
180/**
181 * Returns whether the object is in an open state or not.
182 */
183bool DnDURIObject::IsOpen(void) const
184{
185 switch (m_enmType)
186 {
187 case Type_File: return RTFileIsValid(u.File.hFile);
188 case Type_Directory: return RTDirIsValid(u.Dir.hDir);
189 default: break;
190 }
191
192 return false;
193}
194
195/**
196 * (Re-)Opens the object with a specific view, open and file mode.
197 *
198 * @return IPRT status code.
199 * @param enmView View to use for opening the object.
200 * @param fOpen File open flags to use.
201 * @param fMode File mode to use.
202 */
203int DnDURIObject::Open(View enmView, uint64_t fOpen /* = 0 */, RTFMODE fMode /* = 0 */)
204{
205 return OpenEx( enmView == View_Source
206 ? m_strSrcPathAbs : m_strTgtPathAbs
207 , enmView, fOpen, fMode, DNDURIOBJECT_FLAGS_NONE);
208}
209
210/**
211 * Open the object with a specific file type, and, depending on the type, specifying additional parameters.
212 *
213 * @return IPRT status code.
214 * @param strPathAbs Absolute path of the object (file / directory / ...).
215 * @param enmView View of the object.
216 * @param fOpen Open mode to use; only valid for file objects.
217 * @param fMode File mode to use; only valid for file objects.
218 * @param fFlags Additional DnD URI object flags.
219 */
220int DnDURIObject::OpenEx(const RTCString &strPathAbs, View enmView,
221 uint64_t fOpen /* = 0 */, RTFMODE fMode /* = 0 */, DNDURIOBJECTFLAGS fFlags /* = DNDURIOBJECT_FLAGS_NONE */)
222{
223 AssertReturn(!(fFlags & ~DNDURIOBJECT_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
224 RT_NOREF1(fFlags);
225
226 int rc = VINF_SUCCESS;
227
228 switch (enmView)
229 {
230 case View_Source:
231 m_strSrcPathAbs = strPathAbs;
232 break;
233
234 case View_Target:
235 m_strTgtPathAbs = strPathAbs;
236 break;
237
238 default:
239 rc = VERR_NOT_IMPLEMENTED;
240 break;
241 }
242
243 if ( RT_SUCCESS(rc)
244 && fOpen) /* Opening mode specified? */
245 {
246 LogFlowThisFunc(("strPath=%s, enmView=%RU32, fOpen=0x%x, fMode=0x%x, fFlags=0x%x\n",
247 strPathAbs.c_str(), enmView, fOpen, fMode, fFlags));
248 switch (m_enmType)
249 {
250 case Type_File:
251 {
252 /*
253 * Open files on the source with RTFILE_O_DENY_WRITE to prevent races
254 * where the OS writes to the file while the destination side transfers
255 * it over.
256 */
257 LogFlowThisFunc(("Opening ...\n"));
258 rc = RTFileOpen(&u.File.hFile, strPathAbs.c_str(), fOpen);
259 if (RT_SUCCESS(rc))
260 {
261 if ( (fOpen & RTFILE_O_WRITE) /* Only set the file mode on write. */
262 && fMode /* Some file mode to set specified? */)
263 {
264 rc = RTFileSetMode(u.File.hFile, fMode);
265 }
266 else if (fOpen & RTFILE_O_READ)
267 {
268 rc = queryInfoInternal(enmView);
269 }
270 }
271
272 if (RT_SUCCESS(rc))
273 {
274 LogFlowThisFunc(("File cbObject=%RU64, fMode=0x%x\n",
275 u.File.objInfo.cbObject, u.File.objInfo.Attr.fMode));
276 u.File.cbToProcess = u.File.objInfo.cbObject;
277 u.File.cbProcessed = 0;
278 }
279
280 break;
281 }
282
283 case Type_Directory:
284 {
285 rc = RTDirOpen(&u.Dir.hDir, strPathAbs.c_str());
286 if (RT_SUCCESS(rc))
287 rc = queryInfoInternal(enmView);
288 break;
289 }
290
291 default:
292 rc = VERR_NOT_IMPLEMENTED;
293 break;
294 }
295 }
296
297 if (RT_SUCCESS(rc))
298 {
299 m_enmView = enmView;
300 }
301
302 LogFlowFuncLeaveRC(rc);
303 return rc;
304}
305
306/**
307 * Queries information about the object using a specific view, internal version.
308 *
309 * @return IPRT status code.
310 * @param enmView View to use for querying information. Currently ignored.
311 */
312int DnDURIObject::queryInfoInternal(View enmView)
313{
314 RT_NOREF(enmView);
315
316 int rc;
317
318 switch (m_enmType)
319 {
320 case Type_File:
321 AssertMsgReturn(RTFileIsValid(u.File.hFile), ("Object has invalid file handle\n"), VERR_INVALID_STATE);
322 rc = RTFileQueryInfo(u.File.hFile, &u.File.objInfo, RTFSOBJATTRADD_NOTHING);
323 break;
324
325 case Type_Directory:
326 AssertMsgReturn(RTDirIsValid(u.Dir.hDir), ("Object has invalid directory handle\n"), VERR_INVALID_STATE);
327 rc = RTDirQueryInfo(u.Dir.hDir, &u.Dir.objInfo, RTFSOBJATTRADD_NOTHING);
328 break;
329
330 default:
331 rc = VERR_NOT_IMPLEMENTED;
332 break;
333 }
334
335 return rc;
336}
337
338/**
339 * Queries information about the object using a specific view.
340 *
341 * @return IPRT status code.
342 * @param enmView View to use for querying information.
343 */
344int DnDURIObject::QueryInfo(View enmView)
345{
346 return queryInfoInternal(enmView);
347}
348
349/**
350 * Rebases an absolute URI path from an old path base to a new path base.
351 * This function is needed in order to transform path from the source side to the target side.
352 *
353 * @return IPRT status code.
354 * @param strPathAbs Absolute URI path to rebase.
355 * @param strBaseOld Old base path to rebase from.
356 * @param strBaseNew New base path to rebase to.
357 *
358 ** @todo Put this into an own class like DnDURIPath : public RTCString?
359 */
360/* static */
361int DnDURIObject::RebaseURIPath(RTCString &strPathAbs,
362 const RTCString &strBaseOld /* = "" */,
363 const RTCString &strBaseNew /* = "" */)
364{
365 char *pszPath = RTUriFilePath(strPathAbs.c_str());
366 if (!pszPath) /* No URI? */
367 pszPath = RTStrDup(strPathAbs.c_str());
368
369 int rc;
370
371 if (pszPath)
372 {
373 const char *pszPathStart = pszPath;
374 const char *pszBaseOld = strBaseOld.c_str();
375 if ( pszBaseOld
376 && RTPathStartsWith(pszPath, pszBaseOld))
377 {
378 pszPathStart += strlen(pszBaseOld);
379 }
380
381 rc = VINF_SUCCESS;
382
383 if (RT_SUCCESS(rc))
384 {
385 char *pszPathNew = RTPathJoinA(strBaseNew.c_str(), pszPathStart);
386 if (pszPathNew)
387 {
388 char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */,
389 pszPathNew /* pszPath */,
390 NULL /* pszQuery */, NULL /* pszFragment */);
391 if (pszPathURI)
392 {
393 LogFlowFunc(("Rebasing \"%s\" to \"%s\"\n", strPathAbs.c_str(), pszPathURI));
394
395 strPathAbs = RTCString(pszPathURI) + "\r\n";
396 RTStrFree(pszPathURI);
397 }
398 else
399 rc = VERR_INVALID_PARAMETER;
400
401 RTStrFree(pszPathNew);
402 }
403 else
404 rc = VERR_NO_MEMORY;
405 }
406
407 RTStrFree(pszPath);
408 }
409 else
410 rc = VERR_NO_MEMORY;
411
412 return rc;
413}
414
415/**
416 * Reads data from the object. Only applies to files objects.
417 *
418 * @return IPRT status code.
419 * @param pvBuf Buffer where to store the read data.
420 * @param cbBuf Size (in bytes) of the buffer.
421 * @param pcbRead Pointer where to store how many bytes were read. Optional.
422 */
423int DnDURIObject::Read(void *pvBuf, size_t cbBuf, uint32_t *pcbRead)
424{
425 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
426 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
427 /* pcbRead is optional. */
428
429 AssertMsgReturn(m_enmView == View_Source, ("Cannot write to an object which is not in target view\n"),
430 VERR_INVALID_STATE);
431
432 size_t cbRead = 0;
433
434 int rc;
435 switch (m_enmType)
436 {
437 case Type_File:
438 {
439 rc = RTFileRead(u.File.hFile, pvBuf, cbBuf, &cbRead);
440 if (RT_SUCCESS(rc))
441 {
442 u.File.cbProcessed += cbRead;
443 Assert(u.File.cbProcessed <= u.File.cbToProcess);
444
445 /* End of file reached or error occurred? */
446 if ( u.File.cbToProcess
447 && u.File.cbProcessed == u.File.cbToProcess)
448 {
449 rc = VINF_EOF;
450 }
451 }
452 break;
453 }
454
455 case Type_Directory:
456 {
457 rc = VINF_SUCCESS;
458 break;
459 }
460
461 default:
462 rc = VERR_NOT_IMPLEMENTED;
463 break;
464 }
465
466 if (RT_SUCCESS(rc))
467 {
468 if (pcbRead)
469 *pcbRead = (uint32_t)cbRead;
470 }
471
472 LogFlowFunc(("Returning strSourcePath=%s, cbRead=%zu, rc=%Rrc\n", m_strSrcPathAbs.c_str(), cbRead, rc));
473 return rc;
474}
475
476/**
477 * Resets the object's state and closes all related handles.
478 */
479void DnDURIObject::Reset(void)
480{
481 LogFlowThisFuncEnter();
482
483 Close();
484
485 m_enmType = Type_Unknown;
486 m_enmView = View_Unknown;
487 m_strSrcPathAbs = "";
488 m_strTgtPathAbs = "";
489
490 RT_ZERO(u);
491}
492
493/**
494 * Sets the bytes to process by the object.
495 *
496 * Note: Only applies if the object is of type DnDURIObject::Type_File.
497 *
498 * @return IPRT return code.
499 * @param cbSize Size (in bytes) to process.
500 */
501int DnDURIObject::SetSize(uint64_t cbSize)
502{
503 AssertReturn(m_enmType == Type_File, VERR_INVALID_PARAMETER);
504
505 /** @todo Implement sparse file support here. */
506
507 u.File.cbToProcess = cbSize;
508 return VINF_SUCCESS;
509}
510
511/**
512 * Writes data to an object. Only applies to file objects.
513 *
514 * @return IPRT status code.
515 * @param pvBuf Buffer of data to write.
516 * @param cbBuf Size (in bytes) of data to write.
517 * @param pcbWritten Pointer where to store how many bytes were written. Optional.
518 */
519int DnDURIObject::Write(const void *pvBuf, size_t cbBuf, uint32_t *pcbWritten)
520{
521 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
522 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
523 /* pcbWritten is optional. */
524
525 AssertMsgReturn(m_enmView == View_Target, ("Cannot write to an object which is not in target view\n"),
526 VERR_INVALID_STATE);
527
528 size_t cbWritten = 0;
529
530 int rc;
531 switch (m_enmType)
532 {
533 case Type_File:
534 {
535 rc = RTFileWrite(u.File.hFile, pvBuf, cbBuf, &cbWritten);
536 if (RT_SUCCESS(rc))
537 u.File.cbProcessed += cbWritten;
538 break;
539 }
540
541 case Type_Directory:
542 {
543 rc = VINF_SUCCESS;
544 break;
545 }
546
547 default:
548 rc = VERR_NOT_IMPLEMENTED;
549 break;
550 }
551
552 if (RT_SUCCESS(rc))
553 {
554 if (pcbWritten)
555 *pcbWritten = (uint32_t)cbWritten;
556 }
557
558 LogFlowThisFunc(("Returning strSourcePathAbs=%s, cbWritten=%zu, rc=%Rrc\n", m_strSrcPathAbs.c_str(), cbWritten, rc));
559 return rc;
560}
561
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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