VirtualBox

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

Last change on this file since 71191 was 69753, checked in by vboxsync, 7 years ago

iprt/dir: Morphing PRTDIR into a handle named RTDIR. (Been wanting to correct this for years. Don't know why I makde it a pointer rather than an abstrct handle like everything else.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: DnDDroppedFiles.cpp 69753 2017-11-19 14:27:58Z vboxsync $ */
2/** @file
3 * DnD: Directory handling.
4 */
5
6/*
7 * Copyright (C) 2014-2017 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
23#include <iprt/assert.h>
24#include <iprt/dir.h>
25#include <iprt/path.h>
26#include <iprt/string.h>
27
28#include <VBox/GuestHost/DragAndDrop.h>
29
30#ifdef LOG_GROUP
31 #undef LOG_GROUP
32#endif
33#define LOG_GROUP LOG_GROUP_GUEST_DND
34#include <VBox/log.h>
35
36DnDDroppedFiles::DnDDroppedFiles(void)
37 : m_fOpen(0)
38 , m_hDir(NULL) { }
39
40DnDDroppedFiles::DnDDroppedFiles(const char *pszPath, uint32_t fFlags)
41 : m_fOpen(0)
42 , m_hDir(NULL)
43{
44 OpenEx(pszPath, fFlags);
45}
46
47DnDDroppedFiles::~DnDDroppedFiles(void)
48{
49 /* Only make sure to not leak any handles and stuff, don't delete any
50 * directories / files here. */
51 closeInternal();
52}
53
54int DnDDroppedFiles::AddFile(const char *pszFile)
55{
56 AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
57
58 if (!this->m_lstFiles.contains(pszFile))
59 this->m_lstFiles.append(pszFile);
60 return VINF_SUCCESS;
61}
62
63int DnDDroppedFiles::AddDir(const char *pszDir)
64{
65 AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
66
67 if (!this->m_lstDirs.contains(pszDir))
68 this->m_lstDirs.append(pszDir);
69 return VINF_SUCCESS;
70}
71
72int DnDDroppedFiles::closeInternal(void)
73{
74 int rc;
75 if (this->m_hDir != NULL)
76 {
77 rc = RTDirClose(this->m_hDir);
78 if (RT_SUCCESS(rc))
79 this->m_hDir = NULL;
80 }
81 else
82 rc = VINF_SUCCESS;
83
84 LogFlowFuncLeaveRC(rc);
85 return rc;
86}
87
88int DnDDroppedFiles::Close(void)
89{
90 return closeInternal();
91}
92
93const char *DnDDroppedFiles::GetDirAbs(void) const
94{
95 return this->m_strPathAbs.c_str();
96}
97
98bool DnDDroppedFiles::IsOpen(void) const
99{
100 return (this->m_hDir != NULL);
101}
102
103int DnDDroppedFiles::OpenEx(const char *pszPath, uint32_t fFlags)
104{
105 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
106 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
107
108 int rc;
109
110 do
111 {
112 char pszDropDir[RTPATH_MAX];
113 RTStrPrintf(pszDropDir, sizeof(pszDropDir), "%s", pszPath);
114
115 /** @todo On Windows we also could use the registry to override
116 * this path, on Posix a dotfile and/or a guest property
117 * can be used. */
118
119 /* Append our base drop directory. */
120 rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), "VirtualBox Dropped Files"); /** @todo Make this tag configurable? */
121 if (RT_FAILURE(rc))
122 break;
123
124 /* Create it when necessary. */
125 if (!RTDirExists(pszDropDir))
126 {
127 rc = RTDirCreateFullPath(pszDropDir, RTFS_UNIX_IRWXU);
128 if (RT_FAILURE(rc))
129 break;
130 }
131
132 /* The actually drop directory consist of the current time stamp and a
133 * unique number when necessary. */
134 char pszTime[64];
135 RTTIMESPEC time;
136 if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))
137 {
138 rc = VERR_BUFFER_OVERFLOW;
139 break;
140 }
141
142 rc = DnDPathSanitizeFilename(pszTime, sizeof(pszTime));
143 if (RT_FAILURE(rc))
144 break;
145
146 rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), pszTime);
147 if (RT_FAILURE(rc))
148 break;
149
150 /* Create it (only accessible by the current user) */
151 rc = RTDirCreateUniqueNumbered(pszDropDir, sizeof(pszDropDir), RTFS_UNIX_IRWXU, 3, '-');
152 if (RT_SUCCESS(rc))
153 {
154 RTDIR hDir;
155 rc = RTDirOpen(&hDir, pszDropDir);
156 if (RT_SUCCESS(rc))
157 {
158 this->m_hDir = hDir;
159 this->m_strPathAbs = pszDropDir;
160 this->m_fOpen = fFlags;
161 }
162 }
163
164 } while (0);
165
166 LogFlowFuncLeaveRC(rc);
167 return rc;
168}
169
170int DnDDroppedFiles::OpenTemp(uint32_t fFlags)
171{
172 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
173
174 /*
175 * Get the user's temp directory. Don't use the user's root directory (or
176 * something inside it) because we don't know for how long/if the data will
177 * be kept after the guest OS used it.
178 */
179 char szTemp[RTPATH_MAX];
180 int rc = RTPathTemp(szTemp, sizeof(szTemp));
181 if (RT_SUCCESS(rc))
182 rc = OpenEx(szTemp, fFlags);
183
184 return rc;
185}
186
187int DnDDroppedFiles::Reset(bool fRemoveDropDir)
188{
189 int rc = closeInternal();
190 if (RT_SUCCESS(rc))
191 {
192 if (fRemoveDropDir)
193 {
194 rc = Rollback();
195 }
196 else
197 {
198 this->m_lstDirs.clear();
199 this->m_lstFiles.clear();
200 }
201 }
202
203 LogFlowFuncLeaveRC(rc);
204 return rc;
205}
206
207int DnDDroppedFiles::Reopen(void)
208{
209 if (this->m_strPathAbs.isEmpty())
210 return VERR_NOT_FOUND;
211
212 return OpenEx(this->m_strPathAbs.c_str(), this->m_fOpen);
213}
214
215int DnDDroppedFiles::Rollback(void)
216{
217 if (this->m_strPathAbs.isEmpty())
218 return VINF_SUCCESS;
219
220 int rc = VINF_SUCCESS;
221
222 /* Rollback by removing any stuff created.
223 * Note: Only remove empty directories, never ever delete
224 * anything recursive here! Steam (tm) knows best ... :-) */
225 int rc2;
226 for (size_t i = 0; i < this->m_lstFiles.size(); i++)
227 {
228 rc2 = RTFileDelete(this->m_lstFiles.at(i).c_str());
229 if (RT_SUCCESS(rc2))
230 this->m_lstFiles.removeAt(i);
231 else if (RT_SUCCESS(rc))
232 rc = rc2;
233 /* Keep going. */
234 }
235
236 for (size_t i = 0; i < this->m_lstDirs.size(); i++)
237 {
238 rc2 = RTDirRemove(this->m_lstDirs.at(i).c_str());
239 if (RT_SUCCESS(rc2))
240 this->m_lstDirs.removeAt(i);
241 else if (RT_SUCCESS(rc))
242 rc = rc2;
243 /* Keep going. */
244 }
245
246 if (RT_SUCCESS(rc))
247 {
248 Assert(this->m_lstFiles.isEmpty());
249 Assert(this->m_lstDirs.isEmpty());
250
251 rc2 = closeInternal();
252 if (RT_SUCCESS(rc2))
253 {
254 /* Try to remove the empty root dropped files directory as well.
255 * Might return VERR_DIR_NOT_EMPTY or similar. */
256 rc2 = RTDirRemove(this->m_strPathAbs.c_str());
257 }
258 if (RT_SUCCESS(rc))
259 rc = rc2;
260 }
261
262 LogFlowFuncLeaveRC(rc);
263 return rc;
264}
265
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