VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp@ 78925

Last change on this file since 78925 was 78897, checked in by vboxsync, 6 years ago

Shared Clipboard/URI: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1/* $Id: ClipboardCache.cpp 78897 2019-05-31 15:23:14Z vboxsync $ */
2/** @file
3 * Shared Clipboard - Area handling.
4 */
5
6/*
7 * Copyright (C) 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_SHARED_CLIPBOARD
23#include <VBox/GuestHost/SharedClipboard-uri.h>
24
25#include <iprt/asm.h>
26#include <iprt/assert.h>
27#include <iprt/dir.h>
28#include <iprt/err.h>
29#include <iprt/file.h>
30#include <iprt/path.h>
31#include <iprt/string.h>
32
33
34#include <VBox/log.h>
35
36SharedClipboardArea::SharedClipboardArea(void)
37 : m_cRefs(0)
38 , m_fOpen(0)
39 , m_hDir(NIL_RTDIR)
40 , m_uID(NIL_SHAREDCLIPBOARDAREAID)
41{
42 int rc = initInternal();
43 if (RT_FAILURE(rc))
44 throw rc;
45}
46
47SharedClipboardArea::SharedClipboardArea(const char *pszPath,
48 SHAREDCLIPBOARDAREAID uID /* = NIL_SHAREDCLIPBOARDAREAID */,
49 SHAREDCLIPBOARDAREAFLAGS fFlags /* = SHAREDCLIPBOARDAREA_FLAGS_NONE */)
50 : m_tsCreatedMs(0)
51 , m_cRefs(0)
52 , m_fOpen(0)
53 , m_hDir(NIL_RTDIR)
54 , m_uID(uID)
55{
56 int rc = initInternal();
57 if (RT_SUCCESS(rc))
58 rc = OpenEx(pszPath, fFlags);
59
60 if (RT_FAILURE(rc))
61 throw rc;
62}
63
64SharedClipboardArea::~SharedClipboardArea(void)
65{
66 /* Only make sure to not leak any handles and stuff, don't delete any
67 * directories / files here. */
68 closeInternal();
69
70 int rc = destroyInternal();
71 AssertRC(rc);
72}
73
74/**
75 * Adds a reference to a Shared Clipboard area.
76 *
77 * @returns New reference count.
78 */
79uint32_t SharedClipboardArea::AddRef(void)
80{
81 return ASMAtomicIncU32(&m_cRefs);
82}
83
84/**
85 * Removes a reference from a Shared Clipboard area.
86 *
87 * @returns New reference count.
88 */
89uint32_t SharedClipboardArea::Release(void)
90{
91 Assert(m_cRefs);
92 return ASMAtomicDecU32(&m_cRefs);
93}
94
95/**
96 * Locks a Shared Clipboard area.
97 *
98 * @returns VBox status code.
99 */
100int SharedClipboardArea::Lock(void)
101{
102 return RTCritSectEnter(&m_CritSect);
103}
104
105/**
106 * Unlocks a Shared Clipboard area.
107 *
108 * @returns VBox status code.
109 */
110int SharedClipboardArea::Unlock(void)
111{
112 return RTCritSectLeave(&m_CritSect);
113}
114
115int SharedClipboardArea::AddFile(const char *pszFile)
116{
117 AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
118
119 if (!this->m_lstFiles.contains(pszFile))
120 this->m_lstFiles.append(pszFile);
121 return VINF_SUCCESS;
122}
123
124int SharedClipboardArea::AddDir(const char *pszDir)
125{
126 AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
127
128 if (!this->m_lstDirs.contains(pszDir))
129 this->m_lstDirs.append(pszDir);
130 return VINF_SUCCESS;
131}
132
133int SharedClipboardArea::initInternal(void)
134{
135 return RTCritSectInit(&m_CritSect);
136}
137
138int SharedClipboardArea::destroyInternal(void)
139{
140 return RTCritSectDelete(&m_CritSect);
141}
142
143int SharedClipboardArea::closeInternal(void)
144{
145 int rc;
146 if (this->m_hDir != NIL_RTDIR)
147 {
148 rc = RTDirClose(this->m_hDir);
149 if (RT_SUCCESS(rc))
150 this->m_hDir = NIL_RTDIR;
151 }
152 else
153 rc = VINF_SUCCESS;
154
155 if (RT_SUCCESS(rc))
156 rc = RTDirRemoveRecursive(m_strPathAbs.c_str(), RTDIRRMREC_F_CONTENT_AND_DIR);
157
158 if (RT_SUCCESS(rc))
159 {
160 this->m_fOpen = SHAREDCLIPBOARDAREA_FLAGS_NONE;
161 this->m_uID = NIL_SHAREDCLIPBOARDAREAID;
162 }
163
164 LogFlowFuncLeaveRC(rc);
165 return rc;
166}
167
168/**
169 * Construcuts an area's base path.
170 * Note: This does *not* create any directories or whatsoever!
171 *
172 * @returns VBox status code.
173 * @param pszBase Base path to use for the area.
174 * @param uID Area ID to use for the path.
175 * @param pszPath Where to store the constructured area base path.
176 * @param cbPath Size (in bytes) of the constructured area base path.
177 */
178/* static */
179int SharedClipboardArea::PathConstruct(const char *pszBase, SHAREDCLIPBOARDAREAID uID, char *pszPath, size_t cbPath)
180{
181 LogFlowFunc(("pszBase=%s, uAreaID=%RU32\n", pszBase, uID));
182
183 int rc = RTStrCopy(pszPath, cbPath, pszBase);
184 if (RT_SUCCESS(rc))
185 {
186 /** @todo On Windows we also could use the registry to override
187 * this path, on Posix a dotfile and/or a guest property
188 * can be used. */
189
190 /* Append our base area directory. */
191 rc = RTPathAppend(pszPath, cbPath, "VirtualBox Shared Clipboards"); /** @todo Make this tag configurable? */
192 if (RT_SUCCESS(rc))
193 {
194 rc = RTPathAppend(pszPath, cbPath, "Clipboard-");
195 if (RT_SUCCESS(rc))
196 {
197 char szID[8];
198 rc = RTStrFormatU32(szID, sizeof(szID), uID, 10, 0, 0, 0);
199 if (RT_SUCCESS(rc))
200 {
201 rc = RTStrCat(pszPath, cbPath, szID);
202 }
203 }
204 }
205 }
206
207 LogFlowFunc(("rc=%Rrc, szPath=%s\n", rc, pszPath));
208 return rc;
209}
210
211int SharedClipboardArea::Close(void)
212{
213 return closeInternal();
214}
215
216SHAREDCLIPBOARDAREAID SharedClipboardArea::GetAreaID(void) const
217{
218 return this->m_uID;
219}
220
221const char *SharedClipboardArea::GetDirAbs(void) const
222{
223 return this->m_strPathAbs.c_str();
224}
225
226uint32_t SharedClipboardArea::GetRefCount(void)
227{
228 return ASMAtomicReadU32(&m_cRefs);
229}
230
231bool SharedClipboardArea::IsOpen(void) const
232{
233 return (this->m_hDir != NULL);
234}
235
236int SharedClipboardArea::OpenEx(const char *pszPath,
237 SHAREDCLIPBOARDAREAID uID /* = NIL_SHAREDCLIPBOARDAREAID */,
238 SHAREDCLIPBOARDAREAFLAGS fFlags /* = SHAREDCLIPBOARDAREA_FLAGS_NONE */)
239{
240 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
241 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
242
243 char szAreaDir[RTPATH_MAX];
244 int rc = SharedClipboardArea::PathConstruct(pszPath, uID, szAreaDir, sizeof(szAreaDir));
245 if (RT_SUCCESS(rc))
246 {
247 if (!RTDirExists(szAreaDir))
248 rc = RTDirCreateFullPath(szAreaDir, RTFS_UNIX_IRWXU);
249
250 if (RT_SUCCESS(rc))
251 {
252 RTDIR hDir;
253 rc = RTDirOpen(&hDir, szAreaDir);
254 if (RT_SUCCESS(rc))
255 {
256 this->m_hDir = hDir;
257 this->m_strPathAbs = szAreaDir;
258 this->m_fOpen = fFlags;
259 this->m_uID = uID;
260 this->m_tsCreatedMs = RTTimeMilliTS();
261 }
262 }
263 }
264
265 LogFlowFuncLeaveRC(rc);
266 return rc;
267}
268
269int SharedClipboardArea::OpenTemp(SHAREDCLIPBOARDAREAID uID,
270 SHAREDCLIPBOARDAREAFLAGS fFlags /* = SHAREDCLIPBOARDAREA_FLAGS_NONE */)
271{
272 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
273
274 /*
275 * Get the user's temp directory. Don't use the user's root directory (or
276 * something inside it) because we don't know for how long/if the data will
277 * be kept after the guest OS used it.
278 */
279 char szTemp[RTPATH_MAX];
280 int rc = RTPathTemp(szTemp, sizeof(szTemp));
281 if (RT_SUCCESS(rc))
282 rc = OpenEx(szTemp, uID, fFlags);
283
284 return rc;
285}
286
287int SharedClipboardArea::Reset(bool fDeleteContent)
288{
289 int rc = closeInternal();
290 if (RT_SUCCESS(rc))
291 {
292 if (fDeleteContent)
293 {
294 rc = Rollback();
295 }
296 else
297 {
298 this->m_lstDirs.clear();
299 this->m_lstFiles.clear();
300 }
301 }
302
303 LogFlowFuncLeaveRC(rc);
304 return rc;
305}
306
307int SharedClipboardArea::Reopen(void)
308{
309 if (this->m_strPathAbs.isEmpty())
310 return VERR_NOT_FOUND;
311
312 return OpenEx(this->m_strPathAbs.c_str(), this->m_fOpen);
313}
314
315int SharedClipboardArea::Rollback(void)
316{
317 if (this->m_strPathAbs.isEmpty())
318 return VINF_SUCCESS;
319
320 int rc = VINF_SUCCESS;
321
322 /* Rollback by removing any stuff created.
323 * Note: Only remove empty directories, never ever delete
324 * anything recursive here! Steam (tm) knows best ... :-) */
325 int rc2;
326 for (size_t i = 0; i < this->m_lstFiles.size(); i++)
327 {
328 rc2 = RTFileDelete(this->m_lstFiles.at(i).c_str());
329 if (RT_SUCCESS(rc2))
330 this->m_lstFiles.removeAt(i);
331 else if (RT_SUCCESS(rc))
332 rc = rc2;
333 /* Keep going. */
334 }
335
336 for (size_t i = 0; i < this->m_lstDirs.size(); i++)
337 {
338 rc2 = RTDirRemove(this->m_lstDirs.at(i).c_str());
339 if (RT_SUCCESS(rc2))
340 this->m_lstDirs.removeAt(i);
341 else if (RT_SUCCESS(rc))
342 rc = rc2;
343 /* Keep going. */
344 }
345
346 if (RT_SUCCESS(rc))
347 {
348 Assert(this->m_lstFiles.isEmpty());
349 Assert(this->m_lstDirs.isEmpty());
350
351 rc2 = closeInternal();
352 if (RT_SUCCESS(rc2))
353 {
354 /* Try to remove the empty root dropped files directory as well.
355 * Might return VERR_DIR_NOT_EMPTY or similar. */
356 rc2 = RTDirRemove(this->m_strPathAbs.c_str());
357 }
358 if (RT_SUCCESS(rc))
359 rc = rc2;
360 }
361
362 LogFlowFuncLeaveRC(rc);
363 return rc;
364}
365
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