VirtualBox

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

Last change on this file since 98351 was 98307, checked in by vboxsync, 23 months ago

Runtime/RTS3: Retire unused implementation, can be resurrected if required

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