VirtualBox

source: vbox/trunk/src/VBox/Main/VFSExplorerImpl.cpp@ 34906

Last change on this file since 34906 was 33797, checked in by vboxsync, 14 years ago

Main: use RTPathJoin

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.2 KB
Line 
1/* $Id: VFSExplorerImpl.cpp 33797 2010-11-05 16:04:08Z vboxsync $ */
2/** @file
3 *
4 * IVFSExplorer COM class implementations.
5 */
6
7/*
8 * Copyright (C) 2009 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 rc = pVFSExplorer->updateS3(task.get());
229 break;
230 }
231 case TaskVFSExplorer::Delete:
232 {
233 if (pVFSExplorer->m->storageType == VFSType_File)
234 rc = pVFSExplorer->deleteFS(task.get());
235 else if (pVFSExplorer->m->storageType == VFSType_S3)
236 rc = pVFSExplorer->deleteS3(task.get());
237 break;
238 }
239 default:
240 AssertMsgFailed(("Invalid task type %u specified!\n", task->taskType));
241 break;
242 }
243
244 LogFlowFunc(("rc=%Rhrc\n", rc));
245 LogFlowFuncLeave();
246
247 return VINF_SUCCESS;
248}
249
250/* static */
251int VFSExplorer::TaskVFSExplorer::uploadProgress(unsigned uPercent, void *pvUser)
252{
253 VFSExplorer::TaskVFSExplorer* pTask = *(VFSExplorer::TaskVFSExplorer**)pvUser;
254
255 if (pTask &&
256 !pTask->progress.isNull())
257 {
258 BOOL fCanceled;
259 pTask->progress->COMGETTER(Canceled)(&fCanceled);
260 if (fCanceled)
261 return -1;
262 pTask->progress->SetCurrentOperationProgress(uPercent);
263 }
264 return VINF_SUCCESS;
265}
266
267VFSFileType_T VFSExplorer::RTToVFSFileType(int aType) const
268{
269 int a = aType & RTFS_TYPE_MASK;
270 VFSFileType_T t = VFSFileType_Unknown;
271 if ((a & RTFS_TYPE_DIRECTORY) == RTFS_TYPE_DIRECTORY)
272 t = VFSFileType_Directory;
273 else if ((a & RTFS_TYPE_FILE) == RTFS_TYPE_FILE)
274 t = VFSFileType_File;
275 else if ((a & RTFS_TYPE_SYMLINK) == RTFS_TYPE_SYMLINK)
276 t = VFSFileType_SymLink;
277 else if ((a & RTFS_TYPE_FIFO) == RTFS_TYPE_FIFO)
278 t = VFSFileType_Fifo;
279 else if ((a & RTFS_TYPE_DEV_CHAR) == RTFS_TYPE_DEV_CHAR)
280 t = VFSFileType_DevChar;
281 else if ((a & RTFS_TYPE_DEV_BLOCK) == RTFS_TYPE_DEV_BLOCK)
282 t = VFSFileType_DevBlock;
283 else if ((a & RTFS_TYPE_SOCKET) == RTFS_TYPE_SOCKET)
284 t = VFSFileType_Socket;
285 else if ((a & RTFS_TYPE_WHITEOUT) == RTFS_TYPE_WHITEOUT)
286 t = VFSFileType_WhiteOut;
287
288 return t;
289}
290
291HRESULT VFSExplorer::updateFS(TaskVFSExplorer *aTask)
292{
293 LogFlowFuncEnter();
294
295 AutoCaller autoCaller(this);
296 if (FAILED(autoCaller.rc())) return autoCaller.rc();
297
298 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
299
300 HRESULT rc = S_OK;
301
302 std::list<VFSExplorer::Data::DirEntry> fileList;
303 char *pszPath = NULL;
304 PRTDIR pDir = NULL;
305 try
306 {
307 int vrc = RTDirOpen(&pDir, m->strPath.c_str());
308 if (RT_FAILURE(vrc))
309 throw setError(VBOX_E_FILE_ERROR, tr ("Can't open directory '%s' (%Rrc)"), pszPath, vrc);
310
311 if (aTask->progress)
312 aTask->progress->SetCurrentOperationProgress(33);
313 RTDIRENTRYEX entry;
314 while (RT_SUCCESS(vrc))
315 {
316 vrc = RTDirReadEx(pDir, &entry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
317 if (RT_SUCCESS(vrc))
318 {
319 Utf8Str name(entry.szName);
320 if ( name != "."
321 && name != "..")
322 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)));
323 }
324 }
325 if (aTask->progress)
326 aTask->progress->SetCurrentOperationProgress(66);
327 }
328 catch(HRESULT aRC)
329 {
330 rc = aRC;
331 }
332
333 /* Clean up */
334 if (pszPath)
335 RTStrFree(pszPath);
336 if (pDir)
337 RTDirClose(pDir);
338
339 if (aTask->progress)
340 aTask->progress->SetCurrentOperationProgress(99);
341
342 /* Assign the result on success (this clears the old list) */
343 if (rc == S_OK)
344 m->entryList.assign(fileList.begin(), fileList.end());
345
346 aTask->rc = rc;
347
348 if (!aTask->progress.isNull())
349 aTask->progress->notifyComplete(rc);
350
351 LogFlowFunc(("rc=%Rhrc\n", rc));
352 LogFlowFuncLeave();
353
354 return VINF_SUCCESS;
355}
356
357HRESULT VFSExplorer::deleteFS(TaskVFSExplorer *aTask)
358{
359 LogFlowFuncEnter();
360
361 AutoCaller autoCaller(this);
362 if (FAILED(autoCaller.rc())) return autoCaller.rc();
363
364 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
365
366 HRESULT rc = S_OK;
367
368 float fPercentStep = 100.0f / aTask->filenames.size();
369 try
370 {
371 char szPath[RTPATH_MAX];
372 std::list<Utf8Str>::const_iterator it;
373 size_t i = 0;
374 for (it = aTask->filenames.begin();
375 it != aTask->filenames.end();
376 ++it, ++i)
377 {
378 int vrc = RTPathJoin(szPath, sizeof(szPath), m->strPath.c_str(), (*it).c_str());
379 if (RT_FAILURE(vrc))
380 throw setError(E_FAIL, tr("Internal Error (%Rrc)"), vrc);
381 vrc = RTFileDelete(szPath);
382 if (RT_FAILURE(vrc))
383 throw setError(VBOX_E_FILE_ERROR, tr("Can't delete file '%s' (%Rrc)"), szPath, vrc);
384 if (aTask->progress)
385 aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
386 }
387 }
388 catch(HRESULT aRC)
389 {
390 rc = aRC;
391 }
392
393 aTask->rc = rc;
394
395 if (!aTask->progress.isNull())
396 aTask->progress->notifyComplete(rc);
397
398 LogFlowFunc(("rc=%Rhrc\n", rc));
399 LogFlowFuncLeave();
400
401 return VINF_SUCCESS;
402}
403
404HRESULT VFSExplorer::updateS3(TaskVFSExplorer *aTask)
405{
406 LogFlowFuncEnter();
407
408 AutoCaller autoCaller(this);
409 if (FAILED(autoCaller.rc())) return autoCaller.rc();
410
411 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
412
413 HRESULT rc = S_OK;
414
415 RTS3 hS3 = NULL;
416 std::list<VFSExplorer::Data::DirEntry> fileList;
417 try
418 {
419 int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(), m->strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING);
420 if (RT_FAILURE(vrc))
421 throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
422
423 RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
424 /* Do we need the list of buckets or keys? */
425 if (m->strBucket.isEmpty())
426 {
427 PCRTS3BUCKETENTRY pBuckets = NULL;
428 vrc = RTS3GetBuckets(hS3, &pBuckets);
429 if (RT_FAILURE(vrc))
430 throw setError(E_FAIL, tr ("Can't get buckets (%Rrc)"), vrc);
431
432 PCRTS3BUCKETENTRY pTmpBuckets = pBuckets;
433 while (pBuckets)
434 {
435 /* Set always read/write permissions of the current logged in user. */
436 fileList.push_back(VFSExplorer::Data::DirEntry(pBuckets->pszName, VFSFileType_Directory, 0, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR));
437 pBuckets = pBuckets->pNext;
438 }
439 RTS3BucketsDestroy(pTmpBuckets);
440 }
441 else
442 {
443 PCRTS3KEYENTRY pKeys = NULL;
444 vrc = RTS3GetBucketKeys(hS3, m->strBucket.c_str(), &pKeys);
445 if (RT_FAILURE(vrc))
446 throw setError(E_FAIL, tr ("Can't get keys for bucket (%Rrc)"), vrc);
447
448 PCRTS3KEYENTRY pTmpKeys = pKeys;
449 while (pKeys)
450 {
451 Utf8Str name(pKeys->pszName);
452 /* Set always read/write permissions of the current logged in user. */
453 fileList.push_back(VFSExplorer::Data::DirEntry(pKeys->pszName, VFSFileType_File, pKeys->cbFile, RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR));
454 pKeys = pKeys->pNext;
455 }
456 RTS3KeysDestroy(pTmpKeys);
457 }
458 }
459 catch(HRESULT aRC)
460 {
461 rc = aRC;
462 }
463
464 if (hS3 != NULL)
465 RTS3Destroy(hS3);
466
467 /* Assign the result on success (this clears the old list) */
468 if (rc == S_OK)
469 m->entryList.assign(fileList.begin(), fileList.end());
470
471 aTask->rc = rc;
472
473 if (!aTask->progress.isNull())
474 aTask->progress->notifyComplete(rc);
475
476 LogFlowFunc(("rc=%Rhrc\n", rc));
477 LogFlowFuncLeave();
478
479 return VINF_SUCCESS;
480}
481
482HRESULT VFSExplorer::deleteS3(TaskVFSExplorer *aTask)
483{
484 LogFlowFuncEnter();
485
486 AutoCaller autoCaller(this);
487 if (FAILED(autoCaller.rc())) return autoCaller.rc();
488
489 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
490
491 HRESULT rc = S_OK;
492
493 RTS3 hS3 = NULL;
494 float fPercentStep = 100.0f / aTask->filenames.size();
495 try
496 {
497 int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(), m->strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING);
498 if (RT_FAILURE(vrc))
499 throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
500
501 RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
502
503 std::list<Utf8Str>::const_iterator it;
504 size_t i = 0;
505 for (it = aTask->filenames.begin();
506 it != aTask->filenames.end();
507 ++it, ++i)
508 {
509 vrc = RTS3DeleteKey(hS3, m->strBucket.c_str(), (*it).c_str());
510 if (RT_FAILURE(vrc))
511 throw setError(VBOX_E_FILE_ERROR, tr ("Can't delete file '%s' (%Rrc)"), (*it).c_str(), vrc);
512 if (aTask->progress)
513 aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
514 }
515 }
516 catch(HRESULT aRC)
517 {
518 rc = aRC;
519 }
520
521 aTask->rc = rc;
522
523 if (hS3 != NULL)
524 RTS3Destroy(hS3);
525
526 if (!aTask->progress.isNull())
527 aTask->progress->notifyComplete(rc);
528
529 LogFlowFunc(("rc=%Rhrc\n", rc));
530 LogFlowFuncLeave();
531
532 return VINF_SUCCESS;
533}
534
535STDMETHODIMP VFSExplorer::Update(IProgress **aProgress)
536{
537 CheckComArgOutPointerValid(aProgress);
538
539 AutoCaller autoCaller(this);
540 if (FAILED(autoCaller.rc())) return autoCaller.rc();
541
542 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
543
544 HRESULT rc = S_OK;
545
546 ComObjPtr<Progress> progress;
547 try
548 {
549 Bstr progressDesc = BstrFmt(tr("Update directory info for '%s'"),
550 m->strPath.c_str());
551 /* Create the progress object */
552 progress.createObject();
553
554 rc = progress->init(mVirtualBox,
555 static_cast<IVFSExplorer*>(this),
556 progressDesc.raw(),
557 TRUE /* aCancelable */);
558 if (FAILED(rc)) throw rc;
559
560 /* Initialize our worker task */
561 std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Update, this, progress));
562
563 rc = task->startThread();
564 if (FAILED(rc)) throw rc;
565
566 /* Don't destruct on success */
567 task.release();
568 }
569 catch (HRESULT aRC)
570 {
571 rc = aRC;
572 }
573
574 if (SUCCEEDED(rc))
575 /* Return progress to the caller */
576 progress.queryInterfaceTo(aProgress);
577
578 return rc;
579}
580
581STDMETHODIMP VFSExplorer::Cd(IN_BSTR aDir, IProgress **aProgress)
582{
583 CheckComArgStrNotEmptyOrNull(aDir);
584
585 AutoCaller autoCaller(this);
586 if (FAILED(autoCaller.rc())) return autoCaller.rc();
587
588 {
589 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
590 m->strPath = aDir;
591 }
592
593 return Update(aProgress);
594}
595
596STDMETHODIMP VFSExplorer::CdUp(IProgress **aProgress)
597{
598 AutoCaller autoCaller(this);
599 if (FAILED(autoCaller.rc())) return autoCaller.rc();
600
601 Utf8Str strUpPath;
602 {
603 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
604 /* Remove lowest dir entry in a platform neutral way. */
605 char *pszNewPath = RTStrDup(m->strPath.c_str());
606 RTPathStripTrailingSlash(pszNewPath);
607 RTPathStripFilename(pszNewPath);
608 strUpPath = pszNewPath;
609 RTStrFree(pszNewPath);
610 }
611
612 return Cd(Bstr(strUpPath).raw(), aProgress);
613}
614
615STDMETHODIMP VFSExplorer::EntryList(ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(VFSFileType_T, aTypes), ComSafeArrayOut(ULONG, aSizes), ComSafeArrayOut(ULONG, aModes))
616{
617 if (ComSafeArrayOutIsNull(aNames) ||
618 ComSafeArrayOutIsNull(aTypes))
619 return E_POINTER;
620
621 AutoCaller autoCaller(this);
622 if (FAILED(autoCaller.rc())) return autoCaller.rc();
623
624 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
625
626 com::SafeArray<BSTR> sfaNames(m->entryList.size());
627 com::SafeArray<ULONG> sfaTypes(m->entryList.size());
628 com::SafeArray<ULONG> sfaSizes(m->entryList.size());
629 com::SafeArray<ULONG> sfaModes(m->entryList.size());
630
631 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
632 size_t i = 0;
633 for (it = m->entryList.begin();
634 it != m->entryList.end();
635 ++it, ++i)
636 {
637 const VFSExplorer::Data::DirEntry &entry = (*it);
638 Bstr bstr(entry.name);
639 bstr.cloneTo(&sfaNames[i]);
640 sfaTypes[i] = entry.type;
641 sfaSizes[i] = entry.size;
642 sfaModes[i] = entry.mode;
643 }
644
645 sfaNames.detachTo(ComSafeArrayOutArg(aNames));
646 sfaTypes.detachTo(ComSafeArrayOutArg(aTypes));
647 sfaSizes.detachTo(ComSafeArrayOutArg(aSizes));
648 sfaModes.detachTo(ComSafeArrayOutArg(aModes));
649
650 return S_OK;
651}
652
653STDMETHODIMP VFSExplorer::Exists(ComSafeArrayIn(IN_BSTR, aNames), ComSafeArrayOut(BSTR, aExists))
654{
655 CheckComArgSafeArrayNotNull(aNames);
656
657 AutoCaller autoCaller(this);
658 if (FAILED(autoCaller.rc())) return autoCaller.rc();
659
660 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
661
662 com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
663 std::list<BSTR> listExists;
664
665 for (size_t a=0; a < sfaNames.size(); ++a)
666 {
667 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
668 for (it = m->entryList.begin();
669 it != m->entryList.end();
670 ++it)
671 {
672 const VFSExplorer::Data::DirEntry &entry = (*it);
673 if (entry.name == RTPathFilename(Utf8Str(sfaNames[a]).c_str()))
674 {
675 BSTR name;
676 Bstr tmp(sfaNames[a]); /* gcc-3.3 cruft */
677 tmp.cloneTo(&name);
678 listExists.push_back(name);
679 }
680 }
681 }
682
683 com::SafeArray<BSTR> sfaExists(listExists);
684 sfaExists.detachTo(ComSafeArrayOutArg(aExists));
685
686 return S_OK;
687}
688
689STDMETHODIMP VFSExplorer::Remove(ComSafeArrayIn(IN_BSTR, aNames), IProgress **aProgress)
690{
691 CheckComArgSafeArrayNotNull(aNames);
692 CheckComArgOutPointerValid(aProgress);
693
694 AutoCaller autoCaller(this);
695 if (FAILED(autoCaller.rc())) return autoCaller.rc();
696
697 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
698
699 HRESULT rc = S_OK;
700
701 com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
702
703 ComObjPtr<Progress> progress;
704 try
705 {
706 /* Create the progress object */
707 progress.createObject();
708
709 rc = progress->init(mVirtualBox, static_cast<IVFSExplorer*>(this),
710 Bstr(tr("Delete files")).raw(),
711 TRUE /* aCancelable */);
712 if (FAILED(rc)) throw rc;
713
714 /* Initialize our worker task */
715 std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Delete, this, progress));
716
717 /* Add all filenames to delete as task data */
718 for (size_t a=0; a < sfaNames.size(); ++a)
719 task->filenames.push_back(Utf8Str(sfaNames[a]));
720
721 rc = task->startThread();
722 if (FAILED(rc)) throw rc;
723
724 /* Don't destruct on success */
725 task.release();
726 }
727 catch (HRESULT aRC)
728 {
729 rc = aRC;
730 }
731
732 if (SUCCEEDED(rc))
733 /* Return progress to the caller */
734 progress.queryInterfaceTo(aProgress);
735
736 return rc;
737}
738
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