VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/ClipboardArea.cpp@ 85794

Last change on this file since 85794 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/* $Id: ClipboardArea.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * Shared Clipboard - Area handling.
4 */
5
6/*
7 * Copyright (C) 2019-2020 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-transfers.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_SHCLAREAID)
41{
42 int rc = initInternal();
43 if (RT_FAILURE(rc))
44 throw rc;
45}
46
47SharedClipboardArea::SharedClipboardArea(const char *pszPath,
48 SHCLAREAID uID /* = NIL_SHCLAREAID */,
49 SHCLAREAOPENFLAGS fFlags /* = SHCLAREA_OPEN_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 ++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 if (m_cRefs)
92 m_cRefs--;
93
94 return m_cRefs;
95}
96
97/**
98 * Locks a Shared Clipboard area.
99 *
100 * @returns VBox status code.
101 */
102int SharedClipboardArea::Lock(void)
103{
104 return RTCritSectEnter(&m_CritSect);
105}
106
107/**
108 * Unlocks a Shared Clipboard area.
109 *
110 * @returns VBox status code.
111 */
112int SharedClipboardArea::Unlock(void)
113{
114 return RTCritSectLeave(&m_CritSect);
115}
116
117int SharedClipboardArea::AddObject(const char *pszPath, const SHCLAREAOBJ &Obj)
118{
119 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
120
121 AssertReturn(m_mapObj.find(pszPath) == m_mapObj.end(), VERR_ALREADY_EXISTS);
122
123 m_mapObj[pszPath] = Obj; /** @todo Throw? */
124
125 return VINF_SUCCESS;
126}
127
128int SharedClipboardArea::GetObject(const char *pszPath, PSHCLAREAOBJ pObj)
129{
130 SharedClipboardAreaFsObjMap::const_iterator itObj = m_mapObj.find(pszPath);
131 if (itObj != m_mapObj.end())
132 {
133 *pObj = itObj->second;
134 return VINF_SUCCESS;
135 }
136
137 return VERR_NOT_FOUND;
138}
139
140int SharedClipboardArea::initInternal(void)
141{
142 return RTCritSectInit(&m_CritSect);
143}
144
145int SharedClipboardArea::destroyInternal(void)
146{
147 return RTCritSectDelete(&m_CritSect);
148}
149
150int SharedClipboardArea::closeInternal(void)
151{
152 int rc;
153 if (this->m_hDir != NIL_RTDIR)
154 {
155 rc = RTDirClose(this->m_hDir);
156 if (RT_SUCCESS(rc))
157 this->m_hDir = NIL_RTDIR;
158 }
159 else
160 rc = VINF_SUCCESS;
161
162 if ( RT_SUCCESS(rc)
163 && m_strPathAbs.isNotEmpty())
164 rc = RTDirRemoveRecursive(m_strPathAbs.c_str(), RTDIRRMREC_F_CONTENT_AND_DIR);
165
166 if (RT_SUCCESS(rc))
167 {
168 this->m_fOpen = SHCLAREA_OPEN_FLAGS_NONE;
169 this->m_uID = NIL_SHCLAREAID;
170 }
171
172 LogFlowFuncLeaveRC(rc);
173 return rc;
174}
175
176/**
177 * Construcuts an area's base path.
178 * Note: This does *not* create any directories or whatsoever!
179 *
180 * @returns VBox status code.
181 * @param pszBase Base path to use for the area.
182 * @param uID Area ID to use for the path.
183 * @param pszPath Where to store the constructured area base path.
184 * @param cbPath Size (in bytes) of the constructured area base path.
185 */
186/* static */
187int SharedClipboardArea::PathConstruct(const char *pszBase, SHCLAREAID uID, char *pszPath, size_t cbPath)
188{
189 LogFlowFunc(("pszBase=%s, uAreaID=%RU32\n", pszBase, uID));
190
191 int rc = RTStrCopy(pszPath, cbPath, pszBase);
192 if (RT_SUCCESS(rc))
193 {
194 /** @todo On Windows we also could use the registry to override
195 * this path, on Posix a dotfile and/or a guest property
196 * can be used. */
197
198 /* Append our base area directory. */
199 rc = RTPathAppend(pszPath, cbPath, "VirtualBox Shared Clipboards"); /** @todo Make this tag configurable? */
200 if (RT_SUCCESS(rc))
201 {
202 rc = RTPathAppend(pszPath, cbPath, "Clipboard-");
203 if (RT_SUCCESS(rc))
204 {
205 char szID[16];
206 ssize_t cchID = RTStrFormatU32(szID, sizeof(szID), uID, 10, 0, 0, 0);
207 if (cchID)
208 {
209 rc = RTStrCat(pszPath, cbPath, szID);
210 }
211 else
212 rc = VERR_INVALID_PARAMETER;
213 }
214 }
215 }
216
217 LogFlowFunc(("rc=%Rrc, szPath=%s\n", rc, pszPath));
218 return rc;
219}
220
221int SharedClipboardArea::Close(void)
222{
223 return closeInternal();
224}
225
226SHCLAREAID SharedClipboardArea::GetID(void) const
227{
228 return this->m_uID;
229}
230
231const char *SharedClipboardArea::GetDirAbs(void) const
232{
233 return this->m_strPathAbs.c_str();
234}
235
236uint32_t SharedClipboardArea::GetRefCount(void)
237{
238 return ASMAtomicReadU32(&m_cRefs);
239}
240
241bool SharedClipboardArea::IsOpen(void) const
242{
243 return (this->m_hDir != NULL);
244}
245
246int SharedClipboardArea::OpenEx(const char *pszPath,
247 SHCLAREAID uID /* = NIL_SHCLAREAID */,
248 SHCLAREAOPENFLAGS fFlags /* = SHCLAREA_OPEN_FLAGS_NONE */)
249{
250 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
251 AssertReturn(!(fFlags & ~SHCLAREA_OPEN_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
252
253 char szAreaDir[RTPATH_MAX];
254 int rc = SharedClipboardArea::PathConstruct(pszPath, uID, szAreaDir, sizeof(szAreaDir));
255 if (RT_SUCCESS(rc))
256 {
257 if ( RTDirExists(szAreaDir)
258 && (fFlags & SHCLAREA_OPEN_FLAGS_MUST_NOT_EXIST))
259 {
260 rc = VERR_ALREADY_EXISTS;
261 }
262 else
263 rc = RTDirCreateFullPath(szAreaDir, RTFS_UNIX_IRWXU); /** @todo Tweak path mode? */
264
265 if (RT_SUCCESS(rc))
266 {
267 RTDIR hDir;
268 rc = RTDirOpen(&hDir, szAreaDir);
269 if (RT_SUCCESS(rc))
270 {
271 this->m_hDir = hDir;
272 this->m_strPathAbs = szAreaDir;
273 this->m_fOpen = fFlags;
274 this->m_uID = uID;
275 this->m_tsCreatedMs = RTTimeMilliTS();
276 }
277 }
278 }
279
280 LogFlowFuncLeaveRC(rc);
281 return rc;
282}
283
284int SharedClipboardArea::OpenTemp(SHCLAREAID uID,
285 SHCLAREAOPENFLAGS fFlags /* = SHCLAREA_OPEN_FLAGS_NONE */)
286{
287 AssertReturn(!(fFlags & ~SHCLAREA_OPEN_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
288
289 /*
290 * Get the user's temp directory. Don't use the user's root directory (or
291 * something inside it) because we don't know for how long/if the data will
292 * be kept after the guest OS used it.
293 */
294 char szTemp[RTPATH_MAX];
295 int rc = RTPathTemp(szTemp, sizeof(szTemp));
296 if (RT_SUCCESS(rc))
297 rc = OpenEx(szTemp, uID, fFlags);
298
299 return rc;
300}
301
302int SharedClipboardArea::Reset(bool fDeleteContent)
303{
304 int rc = closeInternal();
305 if (RT_SUCCESS(rc))
306 {
307 if (fDeleteContent)
308 {
309 rc = Rollback();
310 }
311 else
312 {
313
314 }
315 }
316
317 LogFlowFuncLeaveRC(rc);
318 return rc;
319}
320
321int SharedClipboardArea::Reopen(void)
322{
323 if (this->m_strPathAbs.isEmpty())
324 return VERR_NOT_FOUND;
325
326 return OpenEx(this->m_strPathAbs.c_str(), this->m_fOpen);
327}
328
329int SharedClipboardArea::Rollback(void)
330{
331 if (this->m_strPathAbs.isEmpty())
332 return VINF_SUCCESS;
333
334 int rc = VINF_SUCCESS;
335
336#if 0
337 /* Rollback by removing any stuff created.
338 * Note: Only remove empty directories, never ever delete
339 * anything recursive here! Steam (tm) knows best ... :-) */
340 int rc2;
341 for (size_t i = 0; i < this->m_lstFiles.size(); i++)
342 {
343 rc2 = RTFileDelete(this->m_lstFiles.at(i).c_str());
344 if (RT_SUCCESS(rc2))
345 this->m_lstFiles.removeAt(i);
346 else if (RT_SUCCESS(rc))
347 rc = rc2;
348 /* Keep going. */
349 }
350
351 for (size_t i = 0; i < this->m_lstDirs.size(); i++)
352 {
353 rc2 = RTDirRemove(this->m_lstDirs.at(i).c_str());
354 if (RT_SUCCESS(rc2))
355 this->m_lstDirs.removeAt(i);
356 else if (RT_SUCCESS(rc))
357 rc = rc2;
358 /* Keep going. */
359 }
360
361 if (RT_SUCCESS(rc))
362 {
363 Assert(this->m_lstFiles.isEmpty());
364 Assert(this->m_lstDirs.isEmpty());
365
366 rc2 = closeInternal();
367 if ( RT_SUCCESS(rc2)
368 && m_strPathAbs.isNotEmpty())
369 {
370 /* Try to remove the empty root dropped files directory as well.
371 * Might return VERR_DIR_NOT_EMPTY or similar. */
372 rc2 = RTDirRemove(this->m_strPathAbs.c_str());
373 }
374 if (RT_SUCCESS(rc))
375 rc = rc2;
376 }
377#endif
378
379 LogFlowFuncLeaveRC(rc);
380 return rc;
381}
382
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