VirtualBox

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

Last change on this file since 61644 was 60448, checked in by vboxsync, 9 years ago

bugref:7179. Removed auto_ptr from VFSExplorerImpl.cpp

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1/* $Id: VFSExplorerImpl.cpp 60448 2016-04-12 10:26:56Z vboxsync $ */
2/** @file
3 * IVFSExplorer COM class implementations.
4 */
5
6/*
7 * Copyright (C) 2009-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <iprt/dir.h>
19#include <iprt/path.h>
20#include <iprt/file.h>
21#include <iprt/s3.h>
22#include <iprt/cpp/utils.h>
23
24#include <VBox/com/array.h>
25
26#include <VBox/param.h>
27#include <VBox/version.h>
28
29#include "VFSExplorerImpl.h"
30#include "VirtualBoxImpl.h"
31#include "ProgressImpl.h"
32
33#include "AutoCaller.h"
34#include "Logging.h"
35#include "ThreadTask.h"
36
37#include <memory>
38
39struct VFSExplorer::Data
40{
41 struct DirEntry
42 {
43 DirEntry(Utf8Str strName, FsObjType_T fileType, uint64_t cbSize, uint32_t fMode)
44 : name(strName)
45 , type(fileType)
46 , size(cbSize)
47 , mode(fMode) {}
48
49 Utf8Str name;
50 FsObjType_T type;
51 uint64_t size;
52 uint32_t mode;
53 };
54
55 VFSType_T storageType;
56 Utf8Str strUsername;
57 Utf8Str strPassword;
58 Utf8Str strHostname;
59 Utf8Str strPath;
60 Utf8Str strBucket;
61 std::list<DirEntry> entryList;
62};
63
64
65VFSExplorer::VFSExplorer()
66 : mVirtualBox(NULL)
67{
68}
69
70VFSExplorer::~VFSExplorer()
71{
72}
73
74
75/**
76 * VFSExplorer COM initializer.
77 * @param
78 * @return
79 */
80HRESULT VFSExplorer::init(VFSType_T aType, Utf8Str aFilePath, Utf8Str aHostname, Utf8Str aUsername,
81 Utf8Str aPassword, VirtualBox *aVirtualBox)
82{
83 /* Enclose the state transition NotReady->InInit->Ready */
84 AutoInitSpan autoInitSpan(this);
85 AssertReturn(autoInitSpan.isOk(), E_FAIL);
86
87 /* Weak reference to a VirtualBox object */
88 unconst(mVirtualBox) = aVirtualBox;
89
90 /* initialize data */
91 m = new Data;
92
93 m->storageType = aType;
94 m->strPath = aFilePath;
95 m->strHostname = aHostname;
96 m->strUsername = aUsername;
97 m->strPassword = aPassword;
98
99 if (m->storageType == VFSType_S3)
100 {
101 size_t bpos = aFilePath.find("/", 1);
102 if (bpos != Utf8Str::npos)
103 {
104 m->strBucket = aFilePath.substr(1, bpos - 1); /* The bucket without any slashes */
105 aFilePath = aFilePath.substr(bpos); /* The rest of the file path */
106 }
107 }
108
109 /* Confirm a successful initialization */
110 autoInitSpan.setSucceeded();
111
112 return S_OK;
113}
114
115/**
116 * VFSExplorer COM uninitializer.
117 * @return
118 */
119void VFSExplorer::uninit()
120{
121 delete m;
122 m = NULL;
123}
124
125/**
126 * Public method implementation.
127 * @param
128 * @return
129 */
130HRESULT VFSExplorer::getPath(com::Utf8Str &aPath)
131{
132 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
133
134 aPath = m->strPath;
135
136 return S_OK;
137}
138
139
140HRESULT VFSExplorer::getType(VFSType_T *aType)
141{
142 if (!aType)
143 return E_POINTER;
144
145 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
146
147 *aType = m->storageType;
148
149 return S_OK;
150}
151
152class VFSExplorer::TaskVFSExplorer : public ThreadTask
153{
154public:
155 enum TaskType
156 {
157 Update,
158 Delete
159 };
160
161 TaskVFSExplorer(TaskType aTaskType, VFSExplorer *aThat, Progress *aProgress)
162 : taskType(aTaskType),
163 pVFSExplorer(aThat),
164 progress(aProgress),
165 rc(S_OK)
166 {
167 m_strTaskName = "Explorer::Task";
168 }
169 ~TaskVFSExplorer() {}
170
171private:
172 void handler()
173 {
174 int vrc = taskThread(NULL, this);
175 }
176
177 static DECLCALLBACK(int) taskThread(RTTHREAD aThread, void *pvUser);
178 static DECLCALLBACK(int) uploadProgress(unsigned uPercent, void *pvUser);
179
180 TaskType taskType;
181 VFSExplorer *pVFSExplorer;
182
183 ComObjPtr<Progress> progress;
184 HRESULT rc;
185
186 /* task data */
187 std::list<Utf8Str> filenames;
188
189 friend class VFSExplorer;
190};
191
192/* static */
193DECLCALLBACK(int) VFSExplorer::TaskVFSExplorer::taskThread(RTTHREAD /* aThread */, void *pvUser)
194{
195 TaskVFSExplorer* pTask = static_cast<TaskVFSExplorer*>(pvUser);
196 AssertReturn(pTask, VERR_GENERAL_FAILURE);
197
198 VFSExplorer *pVFSExplorer = pTask->pVFSExplorer;
199
200 LogFlowFuncEnter();
201 LogFlowFunc(("VFSExplorer %p\n", pVFSExplorer));
202
203 HRESULT rc = S_OK;
204
205 switch(pTask->taskType)
206 {
207 case TaskVFSExplorer::Update:
208 {
209 if (pVFSExplorer->m->storageType == VFSType_File)
210 rc = pVFSExplorer->i_updateFS(pTask);
211 else if (pVFSExplorer->m->storageType == VFSType_S3)
212 rc = VERR_NOT_IMPLEMENTED;
213 break;
214 }
215 case TaskVFSExplorer::Delete:
216 {
217 if (pVFSExplorer->m->storageType == VFSType_File)
218 rc = pVFSExplorer->i_deleteFS(pTask);
219 else if (pVFSExplorer->m->storageType == VFSType_S3)
220 rc = VERR_NOT_IMPLEMENTED;
221 break;
222 }
223 default:
224 AssertMsgFailed(("Invalid task type %u specified!\n", pTask->taskType));
225 break;
226 }
227
228 LogFlowFunc(("rc=%Rhrc\n", rc)); NOREF(rc);
229 LogFlowFuncLeave();
230
231 return VINF_SUCCESS;
232}
233
234/* static */
235DECLCALLBACK(int) VFSExplorer::TaskVFSExplorer::uploadProgress(unsigned uPercent, void *pvUser)
236{
237 VFSExplorer::TaskVFSExplorer* pTask = *(VFSExplorer::TaskVFSExplorer**)pvUser;
238
239 if (pTask &&
240 !pTask->progress.isNull())
241 {
242 BOOL fCanceled;
243 pTask->progress->COMGETTER(Canceled)(&fCanceled);
244 if (fCanceled)
245 return -1;
246 pTask->progress->SetCurrentOperationProgress(uPercent);
247 }
248 return VINF_SUCCESS;
249}
250
251FsObjType_T VFSExplorer::i_iprtToVfsObjType(RTFMODE aType) const
252{
253 int a = aType & RTFS_TYPE_MASK;
254 FsObjType_T t = FsObjType_Unknown;
255 if ((a & RTFS_TYPE_DIRECTORY) == RTFS_TYPE_DIRECTORY)
256 t = FsObjType_Directory;
257 else if ((a & RTFS_TYPE_FILE) == RTFS_TYPE_FILE)
258 t = FsObjType_File;
259 else if ((a & RTFS_TYPE_SYMLINK) == RTFS_TYPE_SYMLINK)
260 t = FsObjType_Symlink;
261 else if ((a & RTFS_TYPE_FIFO) == RTFS_TYPE_FIFO)
262 t = FsObjType_Fifo;
263 else if ((a & RTFS_TYPE_DEV_CHAR) == RTFS_TYPE_DEV_CHAR)
264 t = FsObjType_DevChar;
265 else if ((a & RTFS_TYPE_DEV_BLOCK) == RTFS_TYPE_DEV_BLOCK)
266 t = FsObjType_DevBlock;
267 else if ((a & RTFS_TYPE_SOCKET) == RTFS_TYPE_SOCKET)
268 t = FsObjType_Socket;
269 else if ((a & RTFS_TYPE_WHITEOUT) == RTFS_TYPE_WHITEOUT)
270 t = FsObjType_WhiteOut;
271
272 return t;
273}
274
275HRESULT VFSExplorer::i_updateFS(TaskVFSExplorer *aTask)
276{
277 LogFlowFuncEnter();
278
279 AutoCaller autoCaller(this);
280 if (FAILED(autoCaller.rc())) return autoCaller.rc();
281
282 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
283
284 HRESULT rc = S_OK;
285
286 std::list<VFSExplorer::Data::DirEntry> fileList;
287 char *pszPath = NULL;
288 PRTDIR pDir = NULL;
289 try
290 {
291 int vrc = RTDirOpen(&pDir, m->strPath.c_str());
292 if (RT_FAILURE(vrc))
293 throw setError(VBOX_E_FILE_ERROR, tr ("Can't open directory '%s' (%Rrc)"), pszPath, vrc);
294
295 if (aTask->progress)
296 aTask->progress->SetCurrentOperationProgress(33);
297 RTDIRENTRYEX entry;
298 while (RT_SUCCESS(vrc))
299 {
300 vrc = RTDirReadEx(pDir, &entry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
301 if (RT_SUCCESS(vrc))
302 {
303 Utf8Str name(entry.szName);
304 if ( name != "."
305 && name != "..")
306 fileList.push_back(VFSExplorer::Data::DirEntry(name, i_iprtToVfsObjType(entry.Info.Attr.fMode),
307 entry.Info.cbObject,
308 entry.Info.Attr.fMode & (RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXG | RTFS_UNIX_IRWXO)));
309 }
310 }
311 if (aTask->progress)
312 aTask->progress->SetCurrentOperationProgress(66);
313 }
314 catch(HRESULT aRC)
315 {
316 rc = aRC;
317 }
318
319 /* Clean up */
320 if (pszPath)
321 RTStrFree(pszPath);
322 if (pDir)
323 RTDirClose(pDir);
324
325 if (aTask->progress)
326 aTask->progress->SetCurrentOperationProgress(99);
327
328 /* Assign the result on success (this clears the old list) */
329 if (rc == S_OK)
330 m->entryList.assign(fileList.begin(), fileList.end());
331
332 aTask->rc = rc;
333
334 if (!aTask->progress.isNull())
335 aTask->progress->i_notifyComplete(rc);
336
337 LogFlowFunc(("rc=%Rhrc\n", rc));
338 LogFlowFuncLeave();
339
340 return VINF_SUCCESS;
341}
342
343HRESULT VFSExplorer::i_deleteFS(TaskVFSExplorer *aTask)
344{
345 LogFlowFuncEnter();
346
347 AutoCaller autoCaller(this);
348 if (FAILED(autoCaller.rc())) return autoCaller.rc();
349
350 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
351
352 HRESULT rc = S_OK;
353
354 float fPercentStep = 100.0f / aTask->filenames.size();
355 try
356 {
357 char szPath[RTPATH_MAX];
358 std::list<Utf8Str>::const_iterator it;
359 size_t i = 0;
360 for (it = aTask->filenames.begin();
361 it != aTask->filenames.end();
362 ++it, ++i)
363 {
364 int vrc = RTPathJoin(szPath, sizeof(szPath), m->strPath.c_str(), (*it).c_str());
365 if (RT_FAILURE(vrc))
366 throw setError(E_FAIL, tr("Internal Error (%Rrc)"), vrc);
367 vrc = RTFileDelete(szPath);
368 if (RT_FAILURE(vrc))
369 throw setError(VBOX_E_FILE_ERROR, tr("Can't delete file '%s' (%Rrc)"), szPath, vrc);
370 if (aTask->progress)
371 aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
372 }
373 }
374 catch(HRESULT aRC)
375 {
376 rc = aRC;
377 }
378
379 aTask->rc = rc;
380
381 if (!aTask->progress.isNull())
382 aTask->progress->i_notifyComplete(rc);
383
384 LogFlowFunc(("rc=%Rhrc\n", rc));
385 LogFlowFuncLeave();
386
387 return VINF_SUCCESS;
388}
389
390HRESULT VFSExplorer::update(ComPtr<IProgress> &aProgress)
391{
392 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
393
394 HRESULT rc = S_OK;
395
396 ComObjPtr<Progress> progress;
397 try
398 {
399 Bstr progressDesc = BstrFmt(tr("Update directory info for '%s'"),
400 m->strPath.c_str());
401 /* Create the progress object */
402 progress.createObject();
403
404 rc = progress->init(mVirtualBox,
405 static_cast<IVFSExplorer*>(this),
406 progressDesc.raw(),
407 TRUE /* aCancelable */);
408 if (FAILED(rc)) throw rc;
409
410 /* Initialize our worker task */
411 TaskVFSExplorer* pTask = new TaskVFSExplorer(TaskVFSExplorer::Update, this, progress);
412
413 //this function delete task in case of exceptions, so there is no need in the call of delete operator
414 rc = pTask->createThread(NULL, RTTHREADTYPE_MAIN_HEAVY_WORKER);
415 }
416 catch (HRESULT aRC)
417 {
418 rc = aRC;
419 }
420
421 if (SUCCEEDED(rc))
422 /* Return progress to the caller */
423 progress.queryInterfaceTo(aProgress.asOutParam());
424
425 return rc;
426}
427
428HRESULT VFSExplorer::cd(const com::Utf8Str &aDir, ComPtr<IProgress> &aProgress)
429{
430 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
431 m->strPath = aDir;
432 return update(aProgress);
433}
434
435HRESULT VFSExplorer::cdUp(ComPtr<IProgress> &aProgress)
436{
437 Utf8Str strUpPath;
438 {
439 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
440 /* Remove lowest dir entry in a platform neutral way. */
441 char *pszNewPath = RTStrDup(m->strPath.c_str());
442 RTPathStripTrailingSlash(pszNewPath);
443 RTPathStripFilename(pszNewPath);
444 strUpPath = pszNewPath;
445 RTStrFree(pszNewPath);
446 }
447
448 return cd(strUpPath, aProgress);
449}
450
451HRESULT VFSExplorer::entryList(std::vector<com::Utf8Str> &aNames,
452 std::vector<ULONG> &aTypes,
453 std::vector<LONG64> &aSizes,
454 std::vector<ULONG> &aModes)
455{
456 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
457 aNames.resize(m->entryList.size());
458 aTypes.resize(m->entryList.size());
459 aSizes.resize(m->entryList.size());
460 aModes.resize(m->entryList.size());
461
462 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
463 size_t i = 0;
464 for (it = m->entryList.begin();
465 it != m->entryList.end();
466 ++it, ++i)
467 {
468 const VFSExplorer::Data::DirEntry &entry = (*it);
469 aNames[i] = entry.name;
470 aTypes[i] = entry.type;
471 aSizes[i] = entry.size;
472 aModes[i] = entry.mode;
473 }
474
475 return S_OK;
476}
477
478HRESULT VFSExplorer::exists(const std::vector<com::Utf8Str> &aNames,
479 std::vector<com::Utf8Str> &aExists)
480{
481
482 AutoCaller autoCaller(this);
483 if (FAILED(autoCaller.rc())) return autoCaller.rc();
484
485 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
486 aExists.resize(0);
487 for (size_t i=0; i < aNames.size(); ++i)
488 {
489 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
490 for (it = m->entryList.begin();
491 it != m->entryList.end();
492 ++it)
493 {
494 const VFSExplorer::Data::DirEntry &entry = (*it);
495 if (entry.name == RTPathFilename(aNames[i].c_str()))
496 aExists.push_back(aNames[i]);
497 }
498 }
499
500 return S_OK;
501}
502
503HRESULT VFSExplorer::remove(const std::vector<com::Utf8Str> &aNames,
504 ComPtr<IProgress> &aProgress)
505{
506 AutoCaller autoCaller(this);
507 if (FAILED(autoCaller.rc())) return autoCaller.rc();
508
509 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
510
511 HRESULT rc = S_OK;
512
513 ComObjPtr<Progress> progress;
514 try
515 {
516 /* Create the progress object */
517 progress.createObject();
518
519 rc = progress->init(mVirtualBox, static_cast<IVFSExplorer*>(this),
520 Bstr(tr("Delete files")).raw(),
521 TRUE /* aCancelable */);
522 if (FAILED(rc)) throw rc;
523
524 /* Initialize our worker task */
525 TaskVFSExplorer* pTask = new TaskVFSExplorer(TaskVFSExplorer::Delete, this, progress);
526
527 /* Add all filenames to delete as task data */
528 for (size_t i = 0; i < aNames.size(); ++i)
529 pTask->filenames.push_back(aNames[i]);
530
531 //this function delete task in case of exceptions, so there is no need in the call of delete operator
532 rc = pTask->createThread(NULL, RTTHREADTYPE_MAIN_HEAVY_WORKER);
533 }
534 catch (HRESULT aRC)
535 {
536 rc = aRC;
537 }
538
539 if (SUCCEEDED(rc))
540 /* Return progress to the caller */
541 progress.queryInterfaceTo(aProgress.asOutParam());
542
543 return rc;
544}
545
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