VirtualBox

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

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