VirtualBox

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

Last change on this file since 58312 was 58212, checked in by vboxsync, 9 years ago

DnD: Updates.

  • Introduced protocol changelog in DragAndDropSvc.h.
  • Implemented protocol v3 with HOST_DND_HG_SND_DATA_HDR message for doing proper object accounting, among other parameters like checksumming and compression flags.
  • Encapsulated a lot of functionality in class hierarchies.
  • Renamed a lot of functions to make the usage more clear.
  • Various other bugfixes.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line 
1/* $Id: DnDDroppedFiles.cpp 58212 2015-10-13 11:49:33Z vboxsync $ */
2/** @file
3 * DnD: Directory handling.
4 */
5
6/*
7 * Copyright (C) 2014-2015 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 : hDir(NULL)
38 , fOpen(0) { }
39
40DnDDroppedFiles::DnDDroppedFiles(const char *pszPath, uint32_t fOpen)
41 : hDir(NULL)
42 , fOpen(0)
43{
44 OpenEx(pszPath, fOpen);
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->lstFiles.contains(pszFile))
59 this->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->lstDirs.contains(pszDir))
68 this->lstDirs.append(pszDir);
69 return VINF_SUCCESS;
70}
71
72int DnDDroppedFiles::closeInternal(void)
73{
74 int rc;
75 if (this->hDir != NULL)
76 {
77 rc = RTDirClose(this->hDir);
78 if (RT_SUCCESS(rc))
79 this->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->strPathAbs.c_str();
96}
97
98bool DnDDroppedFiles::IsOpen(void) const
99{
100 return (this->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 size_t cchDropDir = 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 PRTDIR phDir;
155 rc = RTDirOpen(&phDir, pszDropDir);
156 if (RT_SUCCESS(rc))
157 {
158 this->hDir = phDir;
159 this->strPathAbs = pszDropDir;
160 this->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->lstDirs.clear();
199 this->lstFiles.clear();
200 }
201 }
202
203 LogFlowFuncLeaveRC(rc);
204 return rc;
205}
206
207int DnDDroppedFiles::Reopen(void)
208{
209 if (this->strPathAbs.isEmpty())
210 return VERR_NOT_FOUND;
211
212 return OpenEx(this->strPathAbs.c_str(), this->fOpen);
213}
214
215int DnDDroppedFiles::Rollback(void)
216{
217 if (this->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->lstFiles.size(); i++)
227 {
228 rc2 = RTFileDelete(this->lstFiles.at(i).c_str());
229 if (RT_SUCCESS(rc2))
230 this->lstFiles.removeAt(i);
231
232 if (RT_SUCCESS(rc))
233 rc = rc2;
234 /* Keep going. */
235 }
236
237 for (size_t i = 0; i < this->lstDirs.size(); i++)
238 {
239 rc2 = RTDirRemove(this->lstDirs.at(i).c_str());
240 if (RT_SUCCESS(rc2))
241 this->lstDirs.removeAt(i);
242
243 if (RT_SUCCESS(rc))
244 rc = rc2;
245 /* Keep going. */
246 }
247
248 if (RT_SUCCESS(rc))
249 {
250 Assert(this->lstFiles.isEmpty());
251 Assert(this->lstDirs.isEmpty());
252
253 rc2 = closeInternal();
254 if (RT_SUCCESS(rc2))
255 {
256 /* Try to remove the empty root dropped files directory as well.
257 * Might return VERR_DIR_NOT_EMPTY or similar. */
258 rc2 = RTDirRemove(this->strPathAbs.c_str());
259 }
260 }
261
262 if (RT_SUCCESS(rc))
263 rc = rc2;
264
265 LogFlowFuncLeaveRC(rc);
266 return rc;
267}
268
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