VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/VFSExplorerImpl.cpp@ 48935

Last change on this file since 48935 was 47922, checked in by vboxsync, 11 years ago

Main: IVFSExplorer use LONG64 for file sizes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1/* $Id: VFSExplorerImpl.cpp 47922 2013-08-20 14:36:24Z vboxsync $ */
2/** @file
3 *
4 * IVFSExplorer COM class implementations.
5 */
6
7/*
8 * Copyright (C) 2009-2011 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#include <iprt/dir.h>
20#include <iprt/path.h>
21#include <iprt/file.h>
22#include <iprt/s3.h>
23#include <iprt/cpp/utils.h>
24
25#include <VBox/com/array.h>
26
27#include <VBox/param.h>
28#include <VBox/version.h>
29
30#include "VFSExplorerImpl.h"
31#include "VirtualBoxImpl.h"
32#include "ProgressImpl.h"
33
34#include "AutoCaller.h"
35#include "Logging.h"
36
37#include <memory>
38
39////////////////////////////////////////////////////////////////////////////////
40//
41// VFSExplorer definitions
42//
43////////////////////////////////////////////////////////////////////////////////
44
45/* opaque private instance data of VFSExplorer class */
46struct VFSExplorer::Data
47{
48 struct DirEntry
49 {
50 DirEntry(Utf8Str strName, VFSFileType_T fileType, uint64_t cbSize, uint32_t fMode)
51 : name(strName)
52 , type(fileType)
53 , size(cbSize)
54 , mode(fMode) {}
55
56 Utf8Str name;
57 VFSFileType_T type;
58 uint64_t size;
59 uint32_t mode;
60 };
61
62 VFSType_T storageType;
63 Utf8Str strUsername;
64 Utf8Str strPassword;
65 Utf8Str strHostname;
66 Utf8Str strPath;
67 Utf8Str strBucket;
68
69 std::list<DirEntry> entryList;
70};
71
72VFSExplorer::VFSExplorer()
73 : mVirtualBox(NULL)
74{
75}
76
77VFSExplorer::~VFSExplorer()
78{
79}
80
81
82/**
83 * VFSExplorer COM initializer.
84 * @param
85 * @return
86 */
87HRESULT VFSExplorer::init(VFSType_T aType, Utf8Str aFilePath, Utf8Str aHostname, Utf8Str aUsername, Utf8Str aPassword, VirtualBox *aVirtualBox)
88{
89 /* Enclose the state transition NotReady->InInit->Ready */
90 AutoInitSpan autoInitSpan(this);
91 AssertReturn(autoInitSpan.isOk(), E_FAIL);
92
93 /* Weak reference to a VirtualBox object */
94 unconst(mVirtualBox) = aVirtualBox;
95
96 /* initialize data */
97 m = new Data;
98
99 m->storageType = aType;
100 m->strPath = aFilePath;
101 m->strHostname = aHostname;
102 m->strUsername = aUsername;
103 m->strPassword = aPassword;
104
105 if (m->storageType == VFSType_S3)
106 {
107 size_t bpos = aFilePath.find("/", 1);
108 if (bpos != Utf8Str::npos)
109 {
110 m->strBucket = aFilePath.substr(1, bpos - 1); /* The bucket without any slashes */
111 aFilePath = aFilePath.substr(bpos); /* The rest of the file path */
112 }
113 }
114
115 /* Confirm a successful initialization */
116 autoInitSpan.setSucceeded();
117
118 return S_OK;
119}
120
121/**
122 * VFSExplorer COM uninitializer.
123 * @return
124 */
125void VFSExplorer::uninit()
126{
127 delete m;
128 m = NULL;
129}
130
131/**
132 * Public method implementation.
133 * @param
134 * @return
135 */
136STDMETHODIMP VFSExplorer::COMGETTER(Path)(BSTR *aPath)
137{
138 if (!aPath)
139 return E_POINTER;
140
141 AutoCaller autoCaller(this);
142 if (FAILED(autoCaller.rc())) return autoCaller.rc();
143
144 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
145
146 Bstr bstrPath(m->strPath);
147 bstrPath.cloneTo(aPath);
148
149 return S_OK;
150}
151
152STDMETHODIMP VFSExplorer::COMGETTER(Type)(VFSType_T *aType)
153{
154 if (!aType)
155 return E_POINTER;
156
157 AutoCaller autoCaller(this);
158 if (FAILED(autoCaller.rc())) return autoCaller.rc();
159
160 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
161
162 *aType = m->storageType;
163
164 return S_OK;
165}
166
167struct VFSExplorer::TaskVFSExplorer
168{
169 enum TaskType
170 {
171 Update,
172 Delete
173 };
174
175 TaskVFSExplorer(TaskType aTaskType, VFSExplorer *aThat, Progress *aProgress)
176 : taskType(aTaskType),
177 pVFSExplorer(aThat),
178 progress(aProgress),
179 rc(S_OK)
180 {}
181 ~TaskVFSExplorer() {}
182
183 int startThread();
184 static int taskThread(RTTHREAD aThread, void *pvUser);
185 static int uploadProgress(unsigned uPercent, void *pvUser);
186
187 TaskType taskType;
188 VFSExplorer *pVFSExplorer;
189 ComObjPtr<Progress> progress;
190 HRESULT rc;
191
192 /* task data */
193 std::list<Utf8Str> filenames;
194};
195
196int VFSExplorer::TaskVFSExplorer::startThread()
197{
198 int vrc = RTThreadCreate(NULL, VFSExplorer::TaskVFSExplorer::taskThread, this,
199 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
200 "Explorer::Task");
201
202 if (RT_FAILURE(vrc))
203 return VFSExplorer::setErrorStatic(E_FAIL, Utf8StrFmt("Could not create taskThreadVFS (%Rrc)\n", vrc));
204
205 return vrc;
206}
207
208/* static */
209DECLCALLBACK(int) VFSExplorer::TaskVFSExplorer::taskThread(RTTHREAD /* aThread */, void *pvUser)
210{
211 std::auto_ptr<TaskVFSExplorer> task(static_cast<TaskVFSExplorer*>(pvUser));
212 AssertReturn(task.get(), VERR_GENERAL_FAILURE);
213
214 VFSExplorer *pVFSExplorer = task->pVFSExplorer;
215
216 LogFlowFuncEnter();
217 LogFlowFunc(("VFSExplorer %p\n", pVFSExplorer));
218
219 HRESULT rc = S_OK;
220
221 switch(task->taskType)
222 {
223 case TaskVFSExplorer::Update:
224 {
225 if (pVFSExplorer->m->storageType == VFSType_File)
226 rc = pVFSExplorer->updateFS(task.get());
227 else if (pVFSExplorer->m->storageType == VFSType_S3)
228#ifdef VBOX_WITH_S3
229 rc = pVFSExplorer->updateS3(task.get());
230#else
231 rc = VERR_NOT_IMPLEMENTED;
232#endif
233 break;
234 }
235 case TaskVFSExplorer::Delete:
236 {
237 if (pVFSExplorer->m->storageType == VFSType_File)
238 rc = pVFSExplorer->deleteFS(task.get());
239 else if (pVFSExplorer->m->storageType == VFSType_S3)
240#ifdef VBOX_WITH_S3
241 rc = pVFSExplorer->deleteS3(task.get());
242#else
243 rc = VERR_NOT_IMPLEMENTED;
244#endif
245 break;
246 }
247 default:
248 AssertMsgFailed(("Invalid task type %u specified!\n", task->taskType));
249 break;
250 }
251
252 LogFlowFunc(("rc=%Rhrc\n", rc)); NOREF(rc);
253 LogFlowFuncLeave();
254
255 return VINF_SUCCESS;
256}
257
258/* static */
259int VFSExplorer::TaskVFSExplorer::uploadProgress(unsigned uPercent, void *pvUser)
260{
261 VFSExplorer::TaskVFSExplorer* pTask = *(VFSExplorer::TaskVFSExplorer**)pvUser;
262
263 if (pTask &&
264 !pTask->progress.isNull())
265 {
266 BOOL fCanceled;
267 pTask->progress->COMGETTER(Canceled)(&fCanceled);
268 if (fCanceled)
269 return -1;
270 pTask->progress->SetCurrentOperationProgress(uPercent);
271 }
272 return VINF_SUCCESS;
273}
274
275VFSFileType_T VFSExplorer::RTToVFSFileType(int aType) const
276{
277 int a = aType & RTFS_TYPE_MASK;
278 VFSFileType_T t = VFSFileType_Unknown;
279 if ((a & RTFS_TYPE_DIRECTORY) == RTFS_TYPE_DIRECTORY)
280 t = VFSFileType_Directory;
281 else if ((a & RTFS_TYPE_FILE) == RTFS_TYPE_FILE)
282 t = VFSFileType_File;
283 else if ((a & RTFS_TYPE_SYMLINK) == RTFS_TYPE_SYMLINK)
284 t = VFSFileType_SymLink;
285 else if ((a & RTFS_TYPE_FIFO) == RTFS_TYPE_FIFO)
286 t = VFSFileType_Fifo;
287 else if ((a & RTFS_TYPE_DEV_CHAR) == RTFS_TYPE_DEV_CHAR)
288 t = VFSFileType_DevChar;
289 else if ((a & RTFS_TYPE_DEV_BLOCK) == RTFS_TYPE_DEV_BLOCK)
290 t = VFSFileType_DevBlock;
291 else if ((a & RTFS_TYPE_SOCKET) == RTFS_TYPE_SOCKET)
292 t = VFSFileType_Socket;
293 else if ((a & RTFS_TYPE_WHITEOUT) == RTFS_TYPE_WHITEOUT)
294 t = VFSFileType_WhiteOut;
295
296 return t;
297}
298
299HRESULT VFSExplorer::updateFS(TaskVFSExplorer *aTask)
300{
301 LogFlowFuncEnter();
302
303 AutoCaller autoCaller(this);
304 if (FAILED(autoCaller.rc())) return autoCaller.rc();
305
306 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
307
308 HRESULT rc = S_OK;
309
310 std::list<VFSExplorer::Data::DirEntry> fileList;
311 char *pszPath = NULL;
312 PRTDIR pDir = NULL;
313 try
314 {
315 int vrc = RTDirOpen(&pDir, m->strPath.c_str());
316 if (RT_FAILURE(vrc))
317 throw setError(VBOX_E_FILE_ERROR, tr ("Can't open directory '%s' (%Rrc)"), pszPath, vrc);
318
319 if (aTask->progress)
320 aTask->progress->SetCurrentOperationProgress(33);
321 RTDIRENTRYEX entry;
322 while (RT_SUCCESS(vrc))
323 {
324 vrc = RTDirReadEx(pDir, &entry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
325 if (RT_SUCCESS(vrc))
326 {
327 Utf8Str name(entry.szName);
328 if ( name != "."
329 && name != "..")
330 fileList.push_back(VFSExplorer::Data::DirEntry(name, RTToVFSFileType(entry.Info.Attr.fMode), entry.Info.cbObject, entry.Info.Attr.fMode & (RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXG | RTFS_UNIX_IRWXO)));
331 }
332 }
333 if (aTask->progress)
334 aTask->progress->SetCurrentOperationProgress(66);
335 }
336 catch(HRESULT aRC)
337 {
338 rc = aRC;
339 }
340
341 /* Clean up */
342 if (pszPath)
343 RTStrFree(pszPath);
344 if (pDir)
345 RTDirClose(pDir);
346
347 if (aTask->progress)
348 aTask->progress->SetCurrentOperationProgress(99);
349
350 /* Assign the result on success (this clears the old list) */
351 if (rc == S_OK)
352 m->entryList.assign(fileList.begin(), fileList.end());
353
354 aTask->rc = rc;
355
356 if (!aTask->progress.isNull())
357 aTask->progress->notifyComplete(rc);
358
359 LogFlowFunc(("rc=%Rhrc\n", rc));
360 LogFlowFuncLeave();
361
362 return VINF_SUCCESS;
363}
364
365HRESULT VFSExplorer::deleteFS(TaskVFSExplorer *aTask)
366{
367 LogFlowFuncEnter();
368
369 AutoCaller autoCaller(this);
370 if (FAILED(autoCaller.rc())) return autoCaller.rc();
371
372 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
373
374 HRESULT rc = S_OK;
375
376 float fPercentStep = 100.0f / aTask->filenames.size();
377 try
378 {
379 char szPath[RTPATH_MAX];
380 std::list<Utf8Str>::const_iterator it;
381 size_t i = 0;
382 for (it = aTask->filenames.begin();
383 it != aTask->filenames.end();
384 ++it, ++i)
385 {
386 int vrc = RTPathJoin(szPath, sizeof(szPath), m->strPath.c_str(), (*it).c_str());
387 if (RT_FAILURE(vrc))
388 throw setError(E_FAIL, tr("Internal Error (%Rrc)"), vrc);
389 vrc = RTFileDelete(szPath);
390 if (RT_FAILURE(vrc))
391 throw setError(VBOX_E_FILE_ERROR, tr("Can't delete file '%s' (%Rrc)"), szPath, vrc);
392 if (aTask->progress)
393 aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
394 }
395 }
396 catch(HRESULT aRC)
397 {
398 rc = aRC;
399 }
400
401 aTask->rc = rc;
402
403 if (!aTask->progress.isNull())
404 aTask->progress->notifyComplete(rc);
405
406 LogFlowFunc(("rc=%Rhrc\n", rc));
407 LogFlowFuncLeave();
408
409 return VINF_SUCCESS;
410}
411
412#ifdef VBOX_WITH_S3
413HRESULT VFSExplorer::updateS3(TaskVFSExplorer *aTask)
414{
415 LogFlowFuncEnter();
416
417 AutoCaller autoCaller(this);
418 if (FAILED(autoCaller.rc())) return autoCaller.rc();
419
420 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
421
422 HRESULT rc = S_OK;
423
424 RTS3 hS3 = NULL;
425 std::list<VFSExplorer::Data::DirEntry> fileList;
426 try
427 {
428 int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(), m->strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING);
429 if (RT_FAILURE(vrc))
430 throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
431
432 RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
433 /* Do we need the list of buckets or keys? */
434 if (m->strBucket.isEmpty())
435 {
436 PCRTS3BUCKETENTRY pBuckets = NULL;
437 vrc = RTS3GetBuckets(hS3, &pBuckets);
438 if (RT_FAILURE(vrc))
439 throw setError(E_FAIL, tr ("Can't get buckets (%Rrc)"), vrc);
440
441 PCRTS3BUCKETENTRY pTmpBuckets = pBuckets;
442 while (pBuckets)
443 {
444 /* Set always read/write permissions of the current logged in user. */
445 fileList.push_back(VFSExplorer::Data::DirEntry(pBuckets->pszName, VFSFileType_Directory, 0, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR));
446 pBuckets = pBuckets->pNext;
447 }
448 RTS3BucketsDestroy(pTmpBuckets);
449 }
450 else
451 {
452 PCRTS3KEYENTRY pKeys = NULL;
453 vrc = RTS3GetBucketKeys(hS3, m->strBucket.c_str(), &pKeys);
454 if (RT_FAILURE(vrc))
455 throw setError(E_FAIL, tr ("Can't get keys for bucket (%Rrc)"), vrc);
456
457 PCRTS3KEYENTRY pTmpKeys = pKeys;
458 while (pKeys)
459 {
460 Utf8Str name(pKeys->pszName);
461 /* Set always read/write permissions of the current logged in user. */
462 fileList.push_back(VFSExplorer::Data::DirEntry(pKeys->pszName, VFSFileType_File, pKeys->cbFile, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR));
463 pKeys = pKeys->pNext;
464 }
465 RTS3KeysDestroy(pTmpKeys);
466 }
467 }
468 catch(HRESULT aRC)
469 {
470 rc = aRC;
471 }
472
473 if (hS3 != NULL)
474 RTS3Destroy(hS3);
475
476 /* Assign the result on success (this clears the old list) */
477 if (rc == S_OK)
478 m->entryList.assign(fileList.begin(), fileList.end());
479
480 aTask->rc = rc;
481
482 if (!aTask->progress.isNull())
483 aTask->progress->notifyComplete(rc);
484
485 LogFlowFunc(("rc=%Rhrc\n", rc));
486 LogFlowFuncLeave();
487
488 return VINF_SUCCESS;
489}
490
491HRESULT VFSExplorer::deleteS3(TaskVFSExplorer *aTask)
492{
493 LogFlowFuncEnter();
494
495 AutoCaller autoCaller(this);
496 if (FAILED(autoCaller.rc())) return autoCaller.rc();
497
498 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
499
500 HRESULT rc = S_OK;
501
502 RTS3 hS3 = NULL;
503 float fPercentStep = 100.0f / aTask->filenames.size();
504 try
505 {
506 int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(), m->strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING);
507 if (RT_FAILURE(vrc))
508 throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
509
510 RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
511
512 std::list<Utf8Str>::const_iterator it;
513 size_t i = 0;
514 for (it = aTask->filenames.begin();
515 it != aTask->filenames.end();
516 ++it, ++i)
517 {
518 vrc = RTS3DeleteKey(hS3, m->strBucket.c_str(), (*it).c_str());
519 if (RT_FAILURE(vrc))
520 throw setError(VBOX_E_FILE_ERROR, tr ("Can't delete file '%s' (%Rrc)"), (*it).c_str(), vrc);
521 if (aTask->progress)
522 aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
523 }
524 }
525 catch(HRESULT aRC)
526 {
527 rc = aRC;
528 }
529
530 aTask->rc = rc;
531
532 if (hS3 != NULL)
533 RTS3Destroy(hS3);
534
535 if (!aTask->progress.isNull())
536 aTask->progress->notifyComplete(rc);
537
538 LogFlowFunc(("rc=%Rhrc\n", rc));
539 LogFlowFuncLeave();
540
541 return VINF_SUCCESS;
542}
543#endif /* VBOX_WITH_S3 */
544
545STDMETHODIMP VFSExplorer::Update(IProgress **aProgress)
546{
547 CheckComArgOutPointerValid(aProgress);
548
549 AutoCaller autoCaller(this);
550 if (FAILED(autoCaller.rc())) return autoCaller.rc();
551
552 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
553
554 HRESULT rc = S_OK;
555
556 ComObjPtr<Progress> progress;
557 try
558 {
559 Bstr progressDesc = BstrFmt(tr("Update directory info for '%s'"),
560 m->strPath.c_str());
561 /* Create the progress object */
562 progress.createObject();
563
564 rc = progress->init(mVirtualBox,
565 static_cast<IVFSExplorer*>(this),
566 progressDesc.raw(),
567 TRUE /* aCancelable */);
568 if (FAILED(rc)) throw rc;
569
570 /* Initialize our worker task */
571 std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Update, this, progress));
572
573 rc = task->startThread();
574 if (FAILED(rc)) throw rc;
575
576 /* Don't destruct on success */
577 task.release();
578 }
579 catch (HRESULT aRC)
580 {
581 rc = aRC;
582 }
583
584 if (SUCCEEDED(rc))
585 /* Return progress to the caller */
586 progress.queryInterfaceTo(aProgress);
587
588 return rc;
589}
590
591STDMETHODIMP VFSExplorer::Cd(IN_BSTR aDir, IProgress **aProgress)
592{
593 CheckComArgStrNotEmptyOrNull(aDir);
594
595 AutoCaller autoCaller(this);
596 if (FAILED(autoCaller.rc())) return autoCaller.rc();
597
598 {
599 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
600 m->strPath = aDir;
601 }
602
603 return Update(aProgress);
604}
605
606STDMETHODIMP VFSExplorer::CdUp(IProgress **aProgress)
607{
608 AutoCaller autoCaller(this);
609 if (FAILED(autoCaller.rc())) return autoCaller.rc();
610
611 Utf8Str strUpPath;
612 {
613 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
614 /* Remove lowest dir entry in a platform neutral way. */
615 char *pszNewPath = RTStrDup(m->strPath.c_str());
616 RTPathStripTrailingSlash(pszNewPath);
617 RTPathStripFilename(pszNewPath);
618 strUpPath = pszNewPath;
619 RTStrFree(pszNewPath);
620 }
621
622 return Cd(Bstr(strUpPath).raw(), aProgress);
623}
624
625STDMETHODIMP VFSExplorer::EntryList(ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(VFSFileType_T, aTypes), ComSafeArrayOut(LONG64, aSizes), ComSafeArrayOut(ULONG, aModes))
626{
627 if (ComSafeArrayOutIsNull(aNames) ||
628 ComSafeArrayOutIsNull(aTypes))
629 return E_POINTER;
630
631 AutoCaller autoCaller(this);
632 if (FAILED(autoCaller.rc())) return autoCaller.rc();
633
634 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
635
636 com::SafeArray<BSTR> sfaNames(m->entryList.size());
637 com::SafeArray<ULONG> sfaTypes(m->entryList.size());
638 com::SafeArray<LONG64> sfaSizes(m->entryList.size());
639 com::SafeArray<ULONG> sfaModes(m->entryList.size());
640
641 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
642 size_t i = 0;
643 for (it = m->entryList.begin();
644 it != m->entryList.end();
645 ++it, ++i)
646 {
647 const VFSExplorer::Data::DirEntry &entry = (*it);
648 Bstr bstr(entry.name);
649 bstr.cloneTo(&sfaNames[i]);
650 sfaTypes[i] = entry.type;
651 sfaSizes[i] = entry.size;
652 sfaModes[i] = entry.mode;
653 }
654
655 sfaNames.detachTo(ComSafeArrayOutArg(aNames));
656 sfaTypes.detachTo(ComSafeArrayOutArg(aTypes));
657 sfaSizes.detachTo(ComSafeArrayOutArg(aSizes));
658 sfaModes.detachTo(ComSafeArrayOutArg(aModes));
659
660 return S_OK;
661}
662
663STDMETHODIMP VFSExplorer::Exists(ComSafeArrayIn(IN_BSTR, aNames), ComSafeArrayOut(BSTR, aExists))
664{
665 CheckComArgSafeArrayNotNull(aNames);
666
667 AutoCaller autoCaller(this);
668 if (FAILED(autoCaller.rc())) return autoCaller.rc();
669
670 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
671
672 com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
673 std::list<BSTR> listExists;
674
675 for (size_t a=0; a < sfaNames.size(); ++a)
676 {
677 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
678 for (it = m->entryList.begin();
679 it != m->entryList.end();
680 ++it)
681 {
682 const VFSExplorer::Data::DirEntry &entry = (*it);
683 if (entry.name == RTPathFilename(Utf8Str(sfaNames[a]).c_str()))
684 {
685 BSTR name;
686 Bstr tmp(sfaNames[a]); /* gcc-3.3 cruft */
687 tmp.cloneTo(&name);
688 listExists.push_back(name);
689 }
690 }
691 }
692
693 com::SafeArray<BSTR> sfaExists(listExists);
694 sfaExists.detachTo(ComSafeArrayOutArg(aExists));
695
696 return S_OK;
697}
698
699STDMETHODIMP VFSExplorer::Remove(ComSafeArrayIn(IN_BSTR, aNames), IProgress **aProgress)
700{
701 CheckComArgSafeArrayNotNull(aNames);
702 CheckComArgOutPointerValid(aProgress);
703
704 AutoCaller autoCaller(this);
705 if (FAILED(autoCaller.rc())) return autoCaller.rc();
706
707 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
708
709 HRESULT rc = S_OK;
710
711 com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
712
713 ComObjPtr<Progress> progress;
714 try
715 {
716 /* Create the progress object */
717 progress.createObject();
718
719 rc = progress->init(mVirtualBox, static_cast<IVFSExplorer*>(this),
720 Bstr(tr("Delete files")).raw(),
721 TRUE /* aCancelable */);
722 if (FAILED(rc)) throw rc;
723
724 /* Initialize our worker task */
725 std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Delete, this, progress));
726
727 /* Add all filenames to delete as task data */
728 for (size_t a=0; a < sfaNames.size(); ++a)
729 task->filenames.push_back(Utf8Str(sfaNames[a]));
730
731 rc = task->startThread();
732 if (FAILED(rc)) throw rc;
733
734 /* Don't destruct on success */
735 task.release();
736 }
737 catch (HRESULT aRC)
738 {
739 rc = aRC;
740 }
741
742 if (SUCCEEDED(rc))
743 /* Return progress to the caller */
744 progress.queryInterfaceTo(aProgress);
745
746 return rc;
747}
748
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