VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/GuestFileImpl.cpp@ 55631

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

IGuestSession:

  • Added pathStyle attribute and associated enum.
  • Added a currentDirectory attribute (stub).
  • Introduced fsObjExists (earlier fsExists) which works on all fs obj types.
  • Combined directoryQueryInfo and fileQueryInfo into fsObjQueryInfo (earlier fsQueryInfo) which works on all fs obj types. Caller can check the type attribute.
  • Combined fileRemove and symlinkRemove* into fsObjRemove both on suggestion from Michael and because it's impossible to implement correctly with introducing races. Besides, our implementation was already doing the fsObjRemove job, no type checks.
  • Combined directoryRename, fileRename and symlinkRename into fsObjRename since we cannot implement type specific renames without introducing races on all platforms, and again, the current implementation already does the whole shebang.
  • Combined directorySetACL and fileSetACL into fsObjSetACL, adding a UNIX-style mode parameter for use when the ACL string is empty.
  • Stubbed the recursive directory copy methods directoryCopy, directoryCopyToGuest, and directoryCopyFromGuest. These replaces the proposed FileCopyFlag::Recursive flag.
  • Stubbed a generic move-anything-inside-the-guest method, fsObjMove, for future explotations. (Considered this on file/dir level, but it's the rename and type race problem. So, did the 'mv' approach instead.)
  • Renamed CopyFileFlag to FileCopyFlag.
  • Prefixed copyTo and copyFrom with 'file' and added 'Guest' postfix to clarify the direction (now: fileCopyToGuest, fileCopyFromGuest).
  • Added fileCopy method for copy a guest file to another guest location.
  • directoryExists got a followSymlinks parameter.
  • fileExist and fileQuerySize all got a followSymlinks parameter.
  • Retired directoryRename in favor of fsObjRename.
  • Retired directorySetACL in favor of fsObjSetACL.
  • Retired fileSetACL in favor of fsObjSetACL.
  • Retired fileRemove in favor of fsObjRemove - fileRemove was already removing everything except directories, no need for ambiguous duplications.
  • Retired symlinkRemoveDirectory and symlinkRemoveFile in favor of fsObjRemove.
  • replaced the openMode string parameter int fileOpen[Ex] methods with an enum FileAccessMode (we made some wrong design choices way back).
  • replaced the disposition string parameter in fileOpen[Ex] methods with an enum FileOpenAction. This one was more obvious, should've seen this way back.
  • replaced the sharingMode stirng parameter in the fileOpenEx method with an enum FileSharingMode.
  • Documented directoryRemoveRecursive flags issue.


IFile,IGuestFile:

  • Stubbed querySize
  • Stubbed setSize.
  • Renamed FileSeekType to FileSeekOrigin.
  • Implemented seek() relative to end, flag was forgotten.
  • Made seek() return the new offset.
  • Extended setACL with a UNIX-style file mode argument that should be used if the ACL string is empty (this way we can actually get something implemented without 2 months of cross platform ACL research).
  • The openMode and disposition attributes has been updated to match the fileOpenEx enum changes.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.2 KB
Line 
1/* $Id: GuestFileImpl.cpp 55631 2015-05-04 04:08:10Z vboxsync $ */
2/** @file
3 * VirtualBox Main - Guest file handling.
4 */
5
6/*
7 * Copyright (C) 2012-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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#include "GuestFileImpl.h"
23#include "GuestSessionImpl.h"
24#include "GuestCtrlImplPrivate.h"
25#include "ConsoleImpl.h"
26#include "VirtualBoxErrorInfoImpl.h"
27
28#include "Global.h"
29#include "AutoCaller.h"
30#include "VBoxEvents.h"
31
32#include <iprt/cpp/utils.h> /* For unconst(). */
33#include <iprt/file.h>
34
35#include <VBox/com/array.h>
36#include <VBox/com/listeners.h>
37
38#ifdef LOG_GROUP
39 #undef LOG_GROUP
40#endif
41#define LOG_GROUP LOG_GROUP_GUEST_CONTROL
42#include <VBox/log.h>
43
44
45/**
46 * Internal listener class to serve events in an
47 * active manner, e.g. without polling delays.
48 */
49class GuestFileListener
50{
51public:
52
53 GuestFileListener(void)
54 {
55 }
56
57 HRESULT init(GuestFile *pFile)
58 {
59 AssertPtrReturn(pFile, E_POINTER);
60 mFile = pFile;
61 return S_OK;
62 }
63
64 void uninit(void)
65 {
66 mFile = NULL;
67 }
68
69 STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
70 {
71 switch (aType)
72 {
73 case VBoxEventType_OnGuestFileStateChanged:
74 case VBoxEventType_OnGuestFileOffsetChanged:
75 case VBoxEventType_OnGuestFileRead:
76 case VBoxEventType_OnGuestFileWrite:
77 {
78 AssertPtrReturn(mFile, E_POINTER);
79 int rc2 = mFile->signalWaitEvent(aType, aEvent);
80#ifdef DEBUG_andy
81 LogFlowFunc(("Signalling events of type=%RU32, file=%p resulted in rc=%Rrc\n",
82 aType, mFile, rc2));
83#endif
84 break;
85 }
86
87 default:
88 AssertMsgFailed(("Unhandled event %RU32\n", aType));
89 break;
90 }
91
92 return S_OK;
93 }
94
95private:
96
97 GuestFile *mFile;
98};
99typedef ListenerImpl<GuestFileListener, GuestFile*> GuestFileListenerImpl;
100
101VBOX_LISTENER_DECLARE(GuestFileListenerImpl)
102
103// constructor / destructor
104/////////////////////////////////////////////////////////////////////////////
105
106DEFINE_EMPTY_CTOR_DTOR(GuestFile)
107
108HRESULT GuestFile::FinalConstruct(void)
109{
110 LogFlowThisFuncEnter();
111 return BaseFinalConstruct();
112}
113
114void GuestFile::FinalRelease(void)
115{
116 LogFlowThisFuncEnter();
117 uninit();
118 BaseFinalRelease();
119 LogFlowThisFuncLeave();
120}
121
122// public initializer/uninitializer for internal purposes only
123/////////////////////////////////////////////////////////////////////////////
124
125/**
126 * Initializes a file object but does *not* open the file on the guest
127 * yet. This is done in the dedidcated openFile call.
128 *
129 * @return IPRT status code.
130 * @param pConsole Pointer to console object.
131 * @param pSession Pointer to session object.
132 * @param uFileID Host-based file ID (part of the context ID).
133 * @param openInfo File opening information.
134 */
135int GuestFile::init(Console *pConsole, GuestSession *pSession,
136 ULONG uFileID, const GuestFileOpenInfo &openInfo)
137{
138 LogFlowThisFunc(("pConsole=%p, pSession=%p, uFileID=%RU32, strPath=%s\n",
139 pConsole, pSession, uFileID, openInfo.mFileName.c_str()));
140
141 AssertPtrReturn(pConsole, VERR_INVALID_POINTER);
142 AssertPtrReturn(pSession, VERR_INVALID_POINTER);
143
144 /* Enclose the state transition NotReady->InInit->Ready. */
145 AutoInitSpan autoInitSpan(this);
146 AssertReturn(autoInitSpan.isOk(), VERR_OBJECT_DESTROYED);
147
148#ifndef VBOX_WITH_GUEST_CONTROL
149 autoInitSpan.setSucceeded();
150 return VINF_SUCCESS;
151#else
152 int vrc = bindToSession(pConsole, pSession, uFileID /* Object ID */);
153 if (RT_SUCCESS(vrc))
154 {
155 mSession = pSession;
156
157 mData.mID = uFileID;
158 mData.mInitialSize = 0;
159 mData.mStatus = FileStatus_Undefined;
160 mData.mOpenInfo = openInfo;
161
162 unconst(mEventSource).createObject();
163 HRESULT hr = mEventSource->init();
164 if (FAILED(hr))
165 vrc = VERR_COM_UNEXPECTED;
166 }
167
168 if (RT_SUCCESS(vrc))
169 {
170 try
171 {
172 GuestFileListener *pListener = new GuestFileListener();
173 ComObjPtr<GuestFileListenerImpl> thisListener;
174 HRESULT hr = thisListener.createObject();
175 if (SUCCEEDED(hr))
176 hr = thisListener->init(pListener, this);
177
178 if (SUCCEEDED(hr))
179 {
180 com::SafeArray <VBoxEventType_T> eventTypes;
181 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
182 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged);
183 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
184 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
185 hr = mEventSource->RegisterListener(thisListener,
186 ComSafeArrayAsInParam(eventTypes),
187 TRUE /* Active listener */);
188 if (SUCCEEDED(hr))
189 {
190 vrc = baseInit();
191 if (RT_SUCCESS(vrc))
192 {
193 mLocalListener = thisListener;
194 }
195 }
196 else
197 vrc = VERR_COM_UNEXPECTED;
198 }
199 else
200 vrc = VERR_COM_UNEXPECTED;
201 }
202 catch(std::bad_alloc &)
203 {
204 vrc = VERR_NO_MEMORY;
205 }
206 }
207
208 if (RT_SUCCESS(vrc))
209 {
210 /* Confirm a successful initialization when it's the case. */
211 autoInitSpan.setSucceeded();
212 }
213 else
214 autoInitSpan.setFailed();
215
216 LogFlowFuncLeaveRC(vrc);
217 return vrc;
218#endif /* VBOX_WITH_GUEST_CONTROL */
219}
220
221/**
222 * Uninitializes the instance.
223 * Called from FinalRelease().
224 */
225void GuestFile::uninit(void)
226{
227 /* Enclose the state transition Ready->InUninit->NotReady. */
228 AutoUninitSpan autoUninitSpan(this);
229 if (autoUninitSpan.uninitDone())
230 return;
231
232 LogFlowThisFuncEnter();
233
234#ifdef VBOX_WITH_GUEST_CONTROL
235 baseUninit();
236#endif
237 LogFlowThisFuncLeave();
238}
239
240// implementation of public getters/setters for attributes
241/////////////////////////////////////////////////////////////////////////////
242
243HRESULT GuestFile::getCreationMode(ULONG *aCreationMode)
244{
245#ifndef VBOX_WITH_GUEST_CONTROL
246 ReturnComNotImplemented();
247#else
248 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
249
250 *aCreationMode = mData.mOpenInfo.mCreationMode;
251
252 return S_OK;
253#endif /* VBOX_WITH_GUEST_CONTROL */
254}
255
256HRESULT GuestFile::getOpenAction(FileOpenAction_T *aOpenAction)
257{
258#ifndef VBOX_WITH_GUEST_CONTROL
259 ReturnComNotImplemented();
260#else
261 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
262
263 *aOpenAction = mData.mOpenInfo.mOpenAction;
264
265 return S_OK;
266#endif /* VBOX_WITH_GUEST_CONTROL */
267}
268
269HRESULT GuestFile::getEventSource(ComPtr<IEventSource> &aEventSource)
270{
271#ifndef VBOX_WITH_GUEST_CONTROL
272 ReturnComNotImplemented();
273#else
274 /* No need to lock - lifetime constant. */
275 mEventSource.queryInterfaceTo(aEventSource.asOutParam());
276
277 return S_OK;
278#endif /* VBOX_WITH_GUEST_CONTROL */
279}
280
281HRESULT GuestFile::getFileName(com::Utf8Str &aFileName)
282{
283#ifndef VBOX_WITH_GUEST_CONTROL
284 ReturnComNotImplemented();
285#else
286 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
287
288 aFileName = mData.mOpenInfo.mFileName;
289
290 return S_OK;
291#endif /* VBOX_WITH_GUEST_CONTROL */
292}
293
294HRESULT GuestFile::getId(ULONG *aId)
295{
296#ifndef VBOX_WITH_GUEST_CONTROL
297 ReturnComNotImplemented();
298#else
299 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
300
301 *aId = mData.mID;
302
303 return S_OK;
304#endif /* VBOX_WITH_GUEST_CONTROL */
305}
306
307HRESULT GuestFile::getInitialSize(LONG64 *aInitialSize)
308{
309#ifndef VBOX_WITH_GUEST_CONTROL
310 ReturnComNotImplemented();
311#else
312 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
313
314 *aInitialSize = mData.mInitialSize;
315
316 return S_OK;
317#endif /* VBOX_WITH_GUEST_CONTROL */
318}
319
320HRESULT GuestFile::getOffset(LONG64 *aOffset)
321{
322#ifndef VBOX_WITH_GUEST_CONTROL
323 ReturnComNotImplemented();
324#else
325 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
326
327 *aOffset = mData.mOffCurrent;
328
329 return S_OK;
330#endif /* VBOX_WITH_GUEST_CONTROL */
331}
332
333HRESULT GuestFile::getAccessMode(FileAccessMode_T *aAccessMode)
334{
335#ifndef VBOX_WITH_GUEST_CONTROL
336 ReturnComNotImplemented();
337#else
338 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
339
340 *aAccessMode = mData.mOpenInfo.mAccessMode;
341
342 return S_OK;
343#endif /* VBOX_WITH_GUEST_CONTROL */
344}
345
346HRESULT GuestFile::getStatus(FileStatus_T *aStatus)
347{
348#ifndef VBOX_WITH_GUEST_CONTROL
349 ReturnComNotImplemented();
350#else
351 LogFlowThisFuncEnter();
352
353 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
354
355 *aStatus = mData.mStatus;
356
357 return S_OK;
358#endif /* VBOX_WITH_GUEST_CONTROL */
359}
360
361// private methods
362/////////////////////////////////////////////////////////////////////////////
363
364int GuestFile::i_callbackDispatcher(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb)
365{
366 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
367 AssertPtrReturn(pSvcCb, VERR_INVALID_POINTER);
368
369 LogFlowThisFunc(("strName=%s, uContextID=%RU32, uFunction=%RU32, pSvcCb=%p\n",
370 mData.mOpenInfo.mFileName.c_str(), pCbCtx->uContextID, pCbCtx->uFunction, pSvcCb));
371
372 int vrc;
373 switch (pCbCtx->uFunction)
374 {
375 case GUEST_DISCONNECTED:
376 vrc = i_onGuestDisconnected(pCbCtx, pSvcCb);
377 break;
378
379 case GUEST_FILE_NOTIFY:
380 vrc = i_onFileNotify(pCbCtx, pSvcCb);
381 break;
382
383 default:
384 /* Silently ignore not implemented functions. */
385 vrc = VERR_NOT_SUPPORTED;
386 break;
387 }
388
389#ifdef DEBUG
390 LogFlowFuncLeaveRC(vrc);
391#endif
392 return vrc;
393}
394
395int GuestFile::i_closeFile(int *pGuestRc)
396{
397 LogFlowThisFunc(("strFile=%s\n", mData.mOpenInfo.mFileName.c_str()));
398
399 int vrc;
400
401 GuestWaitEvent *pEvent = NULL;
402 GuestEventTypes eventTypes;
403 try
404 {
405 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
406
407 vrc = registerWaitEvent(eventTypes, &pEvent);
408 }
409 catch (std::bad_alloc)
410 {
411 vrc = VERR_NO_MEMORY;
412 }
413
414 if (RT_FAILURE(vrc))
415 return vrc;
416
417 /* Prepare HGCM call. */
418 VBOXHGCMSVCPARM paParms[4];
419 int i = 0;
420 paParms[i++].setUInt32(pEvent->ContextID());
421 paParms[i++].setUInt32(mData.mID /* Guest file ID */);
422
423 vrc = sendCommand(HOST_FILE_CLOSE, i, paParms);
424 if (RT_SUCCESS(vrc))
425 vrc = i_waitForStatusChange(pEvent, 30 * 1000 /* Timeout in ms */,
426 NULL /* FileStatus */, pGuestRc);
427 unregisterWaitEvent(pEvent);
428
429 LogFlowFuncLeaveRC(vrc);
430 return vrc;
431}
432
433/* static */
434Utf8Str GuestFile::i_guestErrorToString(int guestRc)
435{
436 Utf8Str strError;
437
438 /** @todo pData->u32Flags: int vs. uint32 -- IPRT errors are *negative* !!! */
439 switch (guestRc)
440 {
441 case VERR_ALREADY_EXISTS:
442 strError += Utf8StrFmt(tr("File already exists"));
443 break;
444
445 case VERR_FILE_NOT_FOUND:
446 strError += Utf8StrFmt(tr("File not found"));
447 break;
448
449 case VERR_NET_HOST_NOT_FOUND:
450 strError += Utf8StrFmt(tr("Host name not found"));
451 break;
452
453 case VERR_SHARING_VIOLATION:
454 strError += Utf8StrFmt(tr("Sharing violation"));
455 break;
456
457 default:
458 strError += Utf8StrFmt("%Rrc", guestRc);
459 break;
460 }
461
462 return strError;
463}
464
465int GuestFile::i_onFileNotify(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
466{
467 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
468 AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
469
470 LogFlowThisFuncEnter();
471
472 if (pSvcCbData->mParms < 3)
473 return VERR_INVALID_PARAMETER;
474
475 int vrc = VINF_SUCCESS;
476
477 int idx = 1; /* Current parameter index. */
478 CALLBACKDATA_FILE_NOTIFY dataCb;
479 /* pSvcCb->mpaParms[0] always contains the context ID. */
480 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.uType);
481 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.rc);
482
483 FileStatus_T fileStatus = FileStatus_Undefined;
484 int guestRc = (int)dataCb.rc; /* uint32_t vs. int. */
485
486 LogFlowFunc(("uType=%RU32, guestRc=%Rrc\n",
487 dataCb.uType, guestRc));
488
489 if (RT_FAILURE(guestRc))
490 {
491 int rc2 = i_setFileStatus(FileStatus_Error, guestRc);
492 AssertRC(rc2);
493
494 rc2 = signalWaitEventInternal(pCbCtx,
495 guestRc, NULL /* pPayload */);
496 AssertRC(rc2);
497
498 return VINF_SUCCESS; /* Report to the guest. */
499 }
500
501 switch (dataCb.uType)
502 {
503 case GUEST_FILE_NOTIFYTYPE_ERROR:
504 {
505 int rc2 = i_setFileStatus(FileStatus_Error, guestRc);
506 AssertRC(rc2);
507
508 break;
509 }
510
511 case GUEST_FILE_NOTIFYTYPE_OPEN:
512 {
513 if (pSvcCbData->mParms == 4)
514 {
515 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.open.uHandle);
516
517 {
518 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
519 AssertMsg(mData.mID == VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID),
520 ("File ID %RU32 does not match context ID %RU32\n", mData.mID,
521 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pCbCtx->uContextID)));
522
523 /* Set the initial offset. On the guest the whole opening operation
524 * would fail if an initial seek isn't possible. */
525 mData.mOffCurrent = mData.mOpenInfo.mInitialOffset;
526 }
527
528 /* Set the process status. */
529 int rc2 = i_setFileStatus(FileStatus_Open, guestRc);
530 AssertRC(rc2);
531 }
532 else
533 vrc = VERR_NOT_SUPPORTED;
534
535 break;
536 }
537
538 case GUEST_FILE_NOTIFYTYPE_CLOSE:
539 {
540 int rc2 = i_setFileStatus(FileStatus_Closed, guestRc);
541 AssertRC(rc2);
542
543 break;
544 }
545
546 case GUEST_FILE_NOTIFYTYPE_READ:
547 {
548 if (pSvcCbData->mParms == 4)
549 {
550 pSvcCbData->mpaParms[idx++].getPointer(&dataCb.u.read.pvData,
551 &dataCb.u.read.cbData);
552 uint32_t cbRead = dataCb.u.read.cbData;
553
554 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
555
556 mData.mOffCurrent += cbRead;
557
558 alock.release();
559
560 com::SafeArray<BYTE> data((size_t)cbRead);
561 data.initFrom((BYTE*)dataCb.u.read.pvData, cbRead);
562
563 fireGuestFileReadEvent(mEventSource, mSession, this, mData.mOffCurrent,
564 cbRead, ComSafeArrayAsInParam(data));
565 }
566 else
567 vrc = VERR_NOT_SUPPORTED;
568 break;
569 }
570
571 case GUEST_FILE_NOTIFYTYPE_WRITE:
572 {
573 if (pSvcCbData->mParms == 4)
574 {
575 pSvcCbData->mpaParms[idx++].getUInt32(&dataCb.u.write.cbWritten);
576
577 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
578
579 mData.mOffCurrent += dataCb.u.write.cbWritten;
580 uint64_t uOffCurrent = mData.mOffCurrent;
581
582 alock.release();
583
584 fireGuestFileWriteEvent(mEventSource, mSession, this, uOffCurrent,
585 dataCb.u.write.cbWritten);
586 }
587 else
588 vrc = VERR_NOT_SUPPORTED;
589 break;
590 }
591
592 case GUEST_FILE_NOTIFYTYPE_SEEK:
593 {
594 if (pSvcCbData->mParms == 4)
595 {
596 pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.seek.uOffActual);
597
598 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
599
600 mData.mOffCurrent = dataCb.u.seek.uOffActual;
601
602 alock.release();
603
604 fireGuestFileOffsetChangedEvent(mEventSource, mSession, this,
605 dataCb.u.seek.uOffActual, 0 /* Processed */);
606 }
607 else
608 vrc = VERR_NOT_SUPPORTED;
609 break;
610 }
611
612 case GUEST_FILE_NOTIFYTYPE_TELL:
613 {
614 if (pSvcCbData->mParms == 4)
615 {
616 pSvcCbData->mpaParms[idx++].getUInt64(&dataCb.u.tell.uOffActual);
617
618 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
619
620 mData.mOffCurrent = dataCb.u.tell.uOffActual;
621
622 alock.release();
623
624 fireGuestFileOffsetChangedEvent(mEventSource, mSession, this,
625 dataCb.u.tell.uOffActual, 0 /* Processed */);
626 }
627 else
628 vrc = VERR_NOT_SUPPORTED;
629 break;
630 }
631
632 default:
633 vrc = VERR_NOT_SUPPORTED;
634 break;
635 }
636
637 if (RT_SUCCESS(vrc))
638 {
639 GuestWaitEventPayload payload(dataCb.uType, &dataCb, sizeof(dataCb));
640 int rc2 = signalWaitEventInternal(pCbCtx, guestRc, &payload);
641 AssertRC(rc2);
642 }
643
644 LogFlowThisFunc(("uType=%RU32, guestRc=%Rrc\n",
645 dataCb.uType, dataCb.rc));
646
647 LogFlowFuncLeaveRC(vrc);
648 return vrc;
649}
650
651int GuestFile::i_onGuestDisconnected(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData)
652{
653 AssertPtrReturn(pCbCtx, VERR_INVALID_POINTER);
654 AssertPtrReturn(pSvcCbData, VERR_INVALID_POINTER);
655
656 int vrc = i_setFileStatus(FileStatus_Down, VINF_SUCCESS);
657
658 LogFlowFuncLeaveRC(vrc);
659 return vrc;
660}
661
662/**
663 * Called by IGuestSession right before this file gets removed
664 * from the public file list.
665 */
666int GuestFile::i_onRemove(void)
667{
668 LogFlowThisFuncEnter();
669
670 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
671
672 int vrc = VINF_SUCCESS;
673
674 /*
675 * Note: The event source stuff holds references to this object,
676 * so make sure that this is cleaned up *before* calling uninit().
677 */
678 if (!mEventSource.isNull())
679 {
680 mEventSource->UnregisterListener(mLocalListener);
681
682 mLocalListener.setNull();
683 unconst(mEventSource).setNull();
684 }
685
686 LogFlowFuncLeaveRC(vrc);
687 return vrc;
688}
689
690int GuestFile::i_openFile(uint32_t uTimeoutMS, int *pGuestRc)
691{
692 LogFlowThisFuncEnter();
693
694 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
695
696 LogFlowThisFunc(("strFile=%s, enmAccessMode=%d (%s) enmOpenAction=%d (%s) uCreationMode=%RU32, uOffset=%RU64\n",
697 mData.mOpenInfo.mFileName.c_str(), mData.mOpenInfo.mAccessMode, mData.mOpenInfo.mpszAccessMode,
698 mData.mOpenInfo.mOpenAction, mData.mOpenInfo.mpszOpenAction, mData.mOpenInfo.mCreationMode,
699 mData.mOpenInfo.mInitialOffset));
700 int vrc;
701
702 GuestWaitEvent *pEvent = NULL;
703 GuestEventTypes eventTypes;
704 try
705 {
706 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
707
708 vrc = registerWaitEvent(eventTypes, &pEvent);
709 }
710 catch (std::bad_alloc)
711 {
712 vrc = VERR_NO_MEMORY;
713 }
714
715 if (RT_FAILURE(vrc))
716 return vrc;
717
718 /* Prepare HGCM call. */
719 VBOXHGCMSVCPARM paParms[8];
720 int i = 0;
721 paParms[i++].setUInt32(pEvent->ContextID());
722 paParms[i++].setPointer((void*)mData.mOpenInfo.mFileName.c_str(),
723 (ULONG)mData.mOpenInfo.mFileName.length() + 1);
724 paParms[i++].setString(mData.mOpenInfo.mpszAccessMode);
725 paParms[i++].setString(mData.mOpenInfo.mpszOpenAction);
726 paParms[i++].setString(""); /** @todo sharing mode. */
727 paParms[i++].setUInt32(mData.mOpenInfo.mCreationMode);
728 paParms[i++].setUInt64(mData.mOpenInfo.mInitialOffset);
729
730 alock.release(); /* Drop write lock before sending. */
731
732 vrc = sendCommand(HOST_FILE_OPEN, i, paParms);
733 if (RT_SUCCESS(vrc))
734 vrc = i_waitForStatusChange(pEvent, uTimeoutMS,
735 NULL /* FileStatus */, pGuestRc);
736
737 unregisterWaitEvent(pEvent);
738
739 LogFlowFuncLeaveRC(vrc);
740 return vrc;
741}
742
743int GuestFile::i_readData(uint32_t uSize, uint32_t uTimeoutMS,
744 void* pvData, uint32_t cbData, uint32_t* pcbRead)
745{
746 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
747 AssertReturn(cbData, VERR_INVALID_PARAMETER);
748
749 LogFlowThisFunc(("uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
750 uSize, uTimeoutMS, pvData, cbData));
751
752 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
753
754 int vrc;
755
756 GuestWaitEvent *pEvent = NULL;
757 GuestEventTypes eventTypes;
758 try
759 {
760 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
761 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
762
763 vrc = registerWaitEvent(eventTypes, &pEvent);
764 }
765 catch (std::bad_alloc)
766 {
767 vrc = VERR_NO_MEMORY;
768 }
769
770 if (RT_FAILURE(vrc))
771 return vrc;
772
773 /* Prepare HGCM call. */
774 VBOXHGCMSVCPARM paParms[4];
775 int i = 0;
776 paParms[i++].setUInt32(pEvent->ContextID());
777 paParms[i++].setUInt32(mData.mID /* File handle */);
778 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */);
779
780 alock.release(); /* Drop write lock before sending. */
781
782 uint32_t cbRead;
783 vrc = sendCommand(HOST_FILE_READ, i, paParms);
784 if (RT_SUCCESS(vrc))
785 vrc = i_waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead);
786
787 if (RT_SUCCESS(vrc))
788 {
789 LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
790
791 if (pcbRead)
792 *pcbRead = cbRead;
793 }
794
795 unregisterWaitEvent(pEvent);
796
797 LogFlowFuncLeaveRC(vrc);
798 return vrc;
799}
800
801int GuestFile::i_readDataAt(uint64_t uOffset, uint32_t uSize, uint32_t uTimeoutMS,
802 void* pvData, size_t cbData, size_t* pcbRead)
803{
804 LogFlowThisFunc(("uOffset=%RU64, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
805 uOffset, uSize, uTimeoutMS, pvData, cbData));
806
807 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
808
809 int vrc;
810
811 GuestWaitEvent *pEvent = NULL;
812 GuestEventTypes eventTypes;
813 try
814 {
815 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
816 eventTypes.push_back(VBoxEventType_OnGuestFileRead);
817
818 vrc = registerWaitEvent(eventTypes, &pEvent);
819 }
820 catch (std::bad_alloc)
821 {
822 vrc = VERR_NO_MEMORY;
823 }
824
825 if (RT_FAILURE(vrc))
826 return vrc;
827
828 /* Prepare HGCM call. */
829 VBOXHGCMSVCPARM paParms[4];
830 int i = 0;
831 paParms[i++].setUInt32(pEvent->ContextID());
832 paParms[i++].setUInt32(mData.mID /* File handle */);
833 paParms[i++].setUInt64(uOffset /* Offset (in bytes) to start reading */);
834 paParms[i++].setUInt32(uSize /* Size (in bytes) to read */);
835
836 alock.release(); /* Drop write lock before sending. */
837
838 uint32_t cbRead;
839 vrc = sendCommand(HOST_FILE_READ_AT, i, paParms);
840 if (RT_SUCCESS(vrc))
841 vrc = i_waitForRead(pEvent, uTimeoutMS, pvData, cbData, &cbRead);
842
843 if (RT_SUCCESS(vrc))
844 {
845 LogFlowThisFunc(("cbRead=%RU32\n", cbRead));
846
847 if (pcbRead)
848 *pcbRead = cbRead;
849 }
850
851 unregisterWaitEvent(pEvent);
852
853 LogFlowFuncLeaveRC(vrc);
854 return vrc;
855}
856
857int GuestFile::i_seekAt(int64_t iOffset, GUEST_FILE_SEEKTYPE eSeekType,
858 uint32_t uTimeoutMS, uint64_t *puOffset)
859{
860 LogFlowThisFunc(("iOffset=%RI64, uTimeoutMS=%RU32\n",
861 iOffset, uTimeoutMS));
862
863 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
864
865 int vrc;
866
867 GuestWaitEvent *pEvent = NULL;
868 GuestEventTypes eventTypes;
869 try
870 {
871 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
872 eventTypes.push_back(VBoxEventType_OnGuestFileOffsetChanged);
873
874 vrc = registerWaitEvent(eventTypes, &pEvent);
875 }
876 catch (std::bad_alloc)
877 {
878 vrc = VERR_NO_MEMORY;
879 }
880
881 if (RT_FAILURE(vrc))
882 return vrc;
883
884 /* Prepare HGCM call. */
885 VBOXHGCMSVCPARM paParms[4];
886 int i = 0;
887 paParms[i++].setUInt32(pEvent->ContextID());
888 paParms[i++].setUInt32(mData.mID /* File handle */);
889 paParms[i++].setUInt32(eSeekType /* Seek method */);
890 /** @todo uint64_t vs. int64_t! */
891 paParms[i++].setUInt64((uint64_t)iOffset /* Offset (in bytes) to start reading */);
892
893 alock.release(); /* Drop write lock before sending. */
894
895 vrc = sendCommand(HOST_FILE_SEEK, i, paParms);
896 if (RT_SUCCESS(vrc))
897 vrc = i_waitForOffsetChange(pEvent, uTimeoutMS, puOffset);
898
899 unregisterWaitEvent(pEvent);
900
901 LogFlowFuncLeaveRC(vrc);
902 return vrc;
903}
904
905/* static */
906HRESULT GuestFile::i_setErrorExternal(VirtualBoxBase *pInterface, int guestRc)
907{
908 AssertPtr(pInterface);
909 AssertMsg(RT_FAILURE(guestRc), ("Guest rc does not indicate a failure when setting error\n"));
910
911 return pInterface->setError(VBOX_E_IPRT_ERROR, GuestFile::i_guestErrorToString(guestRc).c_str());
912}
913
914int GuestFile::i_setFileStatus(FileStatus_T fileStatus, int fileRc)
915{
916 LogFlowThisFuncEnter();
917
918 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
919
920 LogFlowThisFunc(("oldStatus=%RU32, newStatus=%RU32, fileRc=%Rrc\n",
921 mData.mStatus, fileStatus, fileRc));
922
923#ifdef VBOX_STRICT
924 if (fileStatus == FileStatus_Error)
925 {
926 AssertMsg(RT_FAILURE(fileRc), ("Guest rc must be an error (%Rrc)\n", fileRc));
927 }
928 else
929 AssertMsg(RT_SUCCESS(fileRc), ("Guest rc must not be an error (%Rrc)\n", fileRc));
930#endif
931
932 if (mData.mStatus != fileStatus)
933 {
934 mData.mStatus = fileStatus;
935 mData.mLastError = fileRc;
936
937 ComObjPtr<VirtualBoxErrorInfo> errorInfo;
938 HRESULT hr = errorInfo.createObject();
939 ComAssertComRC(hr);
940 if (RT_FAILURE(fileRc))
941 {
942 hr = errorInfo->initEx(VBOX_E_IPRT_ERROR, fileRc,
943 COM_IIDOF(IGuestFile), getComponentName(),
944 i_guestErrorToString(fileRc));
945 ComAssertComRC(hr);
946 }
947
948 alock.release(); /* Release lock before firing off event. */
949
950 fireGuestFileStateChangedEvent(mEventSource, mSession,
951 this, fileStatus, errorInfo);
952 }
953
954 return VINF_SUCCESS;
955}
956
957int GuestFile::i_waitForOffsetChange(GuestWaitEvent *pEvent,
958 uint32_t uTimeoutMS, uint64_t *puOffset)
959{
960 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
961
962 VBoxEventType_T evtType;
963 ComPtr<IEvent> pIEvent;
964 int vrc = waitForEvent(pEvent, uTimeoutMS,
965 &evtType, pIEvent.asOutParam());
966 if (RT_SUCCESS(vrc))
967 {
968 if (evtType == VBoxEventType_OnGuestFileOffsetChanged)
969 {
970 if (puOffset)
971 {
972 ComPtr<IGuestFileOffsetChangedEvent> pFileEvent = pIEvent;
973 Assert(!pFileEvent.isNull());
974
975 HRESULT hr = pFileEvent->COMGETTER(Offset)((LONG64*)puOffset);
976 ComAssertComRC(hr);
977 }
978 }
979 else
980 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
981 }
982
983 return vrc;
984}
985
986int GuestFile::i_waitForRead(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
987 void *pvData, size_t cbData, uint32_t *pcbRead)
988{
989 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
990
991 VBoxEventType_T evtType;
992 ComPtr<IEvent> pIEvent;
993 int vrc = waitForEvent(pEvent, uTimeoutMS,
994 &evtType, pIEvent.asOutParam());
995 if (RT_SUCCESS(vrc))
996 {
997 if (evtType == VBoxEventType_OnGuestFileRead)
998 {
999 ComPtr<IGuestFileReadEvent> pFileEvent = pIEvent;
1000 Assert(!pFileEvent.isNull());
1001
1002 HRESULT hr;
1003 if (pvData)
1004 {
1005 com::SafeArray <BYTE> data;
1006 hr = pFileEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
1007 ComAssertComRC(hr);
1008 size_t cbRead = data.size();
1009 if ( cbRead
1010 && cbRead <= cbData)
1011 {
1012 memcpy(pvData, data.raw(), data.size());
1013 }
1014 else
1015 vrc = VERR_BUFFER_OVERFLOW;
1016 }
1017 if (pcbRead)
1018 {
1019 hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbRead);
1020 ComAssertComRC(hr);
1021 }
1022 }
1023 else
1024 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
1025 }
1026
1027 return vrc;
1028}
1029
1030int GuestFile::i_waitForStatusChange(GuestWaitEvent *pEvent, uint32_t uTimeoutMS,
1031 FileStatus_T *pFileStatus, int *pGuestRc)
1032{
1033 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1034 /* pFileStatus is optional. */
1035
1036 VBoxEventType_T evtType;
1037 ComPtr<IEvent> pIEvent;
1038 int vrc = waitForEvent(pEvent, uTimeoutMS,
1039 &evtType, pIEvent.asOutParam());
1040 if (RT_SUCCESS(vrc))
1041 {
1042 Assert(evtType == VBoxEventType_OnGuestFileStateChanged);
1043 ComPtr<IGuestFileStateChangedEvent> pFileEvent = pIEvent;
1044 Assert(!pFileEvent.isNull());
1045
1046 HRESULT hr;
1047 if (pFileStatus)
1048 {
1049 hr = pFileEvent->COMGETTER(Status)(pFileStatus);
1050 ComAssertComRC(hr);
1051 }
1052
1053 ComPtr<IVirtualBoxErrorInfo> errorInfo;
1054 hr = pFileEvent->COMGETTER(Error)(errorInfo.asOutParam());
1055 ComAssertComRC(hr);
1056
1057 LONG lGuestRc;
1058 hr = errorInfo->COMGETTER(ResultDetail)(&lGuestRc);
1059 ComAssertComRC(hr);
1060
1061 LogFlowThisFunc(("resultDetail=%RI32 (%Rrc)\n",
1062 lGuestRc, lGuestRc));
1063
1064 if (RT_FAILURE((int)lGuestRc))
1065 vrc = VERR_GSTCTL_GUEST_ERROR;
1066
1067 if (pGuestRc)
1068 *pGuestRc = (int)lGuestRc;
1069 }
1070
1071 return vrc;
1072}
1073
1074int GuestFile::i_waitForWrite(GuestWaitEvent *pEvent,
1075 uint32_t uTimeoutMS, uint32_t *pcbWritten)
1076{
1077 AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
1078
1079 VBoxEventType_T evtType;
1080 ComPtr<IEvent> pIEvent;
1081 int vrc = waitForEvent(pEvent, uTimeoutMS,
1082 &evtType, pIEvent.asOutParam());
1083 if (RT_SUCCESS(vrc))
1084 {
1085 if (evtType == VBoxEventType_OnGuestFileWrite)
1086 {
1087 if (pcbWritten)
1088 {
1089 ComPtr<IGuestFileWriteEvent> pFileEvent = pIEvent;
1090 Assert(!pFileEvent.isNull());
1091
1092 HRESULT hr = pFileEvent->COMGETTER(Processed)((ULONG*)pcbWritten);
1093 ComAssertComRC(hr);
1094 }
1095 }
1096 else
1097 vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
1098 }
1099
1100 return vrc;
1101}
1102
1103int GuestFile::i_writeData(uint32_t uTimeoutMS, void *pvData, uint32_t cbData,
1104 uint32_t *pcbWritten)
1105{
1106 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1107 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1108
1109 LogFlowThisFunc(("uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
1110 uTimeoutMS, pvData, cbData));
1111
1112 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1113
1114 int vrc;
1115
1116 GuestWaitEvent *pEvent = NULL;
1117 GuestEventTypes eventTypes;
1118 try
1119 {
1120 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
1121 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
1122
1123 vrc = registerWaitEvent(eventTypes, &pEvent);
1124 }
1125 catch (std::bad_alloc)
1126 {
1127 vrc = VERR_NO_MEMORY;
1128 }
1129
1130 if (RT_FAILURE(vrc))
1131 return vrc;
1132
1133 /* Prepare HGCM call. */
1134 VBOXHGCMSVCPARM paParms[8];
1135 int i = 0;
1136 paParms[i++].setUInt32(pEvent->ContextID());
1137 paParms[i++].setUInt32(mData.mID /* File handle */);
1138 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */);
1139 paParms[i++].setPointer(pvData, cbData);
1140
1141 alock.release(); /* Drop write lock before sending. */
1142
1143 uint32_t cbWritten;
1144 vrc = sendCommand(HOST_FILE_WRITE, i, paParms);
1145 if (RT_SUCCESS(vrc))
1146 vrc = i_waitForWrite(pEvent, uTimeoutMS, &cbWritten);
1147
1148 if (RT_SUCCESS(vrc))
1149 {
1150 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
1151
1152 if (cbWritten)
1153 *pcbWritten = cbWritten;
1154 }
1155
1156 unregisterWaitEvent(pEvent);
1157
1158 LogFlowFuncLeaveRC(vrc);
1159 return vrc;
1160}
1161
1162int GuestFile::i_writeDataAt(uint64_t uOffset, uint32_t uTimeoutMS,
1163 void *pvData, uint32_t cbData, uint32_t *pcbWritten)
1164{
1165 AssertPtrReturn(pvData, VERR_INVALID_POINTER);
1166 AssertReturn(cbData, VERR_INVALID_PARAMETER);
1167
1168 LogFlowThisFunc(("uOffset=%RU64, uTimeoutMS=%RU32, pvData=%p, cbData=%zu\n",
1169 uOffset, uTimeoutMS, pvData, cbData));
1170
1171 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1172
1173 int vrc;
1174
1175 GuestWaitEvent *pEvent = NULL;
1176 GuestEventTypes eventTypes;
1177 try
1178 {
1179 eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
1180 eventTypes.push_back(VBoxEventType_OnGuestFileWrite);
1181
1182 vrc = registerWaitEvent(eventTypes, &pEvent);
1183 }
1184 catch (std::bad_alloc)
1185 {
1186 vrc = VERR_NO_MEMORY;
1187 }
1188
1189 if (RT_FAILURE(vrc))
1190 return vrc;
1191
1192 /* Prepare HGCM call. */
1193 VBOXHGCMSVCPARM paParms[8];
1194 int i = 0;
1195 paParms[i++].setUInt32(pEvent->ContextID());
1196 paParms[i++].setUInt32(mData.mID /* File handle */);
1197 paParms[i++].setUInt64(uOffset /* Offset where to starting writing */);
1198 paParms[i++].setUInt32(cbData /* Size (in bytes) to write */);
1199 paParms[i++].setPointer(pvData, cbData);
1200
1201 alock.release(); /* Drop write lock before sending. */
1202
1203 uint32_t cbWritten;
1204 vrc = sendCommand(HOST_FILE_WRITE_AT, i, paParms);
1205 if (RT_SUCCESS(vrc))
1206 vrc = i_waitForWrite(pEvent, uTimeoutMS, &cbWritten);
1207
1208 if (RT_SUCCESS(vrc))
1209 {
1210 LogFlowThisFunc(("cbWritten=%RU32\n", cbWritten));
1211
1212 if (cbWritten)
1213 *pcbWritten = cbWritten;
1214 }
1215
1216 unregisterWaitEvent(pEvent);
1217
1218 LogFlowFuncLeaveRC(vrc);
1219 return vrc;
1220}
1221
1222// Wrapped IGuestFile methods
1223/////////////////////////////////////////////////////////////////////////////
1224HRESULT GuestFile::close()
1225{
1226#ifndef VBOX_WITH_GUEST_CONTROL
1227 ReturnComNotImplemented();
1228#else
1229 LogFlowThisFuncEnter();
1230
1231 /* Close file on guest. */
1232 int guestRc;
1233 int rc = i_closeFile(&guestRc);
1234 /* On failure don't return here, instead do all the cleanup
1235 * work first and then return an error. */
1236
1237 AssertPtr(mSession);
1238 int rc2 = mSession->i_fileRemoveFromList(this);
1239 if (RT_SUCCESS(rc))
1240 rc = rc2;
1241
1242 if (RT_FAILURE(rc))
1243 {
1244 if (rc == VERR_GSTCTL_GUEST_ERROR)
1245 return GuestFile::i_setErrorExternal(this, guestRc);
1246
1247 return setError(VBOX_E_IPRT_ERROR,
1248 tr("Closing guest file failed with %Rrc\n"), rc);
1249 }
1250
1251 LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
1252 return S_OK;
1253#endif /* VBOX_WITH_GUEST_CONTROL */
1254}
1255
1256HRESULT GuestFile::queryInfo(ComPtr<IFsObjInfo> &aObjInfo)
1257{
1258#ifndef VBOX_WITH_GUEST_CONTROL
1259 ReturnComNotImplemented();
1260#else
1261 ReturnComNotImplemented();
1262#endif /* VBOX_WITH_GUEST_CONTROL */
1263}
1264
1265HRESULT GuestFile::querySize(LONG64 *aSize)
1266{
1267#ifndef VBOX_WITH_GUEST_CONTROL
1268 ReturnComNotImplemented();
1269#else
1270 ReturnComNotImplemented();
1271#endif /* VBOX_WITH_GUEST_CONTROL */
1272}
1273
1274HRESULT GuestFile::read(ULONG aToRead, ULONG aTimeoutMS, std::vector<BYTE> &aData)
1275{
1276#ifndef VBOX_WITH_GUEST_CONTROL
1277 ReturnComNotImplemented();
1278#else
1279 if (aToRead == 0)
1280 return setError(E_INVALIDARG, tr("The size to read is zero"));
1281
1282 aData.resize(aToRead);
1283
1284 HRESULT hr = S_OK;
1285
1286 uint32_t cbRead;
1287 int vrc = i_readData(aToRead, aTimeoutMS,
1288 &aData.front(), aToRead, &cbRead);
1289
1290 if (RT_SUCCESS(vrc))
1291 {
1292 if (aData.size() != cbRead)
1293 aData.resize(cbRead);
1294 }
1295 else
1296 {
1297 aData.resize(0);
1298
1299 switch (vrc)
1300 {
1301 default:
1302 hr = setError(VBOX_E_IPRT_ERROR,
1303 tr("Reading from file \"%s\" failed: %Rrc"),
1304 mData.mOpenInfo.mFileName.c_str(), vrc);
1305 break;
1306 }
1307 }
1308
1309 LogFlowFuncLeaveRC(vrc);
1310 return hr;
1311#endif /* VBOX_WITH_GUEST_CONTROL */
1312}
1313HRESULT GuestFile::readAt(LONG64 aOffset, ULONG aToRead, ULONG aTimeoutMS, std::vector<BYTE> &aData)
1314
1315{
1316#ifndef VBOX_WITH_GUEST_CONTROL
1317 ReturnComNotImplemented();
1318#else
1319 if (aToRead == 0)
1320 return setError(E_INVALIDARG, tr("The size to read is zero"));
1321
1322 aData.resize(aToRead);
1323
1324 HRESULT hr = S_OK;
1325
1326 size_t cbRead;
1327 int vrc = i_readDataAt(aOffset, aToRead, aTimeoutMS,
1328 &aData.front(), aToRead, &cbRead);
1329 if (RT_SUCCESS(vrc))
1330 {
1331 if (aData.size() != cbRead)
1332 aData.resize(cbRead);
1333 }
1334 else
1335 {
1336 aData.resize(0);
1337
1338 switch (vrc)
1339 {
1340 default:
1341 hr = setError(VBOX_E_IPRT_ERROR,
1342 tr("Reading from file \"%s\" (at offset %RU64) failed: %Rrc"),
1343 mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1344 break;
1345 }
1346 }
1347
1348 LogFlowFuncLeaveRC(vrc);
1349 return hr;
1350#endif /* VBOX_WITH_GUEST_CONTROL */
1351}
1352
1353HRESULT GuestFile::seek(LONG64 aOffset, FileSeekOrigin_T aWhence, LONG64 *aNewOffset)
1354{
1355#ifndef VBOX_WITH_GUEST_CONTROL
1356 ReturnComNotImplemented();
1357#else
1358 LogFlowThisFuncEnter();
1359
1360 HRESULT hr = S_OK;
1361
1362 GUEST_FILE_SEEKTYPE eSeekType;
1363 switch (aWhence)
1364 {
1365 case FileSeekOrigin_Set:
1366 eSeekType = GUEST_FILE_SEEKTYPE_BEGIN;
1367 break;
1368
1369 case FileSeekOrigin_Current:
1370 eSeekType = GUEST_FILE_SEEKTYPE_CURRENT;
1371 break;
1372
1373 case FileSeekOrigin_End:
1374 eSeekType = GUEST_FILE_SEEKTYPE_END;
1375 break;
1376
1377 default:
1378 return setError(E_INVALIDARG, tr("Invalid seek type specified"));
1379 break; /* Never reached. */
1380 }
1381
1382 uint64_t uNewOffset;
1383 int vrc = i_seekAt(aOffset, eSeekType,
1384 30 * 1000 /* 30s timeout */, &uNewOffset);
1385 if (RT_SUCCESS(vrc))
1386 *aNewOffset = RT_MIN(uNewOffset, (uint64_t)INT64_MAX);
1387 else
1388 {
1389 switch (vrc)
1390 {
1391 default:
1392 hr = setError(VBOX_E_IPRT_ERROR,
1393 tr("Seeking file \"%s\" (to offset %RI64) failed: %Rrc"),
1394 mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1395 break;
1396 }
1397 }
1398
1399 LogFlowFuncLeaveRC(vrc);
1400 return hr;
1401#endif /* VBOX_WITH_GUEST_CONTROL */
1402}
1403
1404HRESULT GuestFile::setACL(const com::Utf8Str &aAcl, ULONG aMode)
1405{
1406#ifndef VBOX_WITH_GUEST_CONTROL
1407 ReturnComNotImplemented();
1408#else
1409 ReturnComNotImplemented();
1410#endif /* VBOX_WITH_GUEST_CONTROL */
1411}
1412
1413HRESULT GuestFile::setSize(LONG64 aSize)
1414{
1415#ifndef VBOX_WITH_GUEST_CONTROL
1416 ReturnComNotImplemented();
1417#else
1418 ReturnComNotImplemented();
1419#endif /* VBOX_WITH_GUEST_CONTROL */
1420}
1421
1422HRESULT GuestFile::write(const std::vector<BYTE> &aData, ULONG aTimeoutMS, ULONG *aWritten)
1423{
1424#ifndef VBOX_WITH_GUEST_CONTROL
1425 ReturnComNotImplemented();
1426#else
1427 LogFlowThisFuncEnter();
1428
1429 HRESULT hr = S_OK;
1430
1431 uint32_t cbData = (uint32_t)aData.size();
1432 void *pvData = cbData > 0? (void *)&aData.front(): NULL;
1433 int vrc = i_writeData(aTimeoutMS, pvData, cbData,
1434 (uint32_t*)aWritten);
1435 if (RT_FAILURE(vrc))
1436 {
1437 switch (vrc)
1438 {
1439 default:
1440 hr = setError(VBOX_E_IPRT_ERROR,
1441 tr("Writing %zubytes to file \"%s\" failed: %Rrc"),
1442 aData.size(), mData.mOpenInfo.mFileName.c_str(), vrc);
1443 break;
1444 }
1445 }
1446
1447 LogFlowFuncLeaveRC(vrc);
1448 return hr;
1449#endif /* VBOX_WITH_GUEST_CONTROL */
1450}
1451
1452HRESULT GuestFile::writeAt(LONG64 aOffset, const std::vector<BYTE> &aData, ULONG aTimeoutMS, ULONG *aWritten)
1453
1454{
1455#ifndef VBOX_WITH_GUEST_CONTROL
1456 ReturnComNotImplemented();
1457#else
1458 LogFlowThisFuncEnter();
1459
1460 HRESULT hr = S_OK;
1461
1462 uint32_t cbData = (uint32_t)aData.size();
1463 void *pvData = cbData > 0? (void *)&aData.front(): NULL;
1464 int vrc = i_writeData(aTimeoutMS, pvData, cbData,
1465 (uint32_t*)aWritten);
1466 if (RT_FAILURE(vrc))
1467 {
1468 switch (vrc)
1469 {
1470 default:
1471 hr = setError(VBOX_E_IPRT_ERROR,
1472 tr("Writing %zubytes to file \"%s\" (at offset %RU64) failed: %Rrc"),
1473 aData.size(), mData.mOpenInfo.mFileName.c_str(), aOffset, vrc);
1474 break;
1475 }
1476 }
1477
1478 LogFlowFuncLeaveRC(vrc);
1479 return hr;
1480#endif /* VBOX_WITH_GUEST_CONTROL */
1481}
1482
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