VirtualBox

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

Last change on this file since 78293 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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