VirtualBox

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

Last change on this file since 49614 was 49586, checked in by vboxsync, 12 years ago

newer gcc versions require a space between literal and identifier

  • 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 49586 2013-11-20 13:58:46Z 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.215389.xyz. 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(),
429 m->strHostname.c_str(), "virtualbox-agent/" VBOX_VERSION_STRING);
430 if (RT_FAILURE(vrc))
431 throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
432
433 RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
434 /* Do we need the list of buckets or keys? */
435 if (m->strBucket.isEmpty())
436 {
437 PCRTS3BUCKETENTRY pBuckets = NULL;
438 vrc = RTS3GetBuckets(hS3, &pBuckets);
439 if (RT_FAILURE(vrc))
440 throw setError(E_FAIL, tr ("Can't get buckets (%Rrc)"), vrc);
441
442 PCRTS3BUCKETENTRY pTmpBuckets = pBuckets;
443 while (pBuckets)
444 {
445 /* Set always read/write permissions of the current logged in user. */
446 fileList.push_back(VFSExplorer::Data::DirEntry(pBuckets->pszName, VFSFileType_Directory, 0, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR));
447 pBuckets = pBuckets->pNext;
448 }
449 RTS3BucketsDestroy(pTmpBuckets);
450 }
451 else
452 {
453 PCRTS3KEYENTRY pKeys = NULL;
454 vrc = RTS3GetBucketKeys(hS3, m->strBucket.c_str(), &pKeys);
455 if (RT_FAILURE(vrc))
456 throw setError(E_FAIL, tr ("Can't get keys for bucket (%Rrc)"), vrc);
457
458 PCRTS3KEYENTRY pTmpKeys = pKeys;
459 while (pKeys)
460 {
461 Utf8Str name(pKeys->pszName);
462 /* Set always read/write permissions of the current logged in user. */
463 fileList.push_back(VFSExplorer::Data::DirEntry(pKeys->pszName, VFSFileType_File, pKeys->cbFile, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR));
464 pKeys = pKeys->pNext;
465 }
466 RTS3KeysDestroy(pTmpKeys);
467 }
468 }
469 catch(HRESULT aRC)
470 {
471 rc = aRC;
472 }
473
474 if (hS3 != NULL)
475 RTS3Destroy(hS3);
476
477 /* Assign the result on success (this clears the old list) */
478 if (rc == S_OK)
479 m->entryList.assign(fileList.begin(), fileList.end());
480
481 aTask->rc = rc;
482
483 if (!aTask->progress.isNull())
484 aTask->progress->notifyComplete(rc);
485
486 LogFlowFunc(("rc=%Rhrc\n", rc));
487 LogFlowFuncLeave();
488
489 return VINF_SUCCESS;
490}
491
492HRESULT VFSExplorer::deleteS3(TaskVFSExplorer *aTask)
493{
494 LogFlowFuncEnter();
495
496 AutoCaller autoCaller(this);
497 if (FAILED(autoCaller.rc())) return autoCaller.rc();
498
499 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
500
501 HRESULT rc = S_OK;
502
503 RTS3 hS3 = NULL;
504 float fPercentStep = 100.0f / aTask->filenames.size();
505 try
506 {
507 int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(),
508 m->strHostname.c_str(), "virtualbox-agent/" VBOX_VERSION_STRING);
509 if (RT_FAILURE(vrc))
510 throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
511
512 RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
513
514 std::list<Utf8Str>::const_iterator it;
515 size_t i = 0;
516 for (it = aTask->filenames.begin();
517 it != aTask->filenames.end();
518 ++it, ++i)
519 {
520 vrc = RTS3DeleteKey(hS3, m->strBucket.c_str(), (*it).c_str());
521 if (RT_FAILURE(vrc))
522 throw setError(VBOX_E_FILE_ERROR, tr ("Can't delete file '%s' (%Rrc)"), (*it).c_str(), vrc);
523 if (aTask->progress)
524 aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
525 }
526 }
527 catch(HRESULT aRC)
528 {
529 rc = aRC;
530 }
531
532 aTask->rc = rc;
533
534 if (hS3 != NULL)
535 RTS3Destroy(hS3);
536
537 if (!aTask->progress.isNull())
538 aTask->progress->notifyComplete(rc);
539
540 LogFlowFunc(("rc=%Rhrc\n", rc));
541 LogFlowFuncLeave();
542
543 return VINF_SUCCESS;
544}
545#endif /* VBOX_WITH_S3 */
546
547STDMETHODIMP VFSExplorer::Update(IProgress **aProgress)
548{
549 CheckComArgOutPointerValid(aProgress);
550
551 AutoCaller autoCaller(this);
552 if (FAILED(autoCaller.rc())) return autoCaller.rc();
553
554 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
555
556 HRESULT rc = S_OK;
557
558 ComObjPtr<Progress> progress;
559 try
560 {
561 Bstr progressDesc = BstrFmt(tr("Update directory info for '%s'"),
562 m->strPath.c_str());
563 /* Create the progress object */
564 progress.createObject();
565
566 rc = progress->init(mVirtualBox,
567 static_cast<IVFSExplorer*>(this),
568 progressDesc.raw(),
569 TRUE /* aCancelable */);
570 if (FAILED(rc)) throw rc;
571
572 /* Initialize our worker task */
573 std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Update, this, progress));
574
575 rc = task->startThread();
576 if (FAILED(rc)) throw rc;
577
578 /* Don't destruct on success */
579 task.release();
580 }
581 catch (HRESULT aRC)
582 {
583 rc = aRC;
584 }
585
586 if (SUCCEEDED(rc))
587 /* Return progress to the caller */
588 progress.queryInterfaceTo(aProgress);
589
590 return rc;
591}
592
593STDMETHODIMP VFSExplorer::Cd(IN_BSTR aDir, IProgress **aProgress)
594{
595 CheckComArgStrNotEmptyOrNull(aDir);
596
597 AutoCaller autoCaller(this);
598 if (FAILED(autoCaller.rc())) return autoCaller.rc();
599
600 {
601 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
602 m->strPath = aDir;
603 }
604
605 return Update(aProgress);
606}
607
608STDMETHODIMP VFSExplorer::CdUp(IProgress **aProgress)
609{
610 AutoCaller autoCaller(this);
611 if (FAILED(autoCaller.rc())) return autoCaller.rc();
612
613 Utf8Str strUpPath;
614 {
615 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
616 /* Remove lowest dir entry in a platform neutral way. */
617 char *pszNewPath = RTStrDup(m->strPath.c_str());
618 RTPathStripTrailingSlash(pszNewPath);
619 RTPathStripFilename(pszNewPath);
620 strUpPath = pszNewPath;
621 RTStrFree(pszNewPath);
622 }
623
624 return Cd(Bstr(strUpPath).raw(), aProgress);
625}
626
627STDMETHODIMP VFSExplorer::EntryList(ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(VFSFileType_T, aTypes), ComSafeArrayOut(LONG64, aSizes), ComSafeArrayOut(ULONG, aModes))
628{
629 if (ComSafeArrayOutIsNull(aNames) ||
630 ComSafeArrayOutIsNull(aTypes))
631 return E_POINTER;
632
633 AutoCaller autoCaller(this);
634 if (FAILED(autoCaller.rc())) return autoCaller.rc();
635
636 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
637
638 com::SafeArray<BSTR> sfaNames(m->entryList.size());
639 com::SafeArray<ULONG> sfaTypes(m->entryList.size());
640 com::SafeArray<LONG64> sfaSizes(m->entryList.size());
641 com::SafeArray<ULONG> sfaModes(m->entryList.size());
642
643 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
644 size_t i = 0;
645 for (it = m->entryList.begin();
646 it != m->entryList.end();
647 ++it, ++i)
648 {
649 const VFSExplorer::Data::DirEntry &entry = (*it);
650 Bstr bstr(entry.name);
651 bstr.cloneTo(&sfaNames[i]);
652 sfaTypes[i] = entry.type;
653 sfaSizes[i] = entry.size;
654 sfaModes[i] = entry.mode;
655 }
656
657 sfaNames.detachTo(ComSafeArrayOutArg(aNames));
658 sfaTypes.detachTo(ComSafeArrayOutArg(aTypes));
659 sfaSizes.detachTo(ComSafeArrayOutArg(aSizes));
660 sfaModes.detachTo(ComSafeArrayOutArg(aModes));
661
662 return S_OK;
663}
664
665STDMETHODIMP VFSExplorer::Exists(ComSafeArrayIn(IN_BSTR, aNames), ComSafeArrayOut(BSTR, aExists))
666{
667 CheckComArgSafeArrayNotNull(aNames);
668
669 AutoCaller autoCaller(this);
670 if (FAILED(autoCaller.rc())) return autoCaller.rc();
671
672 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
673
674 com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
675 std::list<BSTR> listExists;
676
677 for (size_t a=0; a < sfaNames.size(); ++a)
678 {
679 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
680 for (it = m->entryList.begin();
681 it != m->entryList.end();
682 ++it)
683 {
684 const VFSExplorer::Data::DirEntry &entry = (*it);
685 if (entry.name == RTPathFilename(Utf8Str(sfaNames[a]).c_str()))
686 {
687 BSTR name;
688 Bstr tmp(sfaNames[a]); /* gcc-3.3 cruft */
689 tmp.cloneTo(&name);
690 listExists.push_back(name);
691 }
692 }
693 }
694
695 com::SafeArray<BSTR> sfaExists(listExists);
696 sfaExists.detachTo(ComSafeArrayOutArg(aExists));
697
698 return S_OK;
699}
700
701STDMETHODIMP VFSExplorer::Remove(ComSafeArrayIn(IN_BSTR, aNames), IProgress **aProgress)
702{
703 CheckComArgSafeArrayNotNull(aNames);
704 CheckComArgOutPointerValid(aProgress);
705
706 AutoCaller autoCaller(this);
707 if (FAILED(autoCaller.rc())) return autoCaller.rc();
708
709 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
710
711 HRESULT rc = S_OK;
712
713 com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
714
715 ComObjPtr<Progress> progress;
716 try
717 {
718 /* Create the progress object */
719 progress.createObject();
720
721 rc = progress->init(mVirtualBox, static_cast<IVFSExplorer*>(this),
722 Bstr(tr("Delete files")).raw(),
723 TRUE /* aCancelable */);
724 if (FAILED(rc)) throw rc;
725
726 /* Initialize our worker task */
727 std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Delete, this, progress));
728
729 /* Add all filenames to delete as task data */
730 for (size_t a=0; a < sfaNames.size(); ++a)
731 task->filenames.push_back(Utf8Str(sfaNames[a]));
732
733 rc = task->startThread();
734 if (FAILED(rc)) throw rc;
735
736 /* Don't destruct on success */
737 task.release();
738 }
739 catch (HRESULT aRC)
740 {
741 rc = aRC;
742 }
743
744 if (SUCCEEDED(rc))
745 /* Return progress to the caller */
746 progress.queryInterfaceTo(aProgress);
747
748 return rc;
749}
750
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