VirtualBox

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

Last change on this file since 85672 was 85218, checked in by vboxsync, 4 years ago

Main/VFSExplorerImpl.cpp: Corrected totally messed up i_iprtToVfsObjType code. Use RTFOFF for the DirEntry size to avoid sign conversion non-sense. bugref:9790

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.5 KB
Line 
1/* $Id: VFSExplorerImpl.cpp 85218 2020-07-11 14:09:04Z vboxsync $ */
2/** @file
3 * IVFSExplorer COM class implementations.
4 */
5
6/*
7 * Copyright (C) 2009-2020 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#define LOG_GROUP LOG_GROUP_MAIN_VFSEXPLORER
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 "LoggingNew.h"
36#include "ThreadTask.h"
37
38#include <memory>
39
40struct VFSExplorer::Data
41{
42 struct DirEntry
43 {
44 DirEntry(Utf8Str strName, FsObjType_T fileType, RTFOFF cbSize, uint32_t fMode)
45 : name(strName)
46 , type(fileType)
47 , size(cbSize)
48 , mode(fMode) {}
49
50 Utf8Str name;
51 FsObjType_T type;
52 RTFOFF size;
53 uint32_t mode;
54 };
55
56 VFSType_T storageType;
57 Utf8Str strUsername;
58 Utf8Str strPassword;
59 Utf8Str strHostname;
60 Utf8Str strPath;
61 Utf8Str strBucket;
62 std::list<DirEntry> entryList;
63};
64
65
66VFSExplorer::VFSExplorer()
67 : mVirtualBox(NULL)
68{
69}
70
71VFSExplorer::~VFSExplorer()
72{
73}
74
75
76/**
77 * VFSExplorer COM initializer.
78 * @param aType VFS type.
79 * @param aFilePath File path.
80 * @param aHostname Host name.
81 * @param aUsername User name.
82 * @param aPassword Password.
83 * @param aVirtualBox VirtualBox object.
84 * @return
85 */
86HRESULT VFSExplorer::init(VFSType_T aType, Utf8Str aFilePath, Utf8Str aHostname, Utf8Str aUsername,
87 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 aPath Where to store the path.
134 * @return
135 */
136HRESULT VFSExplorer::getPath(com::Utf8Str &aPath)
137{
138 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
139
140 aPath = m->strPath;
141
142 return S_OK;
143}
144
145
146HRESULT VFSExplorer::getType(VFSType_T *aType)
147{
148 if (!aType)
149 return E_POINTER;
150
151 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
152
153 *aType = m->storageType;
154
155 return S_OK;
156}
157
158class VFSExplorer::TaskVFSExplorer : public ThreadTask
159{
160public:
161 enum TaskType
162 {
163 Update,
164 Delete
165 };
166
167 TaskVFSExplorer(TaskType aTaskType, VFSExplorer *aThat, Progress *aProgress)
168 : m_taskType(aTaskType),
169 m_pVFSExplorer(aThat),
170 m_ptrProgress(aProgress),
171 m_rc(S_OK)
172 {
173 m_strTaskName = "Explorer::Task";
174 }
175 ~TaskVFSExplorer() {}
176
177private:
178 void handler();
179
180#if 0 /* unused */
181 static DECLCALLBACK(int) uploadProgress(unsigned uPercent, void *pvUser);
182#endif
183
184 TaskType m_taskType;
185 VFSExplorer *m_pVFSExplorer;
186
187 ComObjPtr<Progress> m_ptrProgress;
188 HRESULT m_rc;
189
190 /* task data */
191 std::list<Utf8Str> m_lstFilenames;
192
193 friend class VFSExplorer;
194};
195
196/* static */
197void VFSExplorer::TaskVFSExplorer::handler()
198{
199 VFSExplorer *pVFSExplorer = this->m_pVFSExplorer;
200
201 LogFlowFuncEnter();
202 LogFlowFunc(("VFSExplorer %p\n", pVFSExplorer));
203
204 HRESULT rc = S_OK;
205
206 switch (this->m_taskType)
207 {
208 case TaskVFSExplorer::Update:
209 {
210 if (pVFSExplorer->m->storageType == VFSType_File)
211 rc = pVFSExplorer->i_updateFS(this);
212 else if (pVFSExplorer->m->storageType == VFSType_S3)
213 rc = E_NOTIMPL;
214 break;
215 }
216 case TaskVFSExplorer::Delete:
217 {
218 if (pVFSExplorer->m->storageType == VFSType_File)
219 rc = pVFSExplorer->i_deleteFS(this);
220 else if (pVFSExplorer->m->storageType == VFSType_S3)
221 rc = E_NOTIMPL;
222 break;
223 }
224 default:
225 AssertMsgFailed(("Invalid task type %u specified!\n", this->m_taskType));
226 break;
227 }
228
229 LogFlowFunc(("rc=%Rhrc\n", rc)); NOREF(rc);
230 LogFlowFuncLeave();
231}
232
233#if 0 /* unused */
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->m_ptrProgress.isNull())
241 {
242 BOOL fCanceled;
243 pTask->m_ptrProgress->COMGETTER(Canceled)(&fCanceled);
244 if (fCanceled)
245 return -1;
246 pTask->m_ptrProgress->SetCurrentOperationProgress(uPercent);
247 }
248 return VINF_SUCCESS;
249}
250#endif
251
252FsObjType_T VFSExplorer::i_iprtToVfsObjType(RTFMODE aType) const
253{
254 switch (aType & RTFS_TYPE_MASK)
255 {
256 case RTFS_TYPE_DIRECTORY: return FsObjType_Directory;
257 case RTFS_TYPE_FILE: return FsObjType_File;
258 case RTFS_TYPE_SYMLINK: return FsObjType_Symlink;
259 case RTFS_TYPE_FIFO: return FsObjType_Fifo;
260 case RTFS_TYPE_DEV_CHAR: return FsObjType_DevChar;
261 case RTFS_TYPE_DEV_BLOCK: return FsObjType_DevBlock;
262 case RTFS_TYPE_SOCKET: return FsObjType_Socket;
263 case RTFS_TYPE_WHITEOUT: return FsObjType_WhiteOut;
264 default: return FsObjType_Unknown;
265 }
266}
267
268HRESULT VFSExplorer::i_updateFS(TaskVFSExplorer *aTask)
269{
270 LogFlowFuncEnter();
271
272 AutoCaller autoCaller(this);
273 if (FAILED(autoCaller.rc())) return autoCaller.rc();
274
275 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
276
277 HRESULT rc = S_OK;
278
279 std::list<VFSExplorer::Data::DirEntry> fileList;
280 RTDIR hDir;
281 int vrc = RTDirOpen(&hDir, m->strPath.c_str());
282 if (RT_SUCCESS(vrc))
283 {
284 try
285 {
286 if (aTask->m_ptrProgress)
287 aTask->m_ptrProgress->SetCurrentOperationProgress(33);
288 RTDIRENTRYEX entry;
289 while (RT_SUCCESS(vrc))
290 {
291 vrc = RTDirReadEx(hDir, &entry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
292 if (RT_SUCCESS(vrc))
293 {
294 Utf8Str name(entry.szName);
295 if ( name != "."
296 && name != "..")
297 fileList.push_back(VFSExplorer::Data::DirEntry(name, i_iprtToVfsObjType(entry.Info.Attr.fMode),
298 entry.Info.cbObject,
299 entry.Info.Attr.fMode
300 & (RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXG | RTFS_UNIX_IRWXO)));
301 }
302 }
303 if (aTask->m_ptrProgress)
304 aTask->m_ptrProgress->SetCurrentOperationProgress(66);
305 }
306 catch (HRESULT aRC)
307 {
308 rc = aRC;
309 }
310
311 /* Clean up */
312 RTDirClose(hDir);
313 }
314 else
315 rc = setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr ("Can't open directory '%s' (%Rrc)"), m->strPath.c_str(), vrc);
316
317 if (aTask->m_ptrProgress)
318 aTask->m_ptrProgress->SetCurrentOperationProgress(99);
319
320 /* Assign the result on success (this clears the old list) */
321 if (rc == S_OK)
322 m->entryList.assign(fileList.begin(), fileList.end());
323
324 aTask->m_rc = rc;
325
326 if (!aTask->m_ptrProgress.isNull())
327 aTask->m_ptrProgress->i_notifyComplete(rc);
328
329 LogFlowFunc(("rc=%Rhrc\n", rc));
330 LogFlowFuncLeave();
331
332 return S_OK; /** @todo ??? */
333}
334
335HRESULT VFSExplorer::i_deleteFS(TaskVFSExplorer *aTask)
336{
337 LogFlowFuncEnter();
338
339 AutoCaller autoCaller(this);
340 if (FAILED(autoCaller.rc())) return autoCaller.rc();
341
342 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
343
344 HRESULT rc = S_OK;
345
346 float fPercentStep = 100.0f / (float)aTask->m_lstFilenames.size();
347 try
348 {
349 char szPath[RTPATH_MAX];
350 std::list<Utf8Str>::const_iterator it;
351 size_t i = 0;
352 for (it = aTask->m_lstFilenames.begin();
353 it != aTask->m_lstFilenames.end();
354 ++it, ++i)
355 {
356 int vrc = RTPathJoin(szPath, sizeof(szPath), m->strPath.c_str(), (*it).c_str());
357 if (RT_FAILURE(vrc))
358 throw setErrorBoth(E_FAIL, vrc, tr("Internal Error (%Rrc)"), vrc);
359 vrc = RTFileDelete(szPath);
360 if (RT_FAILURE(vrc))
361 throw setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Can't delete file '%s' (%Rrc)"), szPath, vrc);
362 if (aTask->m_ptrProgress)
363 aTask->m_ptrProgress->SetCurrentOperationProgress((ULONG)(fPercentStep * (float)i));
364 }
365 }
366 catch (HRESULT aRC)
367 {
368 rc = aRC;
369 }
370
371 aTask->m_rc = rc;
372
373 if (aTask->m_ptrProgress.isNotNull())
374 aTask->m_ptrProgress->i_notifyComplete(rc);
375
376 LogFlowFunc(("rc=%Rhrc\n", rc));
377 LogFlowFuncLeave();
378
379 return VINF_SUCCESS;
380}
381
382HRESULT VFSExplorer::update(ComPtr<IProgress> &aProgress)
383{
384 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
385
386 HRESULT rc = S_OK;
387
388 ComObjPtr<Progress> progress;
389 try
390 {
391 Bstr progressDesc = BstrFmt(tr("Update directory info for '%s'"),
392 m->strPath.c_str());
393 /* Create the progress object */
394 progress.createObject();
395
396 rc = progress->init(mVirtualBox,
397 static_cast<IVFSExplorer*>(this),
398 progressDesc.raw(),
399 TRUE /* aCancelable */);
400 if (FAILED(rc)) throw rc;
401
402 /* Initialize our worker task */
403 TaskVFSExplorer* pTask = new TaskVFSExplorer(TaskVFSExplorer::Update, this, progress);
404
405 //this function delete task in case of exceptions, so there is no need in the call of delete operator
406 rc = pTask->createThreadWithType(RTTHREADTYPE_MAIN_HEAVY_WORKER);
407 }
408 catch (HRESULT aRC)
409 {
410 rc = aRC;
411 }
412
413 if (SUCCEEDED(rc))
414 /* Return progress to the caller */
415 progress.queryInterfaceTo(aProgress.asOutParam());
416
417 return rc;
418}
419
420HRESULT VFSExplorer::cd(const com::Utf8Str &aDir, ComPtr<IProgress> &aProgress)
421{
422 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
423 m->strPath = aDir;
424 return update(aProgress);
425}
426
427HRESULT VFSExplorer::cdUp(ComPtr<IProgress> &aProgress)
428{
429 Utf8Str strUpPath;
430 {
431 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
432 /* Remove lowest dir entry in a platform neutral way. */
433 char *pszNewPath = RTStrDup(m->strPath.c_str());
434 RTPathStripTrailingSlash(pszNewPath);
435 RTPathStripFilename(pszNewPath);
436 strUpPath = pszNewPath;
437 RTStrFree(pszNewPath);
438 }
439
440 return cd(strUpPath, aProgress);
441}
442
443HRESULT VFSExplorer::entryList(std::vector<com::Utf8Str> &aNames,
444 std::vector<ULONG> &aTypes,
445 std::vector<LONG64> &aSizes,
446 std::vector<ULONG> &aModes)
447{
448 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
449 aNames.resize(m->entryList.size());
450 aTypes.resize(m->entryList.size());
451 aSizes.resize(m->entryList.size());
452 aModes.resize(m->entryList.size());
453
454 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
455 size_t i = 0;
456 for (it = m->entryList.begin();
457 it != m->entryList.end();
458 ++it, ++i)
459 {
460 const VFSExplorer::Data::DirEntry &entry = (*it);
461 aNames[i] = entry.name;
462 aTypes[i] = entry.type;
463 aSizes[i] = entry.size;
464 aModes[i] = entry.mode;
465 }
466
467 return S_OK;
468}
469
470HRESULT VFSExplorer::exists(const std::vector<com::Utf8Str> &aNames,
471 std::vector<com::Utf8Str> &aExists)
472{
473
474 AutoCaller autoCaller(this);
475 if (FAILED(autoCaller.rc())) return autoCaller.rc();
476
477 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
478 aExists.resize(0);
479 for (size_t i=0; i < aNames.size(); ++i)
480 {
481 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
482 for (it = m->entryList.begin();
483 it != m->entryList.end();
484 ++it)
485 {
486 const VFSExplorer::Data::DirEntry &entry = (*it);
487 if (entry.name == RTPathFilename(aNames[i].c_str()))
488 aExists.push_back(aNames[i]);
489 }
490 }
491
492 return S_OK;
493}
494
495HRESULT VFSExplorer::remove(const std::vector<com::Utf8Str> &aNames,
496 ComPtr<IProgress> &aProgress)
497{
498 AutoCaller autoCaller(this);
499 if (FAILED(autoCaller.rc())) return autoCaller.rc();
500
501 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
502
503 HRESULT rc = S_OK;
504
505 ComObjPtr<Progress> progress;
506 try
507 {
508 /* Create the progress object */
509 progress.createObject();
510
511 rc = progress->init(mVirtualBox, static_cast<IVFSExplorer*>(this),
512 Bstr(tr("Delete files")).raw(),
513 TRUE /* aCancelable */);
514 if (FAILED(rc)) throw rc;
515
516 /* Initialize our worker task */
517 TaskVFSExplorer* pTask = new TaskVFSExplorer(TaskVFSExplorer::Delete, this, progress);
518
519 /* Add all filenames to delete as task data */
520 for (size_t i = 0; i < aNames.size(); ++i)
521 pTask->m_lstFilenames.push_back(aNames[i]);
522
523 //this function delete task in case of exceptions, so there is no need in the call of delete operator
524 rc = pTask->createThreadWithType(RTTHREADTYPE_MAIN_HEAVY_WORKER);
525 }
526 catch (HRESULT aRC)
527 {
528 rc = aRC;
529 }
530
531 if (SUCCEEDED(rc))
532 /* Return progress to the caller */
533 progress.queryInterfaceTo(aProgress.asOutParam());
534
535 return rc;
536}
537
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