VirtualBox

source: vbox/trunk/src/VBox/GuestHost/DragAndDrop/DnDDroppedFiles.cpp@ 85027

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

DnD/DroppedFiles: Renaming.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.9 KB
Line 
1/* $Id: DnDDroppedFiles.cpp 85027 2020-07-01 14:30:46Z vboxsync $ */
2/** @file
3 * DnD - Directory handling.
4 */
5
6/*
7 * Copyright (C) 2014-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
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_GUEST_DND
23#include <VBox/GuestHost/DragAndDrop.h>
24
25#include <iprt/assert.h>
26#include <iprt/dir.h>
27#include <iprt/err.h>
28#include <iprt/file.h>
29#include <iprt/path.h>
30#include <iprt/string.h>
31
32
33#include <VBox/log.h>
34
35DnDDroppedFiles::DnDDroppedFiles(void)
36 : m_fOpen(0)
37 , m_hDir(NULL) { }
38
39DnDDroppedFiles::DnDDroppedFiles(const char *pszPath, DNDURIDROPPEDFILEFLAGS fFlags /* = DNDURIDROPPEDFILE_FLAGS_NONE */)
40 : m_fOpen(0)
41 , m_hDir(NULL)
42{
43 OpenEx(pszPath, fFlags);
44}
45
46DnDDroppedFiles::~DnDDroppedFiles(void)
47{
48 /* Only make sure to not leak any handles and stuff, don't delete any
49 * directories / files here. */
50 closeInternal();
51}
52
53/**
54 * Adds a file reference to a dropped files directory.
55 *
56 * @returns VBox status code.
57 * @param pszFile Path of file entry to add.
58 */
59int DnDDroppedFiles::AddFile(const char *pszFile)
60{
61 AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
62
63 if (!this->m_lstFiles.contains(pszFile))
64 this->m_lstFiles.append(pszFile);
65 return VINF_SUCCESS;
66}
67
68/**
69 * Adds a directory reference to a dropped files directory.
70 * Note: This does *not* (recursively) add sub entries.
71 *
72 * @returns VBox status code.
73 * @param pszDir Path of directory entry to add.
74 */
75int DnDDroppedFiles::AddDir(const char *pszDir)
76{
77 AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
78
79 if (!this->m_lstDirs.contains(pszDir))
80 this->m_lstDirs.append(pszDir);
81 return VINF_SUCCESS;
82}
83
84/**
85 * Closes the dropped files directory handle, internal version.
86 *
87 * @returns VBox status code.
88 */
89int DnDDroppedFiles::closeInternal(void)
90{
91 int rc;
92 if (this->m_hDir != NULL)
93 {
94 rc = RTDirClose(this->m_hDir);
95 if (RT_SUCCESS(rc))
96 this->m_hDir = NULL;
97 }
98 else
99 rc = VINF_SUCCESS;
100
101 LogFlowFuncLeaveRC(rc);
102 return rc;
103}
104
105/**
106 * Closes the dropped files directory handle.
107 *
108 * @returns VBox status code.
109 */
110int DnDDroppedFiles::Close(void)
111{
112 return closeInternal();
113}
114
115/**
116 * Returns the absolute path of the dropped files directory.
117 *
118 * @returns Pointer to absolute path of the dropped files directory.
119 */
120const char *DnDDroppedFiles::GetDirAbs(void) const
121{
122 return this->m_strPathAbs.c_str();
123}
124
125/**
126 * Returns whether the dropped files directory has been opened or not.
127 *
128 * @returns \c true if open, \c false if not.
129 */
130bool DnDDroppedFiles::IsOpen(void) const
131{
132 return (this->m_hDir != NULL);
133}
134
135/**
136 * Opens (creates) the dropped files directory.
137 *
138 * @returns VBox status code.
139 * @param pszPath Absolute path where to create the dropped files directory.
140 * @param fFlags Dropped files flags to use for this directory.
141 */
142int DnDDroppedFiles::OpenEx(const char *pszPath, DNDURIDROPPEDFILEFLAGS fFlags /* = DNDURIDROPPEDFILE_FLAGS_NONE */)
143{
144 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
145 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
146
147 int rc;
148
149 do
150 {
151 char szDropDir[RTPATH_MAX];
152 RTStrPrintf(szDropDir, sizeof(szDropDir), "%s", pszPath);
153
154 /** @todo On Windows we also could use the registry to override
155 * this path, on Posix a dotfile and/or a guest property
156 * can be used. */
157
158 /* Append our base drop directory. */
159 rc = RTPathAppend(szDropDir, sizeof(szDropDir), "VirtualBox Dropped Files"); /** @todo Make this tag configurable? */
160 if (RT_FAILURE(rc))
161 break;
162
163 /* Create it when necessary. */
164 if (!RTDirExists(szDropDir))
165 {
166 rc = RTDirCreateFullPath(szDropDir, RTFS_UNIX_IRWXU);
167 if (RT_FAILURE(rc))
168 break;
169 }
170
171 /* The actually drop directory consist of the current time stamp and a
172 * unique number when necessary. */
173 char szTime[64];
174 RTTIMESPEC time;
175 if (!RTTimeSpecToString(RTTimeNow(&time), szTime, sizeof(szTime)))
176 {
177 rc = VERR_BUFFER_OVERFLOW;
178 break;
179 }
180
181 rc = DnDPathSanitizeFilename(szTime, sizeof(szTime));
182 if (RT_FAILURE(rc))
183 break;
184
185 rc = RTPathAppend(szDropDir, sizeof(szDropDir), szTime);
186 if (RT_FAILURE(rc))
187 break;
188
189 /* Create it (only accessible by the current user) */
190 rc = RTDirCreateUniqueNumbered(szDropDir, sizeof(szDropDir), RTFS_UNIX_IRWXU, 3, '-');
191 if (RT_SUCCESS(rc))
192 {
193 RTDIR hDir;
194 rc = RTDirOpen(&hDir, szDropDir);
195 if (RT_SUCCESS(rc))
196 {
197 this->m_hDir = hDir;
198 this->m_strPathAbs = szDropDir;
199 this->m_fOpen = fFlags;
200 }
201 }
202
203 } while (0);
204
205 LogFlowFuncLeaveRC(rc);
206 return rc;
207}
208
209/**
210 * Opens (creates) the dropped files directory in the system's temp directory.
211 *
212 * @returns VBox status code.
213 * @param fFlags Dropped files flags to use for this directory.
214 */
215int DnDDroppedFiles::OpenTemp(DNDURIDROPPEDFILEFLAGS fFlags /* = DNDURIDROPPEDFILE_FLAGS_NONE */)
216{
217 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
218
219 /*
220 * Get the user's temp directory. Don't use the user's root directory (or
221 * something inside it) because we don't know for how long/if the data will
222 * be kept after the guest OS used it.
223 */
224 char szTemp[RTPATH_MAX];
225 int rc = RTPathTemp(szTemp, sizeof(szTemp));
226 if (RT_SUCCESS(rc))
227 rc = OpenEx(szTemp, fFlags);
228
229 return rc;
230}
231
232/**
233 * Resets a droppped files directory.
234 *
235 * @returns VBox status code.
236 * @param fDelete Whether to physically delete the directory and its content
237 * or just clear the internal references.
238 */
239int DnDDroppedFiles::Reset(bool fDelete)
240{
241 int rc = closeInternal();
242 if (RT_SUCCESS(rc))
243 {
244 if (fDelete)
245 {
246 rc = Rollback();
247 }
248 else
249 {
250 this->m_lstDirs.clear();
251 this->m_lstFiles.clear();
252 }
253 }
254
255 LogFlowFuncLeaveRC(rc);
256 return rc;
257}
258
259/**
260 * Re-opens a droppes files directory.
261 *
262 * @returns VBox status code, or VERR_NOT_FOUND if the dropped files directory has not been opened before.
263 */
264int DnDDroppedFiles::Reopen(void)
265{
266 if (this->m_strPathAbs.isEmpty())
267 return VERR_NOT_FOUND;
268
269 return OpenEx(this->m_strPathAbs.c_str(), this->m_fOpen);
270}
271
272/**
273 * Performs a rollback of a dropped files directory.
274 * This cleans the directory by physically deleting all files / directories which have been added before.
275 *
276 * @returns VBox status code.
277 */
278int DnDDroppedFiles::Rollback(void)
279{
280 if (this->m_strPathAbs.isEmpty())
281 return VINF_SUCCESS;
282
283 int rc = VINF_SUCCESS;
284
285 /* Rollback by removing any stuff created.
286 * Note: Only remove empty directories, never ever delete
287 * anything recursive here! Steam (tm) knows best ... :-) */
288 int rc2;
289 for (size_t i = 0; i < this->m_lstFiles.size(); i++)
290 {
291 rc2 = RTFileDelete(this->m_lstFiles.at(i).c_str());
292 if (RT_SUCCESS(rc2))
293 this->m_lstFiles.removeAt(i);
294 else if (RT_SUCCESS(rc))
295 rc = rc2;
296 /* Keep going. */
297 }
298
299 for (size_t i = 0; i < this->m_lstDirs.size(); i++)
300 {
301 rc2 = RTDirRemove(this->m_lstDirs.at(i).c_str());
302 if (RT_SUCCESS(rc2))
303 this->m_lstDirs.removeAt(i);
304 else if (RT_SUCCESS(rc))
305 rc = rc2;
306 /* Keep going. */
307 }
308
309 if (RT_SUCCESS(rc))
310 {
311 Assert(this->m_lstFiles.isEmpty());
312 Assert(this->m_lstDirs.isEmpty());
313
314 rc2 = closeInternal();
315 if (RT_SUCCESS(rc2))
316 {
317 /* Try to remove the empty root dropped files directory as well.
318 * Might return VERR_DIR_NOT_EMPTY or similar. */
319 rc2 = RTDirRemove(this->m_strPathAbs.c_str());
320 }
321 if (RT_SUCCESS(rc))
322 rc = rc2;
323 }
324
325 LogFlowFuncLeaveRC(rc);
326 return rc;
327}
328
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