VirtualBox

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

Last change on this file since 33794 was 33794, checked in by vboxsync, 15 years ago

Main: remove superfluous striping of the last path component

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