VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-provider-local.cpp@ 100307

Last change on this file since 100307 was 100265, checked in by vboxsync, 18 months ago

Shared Clipboard: Added handling an explicit absolute root path for shClTransferListEntryQueryFsInfo(). bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.6 KB
Line 
1/* $Id: clipboard-transfers-provider-local.cpp 100265 2023-06-23 13:50:43Z vboxsync $ */
2/** @file
3 * Shared Clipboard - Transfers interface implementation for local file systems.
4 */
5
6/*
7 * Copyright (C) 2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
33#include <VBox/GuestHost/SharedClipboard-transfers.h>
34
35#include <iprt/dir.h>
36#include <iprt/err.h>
37#include <iprt/file.h>
38#include <iprt/path.h>
39#include <iprt/string.h>
40
41
42/**
43 * Converts Shared Clipboard create flags (see SharedClipboard-transfers.h) into IPRT create flags.
44 *
45 * @returns IPRT status code.
46 * @param fShClFlags Shared clipboard create flags.
47 * @param[out] pfOpen Where to store the RTFILE_O_XXX flags for
48 * RTFileOpen.
49 *
50 * @sa Initially taken from vbsfConvertFileOpenFlags().
51 */
52static int shClConvertFileCreateFlags(uint32_t fShClFlags, uint64_t *pfOpen)
53{
54 AssertMsgReturnStmt(!(fShClFlags & ~SHCL_OBJ_CF_VALID_MASK), ("%#x4\n", fShClFlags), *pfOpen = 0, VERR_INVALID_FLAGS);
55
56 uint64_t fOpen = 0;
57
58 switch (fShClFlags & SHCL_OBJ_CF_ACCESS_MASK_RW)
59 {
60 case SHCL_OBJ_CF_ACCESS_NONE:
61 {
62#ifdef RT_OS_WINDOWS
63 if ((fShClFlags & SHCL_OBJ_CF_ACCESS_MASK_ATTR) != SHCL_OBJ_CF_ACCESS_ATTR_NONE)
64 fOpen |= RTFILE_O_OPEN | RTFILE_O_ATTR_ONLY;
65 else
66#endif
67 fOpen |= RTFILE_O_OPEN | RTFILE_O_READ;
68 LogFlowFunc(("SHCL_OBJ_CF_ACCESS_NONE\n"));
69 break;
70 }
71
72 case SHCL_OBJ_CF_ACCESS_READ:
73 {
74 fOpen |= RTFILE_O_OPEN | RTFILE_O_READ;
75 LogFlowFunc(("SHCL_OBJ_CF_ACCESS_READ\n"));
76 break;
77 }
78
79 default:
80 AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
81 }
82
83 switch (fShClFlags & SHCL_OBJ_CF_ACCESS_MASK_ATTR)
84 {
85 case SHCL_OBJ_CF_ACCESS_ATTR_NONE:
86 {
87 fOpen |= RTFILE_O_ACCESS_ATTR_DEFAULT;
88 LogFlowFunc(("SHCL_OBJ_CF_ACCESS_ATTR_NONE\n"));
89 break;
90 }
91
92 case SHCL_OBJ_CF_ACCESS_ATTR_READ:
93 {
94 fOpen |= RTFILE_O_ACCESS_ATTR_READ;
95 LogFlowFunc(("SHCL_OBJ_CF_ACCESS_ATTR_READ\n"));
96 break;
97 }
98
99 default:
100 AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
101 }
102
103 /* Sharing mask */
104 switch (fShClFlags & SHCL_OBJ_CF_ACCESS_MASK_DENY)
105 {
106 case SHCL_OBJ_CF_ACCESS_DENYNONE:
107 fOpen |= RTFILE_O_DENY_NONE;
108 LogFlowFunc(("SHCL_OBJ_CF_ACCESS_DENYNONE\n"));
109 break;
110
111 case SHCL_OBJ_CF_ACCESS_DENYWRITE:
112 fOpen |= RTFILE_O_DENY_WRITE;
113 LogFlowFunc(("SHCL_OBJ_CF_ACCESS_DENYWRITE\n"));
114 break;
115
116 default:
117 AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
118 }
119
120 *pfOpen = fOpen;
121
122 LogFlowFuncLeaveRC(VINF_SUCCESS);
123 return VINF_SUCCESS;
124}
125
126/**
127 * Resolves a relative path of a specific transfer to its absolute path.
128 *
129 * @returns VBox status code.
130 * @param pTransfer Clipboard transfer to resolve path for.
131 * @param pszPath Relative path to resolve.
132 * @param fFlags Resolve flags. Currently not used and must be 0.
133 * @param ppszResolved Where to store the allocated resolved path. Must be free'd by the called using RTStrFree().
134 */
135static int shClTransferResolvePathAbs(PSHCLTRANSFER pTransfer, const char *pszPath, uint32_t fFlags,
136 char **ppszResolved)
137{
138 AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
139 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
140 AssertReturn (fFlags == 0, VERR_INVALID_PARAMETER);
141
142 LogFlowFunc(("pszPathRootAbs=%s, pszPath=%s\n", pTransfer->pszPathRootAbs, pszPath));
143
144 int rc = ShClTransferValidatePath(pszPath, false /* fMustExist */);
145 if (RT_SUCCESS(rc))
146 {
147 rc = VERR_PATH_NOT_FOUND; /* Play safe by default. */
148
149 /* Make sure the given path is part of the set of root entries. */
150 PSHCLLISTENTRY pEntry;
151 RTListForEach(&pTransfer->lstRoots.lstEntries, pEntry, SHCLLISTENTRY, Node)
152 {
153 LogFlowFunc(("\tpEntry->pszName=%s\n", pEntry->pszName));
154
155 if (!RTStrCmp(pszPath, pEntry->pszName)) /* Case-sensitive! */
156 {
157 rc = VINF_SUCCESS;
158 break;
159 }
160 }
161
162 if (RT_SUCCESS(rc))
163 {
164 char *pszPathAbs = RTPathJoinA(pTransfer->pszPathRootAbs, pszPath);
165 if (pszPathAbs)
166 {
167 char szResolved[RTPATH_MAX];
168 size_t cbResolved = sizeof(szResolved);
169 rc = RTPathAbsEx(pTransfer->pszPathRootAbs, pszPathAbs, RTPATH_STR_F_STYLE_HOST, szResolved, &cbResolved);
170
171 RTStrFree(pszPathAbs);
172 pszPathAbs = NULL;
173
174 if (RT_SUCCESS(rc))
175 {
176 LogFlowFunc(("pszResolved=%s\n", szResolved));
177
178 if (RT_SUCCESS(rc))
179 *ppszResolved = RTStrDup(szResolved);
180 }
181 }
182 else
183 rc = VERR_NO_MEMORY;
184 }
185 }
186
187 if (RT_FAILURE(rc))
188 LogRel(("Shared Clipboard: Resolving absolute path for '%s' failed, rc=%Rrc\n", pszPath, rc));
189
190 LogFlowFuncLeaveRC(rc);
191 return rc;
192}
193
194/**
195 * Adds a file to a transfer list header.
196 *
197 * @returns VBox status code.
198 * @param pHdr List header to add file to.
199 * @param pszPath Path of file to add.
200 */
201static int shclTransferListHdrAddFile(PSHCLLISTHDR pHdr, const char *pszPath)
202{
203 AssertPtrReturn(pHdr, VERR_INVALID_POINTER);
204 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
205
206 uint64_t cbSize = 0;
207 int rc = RTFileQuerySizeByPath(pszPath, &cbSize);
208 if (RT_SUCCESS(rc))
209 {
210 pHdr->cbTotalSize += cbSize;
211 pHdr->cEntries++;
212 }
213
214 LogFlowFuncLeaveRC(rc);
215 return rc;
216}
217
218/**
219 * Builds a transfer list header, internal version.
220 *
221 * @returns VBox status code.
222 * @param pHdr Where to store the build list header.
223 * @param pcszPathAbs Absolute path to use for building the transfer list.
224 */
225static int shclTransferListHdrFromDir(PSHCLLISTHDR pHdr, const char *pcszPathAbs)
226{
227 AssertPtrReturn(pcszPathAbs, VERR_INVALID_POINTER);
228
229 LogFlowFunc(("pcszPathAbs=%s\n", pcszPathAbs));
230
231 RTFSOBJINFO objInfo;
232 int rc = RTPathQueryInfo(pcszPathAbs, &objInfo, RTFSOBJATTRADD_NOTHING);
233 if (RT_SUCCESS(rc))
234 {
235 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
236 {
237 RTDIR hDir;
238 rc = RTDirOpen(&hDir, pcszPathAbs);
239 if (RT_SUCCESS(rc))
240 {
241 size_t cbDirEntry = 0;
242 PRTDIRENTRYEX pDirEntry = NULL;
243 do
244 {
245 /* Retrieve the next directory entry. */
246 rc = RTDirReadExA(hDir, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
247 if (RT_FAILURE(rc))
248 {
249 if (rc == VERR_NO_MORE_FILES)
250 rc = VINF_SUCCESS;
251 break;
252 }
253
254 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
255 {
256 case RTFS_TYPE_DIRECTORY:
257 {
258 /* Skip "." and ".." entries. */
259 if (RTDirEntryExIsStdDotLink(pDirEntry))
260 break;
261
262 pHdr->cEntries++;
263 break;
264 }
265 case RTFS_TYPE_FILE:
266 {
267 char *pszSrc = RTPathJoinA(pcszPathAbs, pDirEntry->szName);
268 if (pszSrc)
269 {
270 rc = shclTransferListHdrAddFile(pHdr, pszSrc);
271 RTStrFree(pszSrc);
272 }
273 else
274 rc = VERR_NO_MEMORY;
275 break;
276 }
277 case RTFS_TYPE_SYMLINK:
278 {
279 /** @todo Not implemented yet. */
280 }
281
282 default:
283 break;
284 }
285
286 } while (RT_SUCCESS(rc));
287
288 RTDirReadExAFree(&pDirEntry, &cbDirEntry);
289 RTDirClose(hDir);
290 }
291 }
292 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
293 {
294 rc = shclTransferListHdrAddFile(pHdr, pcszPathAbs);
295 }
296 else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
297 {
298 /** @todo Not implemented yet. */
299 }
300 else
301 rc = VERR_NOT_SUPPORTED;
302 }
303
304 LogFlowFuncLeaveRC(rc);
305 return rc;
306}
307
308/**
309 * Creates a new list handle (local only).
310 *
311 * @returns New List handle on success, or NIL_SHCLLISTHANDLE on error.
312 * @param pTransfer Clipboard transfer to create new list handle for.
313 */
314DECLINLINE(SHCLLISTHANDLE) shClTransferListHandleNew(PSHCLTRANSFER pTransfer)
315{
316 return pTransfer->uListHandleNext++; /** @todo Good enough for now. Improve this later. */
317}
318
319/**
320 * Queries information about a local list entry.
321 *
322 * @returns VBox status code.
323 * @param pszPathRootAbs Absolute root path to use for the entry.
324 * @param pListEntry List entry to query information for.
325 * @param pFsObjInfo Where to store the queried information on success.
326 */
327static int shClTransferListEntryQueryFsInfo(const char *pszPathRootAbs, PSHCLLISTENTRY pListEntry, PSHCLFSOBJINFO pFsObjInfo)
328{
329 AssertPtrReturn(pszPathRootAbs, VERR_INVALID_POINTER);
330 AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
331
332 const char *pszSrcPathAbs = RTPathJoinA(pszPathRootAbs, pListEntry->pszName);
333 AssertPtrReturn(pszSrcPathAbs, VERR_NO_MEMORY);
334
335 RTFSOBJINFO fsObjInfo;
336 int rc = RTPathQueryInfo(pszSrcPathAbs, &fsObjInfo, RTFSOBJATTRADD_NOTHING);
337 if (RT_SUCCESS(rc))
338 rc = ShClFsObjInfoFromIPRT(pFsObjInfo, &fsObjInfo);
339
340 return rc;
341}
342
343/** @copydoc SHCLTXPROVIDERIFACE::pfnRootListRead */
344static DECLCALLBACK(int) shclTransferIfaceLocalRootListRead(PSHCLTXPROVIDERCTX pCtx)
345{
346 LogFlowFuncEnter();
347
348 int rc = VINF_SUCCESS;
349
350 PSHCLLISTENTRY pEntry;
351 RTListForEach(&pCtx->pTransfer->lstRoots.lstEntries, pEntry, SHCLLISTENTRY, Node)
352 {
353 AssertBreakStmt(pEntry->cbInfo == sizeof(SHCLFSOBJINFO), rc = VERR_WRONG_ORDER);
354 rc = shClTransferListEntryQueryFsInfo(pCtx->pTransfer->pszPathRootAbs, pEntry, (PSHCLFSOBJINFO)pEntry->pvInfo);
355 if (RT_FAILURE(rc)) /* Currently this is an all-or-nothing op. */
356 break;
357 }
358
359 LogFlowFuncLeaveRC(rc);
360 return rc;
361}
362
363/** @copydoc SHCLTXPROVIDERIFACE::pfnListOpen */
364static DECLCALLBACK(int) shclTransferIfaceLocalListOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
365 PSHCLLISTHANDLE phList)
366{
367 LogFlowFunc(("pszPath=%s\n", pOpenParms->pszPath));
368
369 int rc;
370
371 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
372 AssertPtr(pTransfer);
373
374 PSHCLLISTHANDLEINFO pInfo
375 = (PSHCLLISTHANDLEINFO)RTMemAllocZ(sizeof(SHCLLISTHANDLEINFO));
376 if (pInfo)
377 {
378 rc = ShClTransferListHandleInfoInit(pInfo);
379 if (RT_SUCCESS(rc))
380 {
381 rc = shClTransferResolvePathAbs(pTransfer, pOpenParms->pszPath, 0 /* fFlags */, &pInfo->pszPathLocalAbs);
382 if (RT_SUCCESS(rc))
383 {
384 RTFSOBJINFO objInfo;
385 rc = RTPathQueryInfo(pInfo->pszPathLocalAbs, &objInfo, RTFSOBJATTRADD_NOTHING);
386 if (RT_SUCCESS(rc))
387 {
388 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
389 {
390 rc = RTDirOpen(&pInfo->u.Local.hDir, pInfo->pszPathLocalAbs);
391 if (RT_SUCCESS(rc))
392 {
393 pInfo->enmType = SHCLOBJTYPE_DIRECTORY;
394
395 LogRel2(("Shared Clipboard: Opening directory '%s'\n", pInfo->pszPathLocalAbs));
396 }
397 else
398 LogRel(("Shared Clipboard: Opening directory '%s' failed with %Rrc\n", pInfo->pszPathLocalAbs, rc));
399
400 }
401 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
402 {
403 rc = RTFileOpen(&pInfo->u.Local.hFile, pInfo->pszPathLocalAbs,
404 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
405 if (RT_SUCCESS(rc))
406 {
407 pInfo->enmType = SHCLOBJTYPE_FILE;
408
409 LogRel2(("Shared Clipboard: Opening file '%s'\n", pInfo->pszPathLocalAbs));
410 }
411 else
412 LogRel(("Shared Clipboard: Opening file '%s' failed with %Rrc\n", pInfo->pszPathLocalAbs, rc));
413 }
414 else
415 rc = VERR_NOT_SUPPORTED;
416
417 if (RT_SUCCESS(rc))
418 {
419 pInfo->hList = shClTransferListHandleNew(pTransfer);
420
421 RTListAppend(&pTransfer->lstHandles, &pInfo->Node);
422 pTransfer->cListHandles++;
423
424 if (phList)
425 *phList = pInfo->hList;
426
427 LogFlowFunc(("pszPathLocalAbs=%s, hList=%RU64, cListHandles=%RU32\n",
428 pInfo->pszPathLocalAbs, pInfo->hList, pTransfer->cListHandles));
429 }
430 else
431 {
432 if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
433 {
434 if (RTDirIsValid(pInfo->u.Local.hDir))
435 RTDirClose(pInfo->u.Local.hDir);
436 }
437 else if (RTFS_IS_FILE(objInfo.Attr.fMode))
438 {
439 if (RTFileIsValid(pInfo->u.Local.hFile))
440 RTFileClose(pInfo->u.Local.hFile);
441 }
442 }
443 }
444 }
445 }
446
447 if (RT_FAILURE(rc))
448 {
449 ShClTransferListHandleInfoDestroy(pInfo);
450
451 RTMemFree(pInfo);
452 pInfo = NULL;
453 }
454 }
455 else
456 rc = VERR_NO_MEMORY;
457
458 LogFlowFuncLeaveRC(rc);
459 return rc;
460}
461
462/** @copydoc SHCLTXPROVIDERIFACE::pfnListClose */
463static DECLCALLBACK(int) shclTransferIfaceLocalListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList)
464{
465 LogFlowFuncEnter();
466
467 int rc = VINF_SUCCESS;
468
469 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
470 AssertPtr(pTransfer);
471
472 PSHCLLISTHANDLEINFO pInfo = ShClTransferListGetByHandle(pTransfer, hList);
473 if (pInfo)
474 {
475 switch (pInfo->enmType)
476 {
477 case SHCLOBJTYPE_DIRECTORY:
478 {
479 if (RTDirIsValid(pInfo->u.Local.hDir))
480 {
481 RTDirClose(pInfo->u.Local.hDir);
482 pInfo->u.Local.hDir = NIL_RTDIR;
483 }
484 break;
485 }
486
487 default:
488 rc = VERR_NOT_SUPPORTED;
489 break;
490 }
491
492 RTListNodeRemove(&pInfo->Node);
493
494 Assert(pTransfer->cListHandles);
495 pTransfer->cListHandles--;
496
497 RTMemFree(pInfo);
498 }
499 else
500 rc = VERR_NOT_FOUND;
501
502 LogFlowFuncLeaveRC(rc);
503 return rc;
504}
505
506/** @copydoc SHCLTXPROVIDERIFACE::pfnListHdrRead */
507static DECLCALLBACK(int) shclTransferIfaceLocalListHdrRead(PSHCLTXPROVIDERCTX pCtx,
508 SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
509{
510 LogFlowFuncEnter();
511
512 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
513 AssertPtr(pTransfer);
514
515 int rc;
516
517 PSHCLLISTHANDLEINFO pInfo = ShClTransferListGetByHandle(pTransfer, hList);
518 if (pInfo)
519 {
520 rc = ShClTransferListHdrInit(pListHdr);
521 if (RT_SUCCESS(rc))
522 {
523 switch (pInfo->enmType)
524 {
525 case SHCLOBJTYPE_DIRECTORY:
526 {
527 LogFlowFunc(("DirAbs: %s\n", pInfo->pszPathLocalAbs));
528
529 rc = shclTransferListHdrFromDir(pListHdr, pInfo->pszPathLocalAbs);
530 break;
531 }
532
533 case SHCLOBJTYPE_FILE:
534 {
535 LogFlowFunc(("FileAbs: %s\n", pInfo->pszPathLocalAbs));
536
537 pListHdr->cEntries = 1;
538
539 RTFSOBJINFO objInfo;
540 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
541 if (RT_SUCCESS(rc))
542 {
543 pListHdr->cbTotalSize = objInfo.cbObject;
544 }
545 break;
546 }
547
548 /* We don't support symlinks (yet). */
549
550 default:
551 rc = VERR_NOT_SUPPORTED;
552 break;
553 }
554 }
555
556 LogFlowFunc(("cTotalObj=%RU64, cbTotalSize=%RU64\n", pListHdr->cEntries, pListHdr->cbTotalSize));
557 }
558 else
559 rc = VERR_NOT_FOUND;
560
561 LogFlowFuncLeaveRC(rc);
562 return rc;
563}
564
565/** @copydoc SHCLTXPROVIDERIFACE::pfnListEntryRead */
566static DECLCALLBACK(int) shclTransferIfaceLocalListEntryRead(PSHCLTXPROVIDERCTX pCtx,
567 SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry)
568{
569 LogFlowFuncEnter();
570
571 int rc;
572
573 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
574 AssertPtr(pTransfer);
575
576 PSHCLLISTHANDLEINFO pInfo = ShClTransferListGetByHandle(pTransfer, hList);
577 if (pInfo)
578 {
579 switch (pInfo->enmType)
580 {
581 case SHCLOBJTYPE_DIRECTORY:
582 {
583 LogFlowFunc(("\tDirectory: %s\n", pInfo->pszPathLocalAbs));
584
585 for (;;)
586 {
587 bool fSkipEntry = false; /* Whether to skip an entry in the enumeration. */
588
589 size_t cbDirEntry = 0;
590 PRTDIRENTRYEX pDirEntry = NULL;
591 rc = RTDirReadExA(pInfo->u.Local.hDir, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
592 if (RT_SUCCESS(rc))
593 {
594 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
595 {
596 case RTFS_TYPE_DIRECTORY:
597 {
598 /* Skip "." and ".." entries. */
599 if (RTDirEntryExIsStdDotLink(pDirEntry))
600 {
601 fSkipEntry = true;
602 break;
603 }
604
605 LogFlowFunc(("Directory: %s\n", pDirEntry->szName));
606 break;
607 }
608
609 case RTFS_TYPE_FILE:
610 {
611 LogFlowFunc(("File: %s\n", pDirEntry->szName));
612 break;
613 }
614
615 case RTFS_TYPE_SYMLINK:
616 {
617 rc = VERR_NOT_IMPLEMENTED; /** @todo Not implemented yet. */
618 break;
619 }
620
621 default:
622 break;
623 }
624
625 if ( RT_SUCCESS(rc)
626 && !fSkipEntry)
627 {
628 rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pDirEntry->szName);
629 if (RT_SUCCESS(rc))
630 {
631 pEntry->cbName = (uint32_t)strlen(pEntry->pszName) + 1; /* Include termination. */
632
633 AssertPtr(pEntry->pvInfo);
634 Assert (pEntry->cbInfo == sizeof(SHCLFSOBJINFO));
635
636 ShClFsObjInfoFromIPRT(PSHCLFSOBJINFO(pEntry->pvInfo), &pDirEntry->Info);
637
638 LogFlowFunc(("Entry pszName=%s, pvInfo=%p, cbInfo=%RU32\n",
639 pEntry->pszName, pEntry->pvInfo, pEntry->cbInfo));
640 }
641 }
642
643 RTDirReadExAFree(&pDirEntry, &cbDirEntry);
644 }
645
646 if ( !fSkipEntry /* Do we have a valid entry? Bail out. */
647 || RT_FAILURE(rc))
648 {
649 break;
650 }
651 }
652
653 break;
654 }
655
656 case SHCLOBJTYPE_FILE:
657 {
658 LogFlowFunc(("\tSingle file: %s\n", pInfo->pszPathLocalAbs));
659
660 RTFSOBJINFO objInfo;
661 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
662 if (RT_SUCCESS(rc))
663 {
664 pEntry->pvInfo = (PSHCLFSOBJINFO)RTMemAlloc(sizeof(SHCLFSOBJINFO));
665 if (pEntry->pvInfo)
666 {
667 rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pInfo->pszPathLocalAbs);
668 if (RT_SUCCESS(rc))
669 {
670 ShClFsObjInfoFromIPRT(PSHCLFSOBJINFO(pEntry->pvInfo), &objInfo);
671
672 pEntry->cbInfo = sizeof(SHCLFSOBJINFO);
673 pEntry->fInfo = VBOX_SHCL_INFO_F_FSOBJINFO;
674 }
675 }
676 else
677 rc = VERR_NO_MEMORY;
678 }
679
680 break;
681 }
682
683 default:
684 rc = VERR_NOT_SUPPORTED;
685 break;
686 }
687 }
688 else
689 rc = VERR_NOT_FOUND;
690
691 LogFlowFuncLeaveRC(rc);
692 return rc;
693}
694
695/** @copydoc SHCLTXPROVIDERIFACE::pfnObjOpen */
696static DECLCALLBACK(int) shclTransferIfaceLocalObjOpen(PSHCLTXPROVIDERCTX pCtx,
697 PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj)
698{
699 LogFlowFuncEnter();
700
701 int rc;
702
703 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
704 AssertPtr(pTransfer);
705
706 PSHCLOBJHANDLEINFO pInfo = (PSHCLOBJHANDLEINFO)RTMemAllocZ(sizeof(SHCLOBJHANDLEINFO));
707 if (pInfo)
708 {
709 rc = ShClTransferObjHandleInfoInit(pInfo);
710 if (RT_SUCCESS(rc))
711 {
712 uint64_t fOpen;
713 rc = shClConvertFileCreateFlags(pCreateParms->fCreate, &fOpen);
714 if (RT_SUCCESS(rc))
715 {
716 rc = shClTransferResolvePathAbs(pTransfer, pCreateParms->pszPath, 0 /* fFlags */,
717 &pInfo->pszPathLocalAbs);
718 if (RT_SUCCESS(rc))
719 {
720 rc = RTFileOpen(&pInfo->u.Local.hFile, pInfo->pszPathLocalAbs, fOpen);
721 if (RT_SUCCESS(rc))
722 LogRel2(("Shared Clipboard: Opened file '%s'\n", pInfo->pszPathLocalAbs));
723 else
724 LogRel(("Shared Clipboard: Error opening file '%s': rc=%Rrc\n", pInfo->pszPathLocalAbs, rc));
725 }
726 }
727 }
728
729 if (RT_SUCCESS(rc))
730 {
731 pInfo->hObj = pTransfer->uObjHandleNext++;
732 pInfo->enmType = SHCLOBJTYPE_FILE;
733
734 RTListAppend(&pTransfer->lstObj, &pInfo->Node);
735 pTransfer->cObjHandles++;
736
737 LogFlowFunc(("cObjHandles=%RU32\n", pTransfer->cObjHandles));
738
739 *phObj = pInfo->hObj;
740 }
741 else
742 {
743 ShClTransferObjHandleInfoDestroy(pInfo);
744 RTMemFree(pInfo);
745 }
746 }
747 else
748 rc = VERR_NO_MEMORY;
749
750 LogFlowFuncLeaveRC(rc);
751 return rc;
752}
753
754/** @copydoc SHCLTXPROVIDERIFACE::pfnObjClose */
755static DECLCALLBACK(int) shclTransferIfaceLocalObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)
756{
757 LogFlowFuncEnter();
758
759 int rc;
760
761 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
762 AssertPtr(pTransfer);
763
764 PSHCLOBJHANDLEINFO pInfo = ShClTransferObjGet(pTransfer, hObj);
765 if (pInfo)
766 {
767 switch (pInfo->enmType)
768 {
769 case SHCLOBJTYPE_DIRECTORY:
770 {
771 rc = RTDirClose(pInfo->u.Local.hDir);
772 if (RT_SUCCESS(rc))
773 {
774 pInfo->u.Local.hDir = NIL_RTDIR;
775
776 LogRel2(("Shared Clipboard: Closed directory '%s'\n", pInfo->pszPathLocalAbs));
777 }
778 else
779 LogRel(("Shared Clipboard: Closing directory '%s' failed with %Rrc\n", pInfo->pszPathLocalAbs, rc));
780 break;
781 }
782
783 case SHCLOBJTYPE_FILE:
784 {
785 rc = RTFileClose(pInfo->u.Local.hFile);
786 if (RT_SUCCESS(rc))
787 {
788 pInfo->u.Local.hFile = NIL_RTFILE;
789
790 LogRel2(("Shared Clipboard: Closed file '%s'\n", pInfo->pszPathLocalAbs));
791 }
792 else
793 LogRel(("Shared Clipboard: Closing file '%s' failed with %Rrc\n", pInfo->pszPathLocalAbs, rc));
794 break;
795 }
796
797 default:
798 rc = VERR_NOT_IMPLEMENTED;
799 break;
800 }
801
802 RTListNodeRemove(&pInfo->Node);
803
804 Assert(pTransfer->cObjHandles);
805 pTransfer->cObjHandles--;
806
807 ShClTransferObjHandleInfoDestroy(pInfo);
808
809 RTMemFree(pInfo);
810 pInfo = NULL;
811 }
812 else
813 rc = VERR_NOT_FOUND;
814
815 LogFlowFuncLeaveRC(rc);
816 return rc;
817}
818
819/** @copydoc SHCLTXPROVIDERIFACE::pfnObjRead */
820static DECLCALLBACK(int) shclTransferIfaceLocalObjRead(PSHCLTXPROVIDERCTX pCtx,
821 SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData,
822 uint32_t fFlags, uint32_t *pcbRead)
823{
824 RT_NOREF(fFlags);
825
826 LogFlowFuncEnter();
827
828 int rc;
829
830 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
831 AssertPtr(pTransfer);
832
833 PSHCLOBJHANDLEINFO pInfo = ShClTransferObjGet(pTransfer, hObj);
834 if (pInfo)
835 {
836 switch (pInfo->enmType)
837 {
838 case SHCLOBJTYPE_FILE:
839 {
840 size_t cbRead;
841 rc = RTFileRead(pInfo->u.Local.hFile, pvData, cbData, &cbRead);
842 if (RT_SUCCESS(rc))
843 {
844 if (pcbRead)
845 *pcbRead = (uint32_t)cbRead;
846 }
847 break;
848 }
849
850 default:
851 rc = VERR_NOT_SUPPORTED;
852 break;
853 }
854 }
855 else
856 rc = VERR_NOT_FOUND;
857
858 LogFlowFuncLeaveRC(rc);
859 return rc;
860}
861
862static DECLCALLBACK(int) shclTransferIfaceLocalObjWrite(PSHCLTXPROVIDERCTX pCtx,
863 SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData, uint32_t fFlags,
864 uint32_t *pcbWritten)
865{
866 RT_NOREF(fFlags);
867
868 LogFlowFuncEnter();
869
870 int rc;
871
872 PSHCLTRANSFER const pTransfer = pCtx->pTransfer;
873 AssertPtr(pTransfer);
874
875 PSHCLOBJHANDLEINFO pInfo = ShClTransferObjGet(pTransfer, hObj);
876 if (pInfo)
877 {
878 switch (pInfo->enmType)
879 {
880 case SHCLOBJTYPE_FILE:
881 {
882 rc = RTFileWrite(pInfo->u.Local.hFile, pvData, cbData, (size_t *)pcbWritten);
883 break;
884 }
885
886 default:
887 rc = VERR_NOT_SUPPORTED;
888 break;
889 }
890 }
891 else
892 rc = VERR_NOT_FOUND;
893
894 LogFlowFuncLeaveRC(rc);
895 return rc;
896}
897
898/**
899 * Queries (assigns) the local provider to an interface.
900 *
901 * The local provider is being used for accessing files on local file systems.
902 *
903 * @returns Interface pointer assigned to the provider.
904 * @param pProvider Provider to assign interface to.
905 */
906PSHCLTXPROVIDERIFACE VBClTransferProviderLocalQueryInterface(PSHCLTXPROVIDER pProvider)
907{
908 pProvider->Interface.pfnRootListRead = shclTransferIfaceLocalRootListRead;
909 pProvider->Interface.pfnListOpen = shclTransferIfaceLocalListOpen;
910 pProvider->Interface.pfnListClose = shclTransferIfaceLocalListClose;
911 pProvider->Interface.pfnListHdrRead = shclTransferIfaceLocalListHdrRead;
912 pProvider->Interface.pfnListEntryRead = shclTransferIfaceLocalListEntryRead;
913 pProvider->Interface.pfnObjOpen = shclTransferIfaceLocalObjOpen;
914 pProvider->Interface.pfnObjClose = shclTransferIfaceLocalObjClose;
915 pProvider->Interface.pfnObjRead = shclTransferIfaceLocalObjRead;
916 pProvider->Interface.pfnObjWrite = shclTransferIfaceLocalObjWrite;
917
918 return &pProvider->Interface;
919}
920
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