VirtualBox

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

Last change on this file since 33464 was 33461, checked in by vboxsync, 14 years ago

Main: Add additional params to IVirtualBox::EntryList for querying the sizes
and modes of the directory entries. Fix undefined file types on certain
filesystem (XFS,...), by using the stat based API.

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