VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedFolders/testcase/tstSharedFolderService.cpp@ 105087

最後變更 在這個檔案從105087是 105087,由 vboxsync 提交於 9 月 前

doc/manual,include/VBox,Frontends/VBoxManage,HostServices/SharedFolders,
Main/{include,SharedFolder,Console,Machine,VirtualBox.xidl}: Add a
new attribute to ISharedFolder for specifying a symbolic link creation
policy to restrict the source pathname when creating symbolic links
within a guest. The symbolic link policies are represented by a new
enumeration of type SymlinkPolicy_T which includes values for no
restrictions ('any'), symlink sources only within the subtree of the
share ('subtree'), symlink sources as any relative path ('relative'),
and no symlinks allowed ('forbidden'). The symlink policy can only be
applied to permanent shared folders at this stage. bugref:10619

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 61.7 KB
 
1/* $Id: tstSharedFolderService.cpp 105087 2024-07-01 23:27:59Z vboxsync $ */
2/** @file
3 * Testcase for the shared folder service vbsf API.
4 *
5 * Note that this is still very threadbare (there is an awful lot which should
6 * really be tested, but it already took too long to produce this much). The
7 * idea is that anyone who makes changes to the shared folders service and who
8 * cares about unit testing them should add tests to the skeleton framework to
9 * exercise the bits they change before and after changing them.
10 */
11
12/*
13 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
14 *
15 * This file is part of VirtualBox base platform packages, as
16 * available from https://www.alldomusa.eu.org.
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation, in version 3 of the
21 * License.
22 *
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, see <https://www.gnu.org/licenses>.
30 *
31 * SPDX-License-Identifier: GPL-3.0-only
32 */
33
34
35/*********************************************************************************************************************************
36* Header Files *
37*********************************************************************************************************************************/
38
39#include "tstSharedFolderService.h"
40#include "vbsf.h"
41
42#include <iprt/fs.h>
43#include <iprt/dir.h>
44#include <iprt/file.h>
45#include <iprt/path.h>
46#include <iprt/symlink.h>
47#include <iprt/stream.h>
48#include <iprt/test.h>
49#include <iprt/string.h>
50#include <iprt/utf16.h>
51
52#include "teststubs.h"
53
54
55/*********************************************************************************************************************************
56* Global Variables *
57*********************************************************************************************************************************/
58static RTTEST g_hTest = NIL_RTTEST;
59
60
61/*********************************************************************************************************************************
62* Declarations *
63*********************************************************************************************************************************/
64extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable);
65
66
67/*********************************************************************************************************************************
68* Helpers *
69*********************************************************************************************************************************/
70
71/** Simple call handle structure for the guest call completion callback */
72struct VBOXHGCMCALLHANDLE_TYPEDEF
73{
74 /** Where to store the result code */
75 int32_t rc;
76};
77
78/** Call completion callback for guest calls. */
79static DECLCALLBACK(int) callComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
80{
81 callHandle->rc = rc;
82 return VINF_SUCCESS;
83}
84
85static DECLCALLBACK(int) stamRegisterV(void *pvInstance, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
86 STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list va)
87{
88 RT_NOREF(pvInstance, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
89 return VINF_SUCCESS;
90}
91
92static DECLCALLBACK(int) stamDeregisterV(void *pvInstance, const char *pszPatFmt, va_list va)
93{
94 RT_NOREF(pvInstance, pszPatFmt, va);
95 return VINF_SUCCESS;
96}
97
98static DECLCALLBACK(int) infoRegister(void *pvInstance, const char *pszName, const char *pszDesc,
99 PFNDBGFHANDLEREXT pfnHandler, void *pvUser)
100{
101 RT_NOREF(pvInstance, pszName, pszDesc, pfnHandler, pvUser);
102 return VINF_SUCCESS;
103}
104
105static DECLCALLBACK(int) infoDeregister(void *pvInstance, const char *pszName)
106{
107 RT_NOREF(pvInstance, pszName);
108 return VINF_SUCCESS;
109}
110
111/**
112 * Initialise the HGCM service table as much as we need to start the
113 * service
114 * @param pTable the table to initialise
115 */
116static void initTable(VBOXHGCMSVCFNTABLE *pTable, VBOXHGCMSVCHELPERS *pHelpers)
117{
118 pTable->cbSize = sizeof (VBOXHGCMSVCFNTABLE);
119 pTable->u32Version = VBOX_HGCM_SVC_VERSION;
120 pHelpers->pfnCallComplete = callComplete;
121 pHelpers->pfnStamRegisterV = stamRegisterV;
122 pHelpers->pfnStamDeregisterV = stamDeregisterV;
123 pHelpers->pfnInfoRegister = infoRegister;
124 pHelpers->pfnInfoDeregister = infoDeregister;
125 pTable->pHelpers = pHelpers;
126}
127
128#define LLUIFY(a) ((unsigned long long)(a))
129
130static void bufferFromPath(char *pszDst, size_t cbDst, const char *pcszSrc)
131{
132 RTStrCopy(pszDst, cbDst, pcszSrc);
133 uintptr_t const uDstEnd = (uintptr_t)&pszDst[cbDst];
134 for (char *psz = pszDst; psz && (uintptr_t)psz < uDstEnd; ++psz)
135 if (*psz == '\\')
136 *psz = '/';
137}
138
139#define ARRAY_FROM_PATH(a, b) \
140 do { \
141 char *p = (a); NOREF(p); \
142 Assert((a) == p); /* Constant parameter */ \
143 Assert(sizeof((a)) > 0); \
144 bufferFromPath(a, sizeof(a), b); \
145 } while (0)
146
147
148/*********************************************************************************************************************************
149* Stub functions and data *
150*********************************************************************************************************************************/
151static bool g_fFailIfNotLowercase = false;
152
153static RTDIR g_testRTDirClose_hDir = NIL_RTDIR;
154
155extern int testRTDirClose(RTDIR hDir)
156{
157 /* RTPrintf("%s: hDir=%p\n", __PRETTY_FUNCTION__, hDir); */
158 g_testRTDirClose_hDir = hDir;
159 return VINF_SUCCESS;
160}
161
162static char g_testRTDirCreate_szPath[256];
163//static RTFMODE testRTDirCreateMode; - unused
164
165extern int testRTDirCreate(const char *pszPath, RTFMODE fMode, uint32_t fCreate)
166{
167 RT_NOREF2(fMode, fCreate);
168 /* RTPrintf("%s: pszPath=%s, fMode=0x%llx\n", __PRETTY_FUNCTION__, pszPath,
169 LLUIFY(fMode)); */
170 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
171 return VERR_FILE_NOT_FOUND;
172 ARRAY_FROM_PATH(g_testRTDirCreate_szPath, pszPath);
173 return 0;
174}
175
176static char g_testRTDirOpen_szName[256];
177static struct TESTDIRHANDLE
178{
179 int iEntry;
180 int iDir;
181} g_aTestDirHandles[4];
182static int g_iNextDirHandle = 0;
183static RTDIR g_testRTDirOpen_hDir;
184
185extern int testRTDirOpen(RTDIR *phDir, const char *pszPath)
186{
187 /* RTPrintf("%s: pszPath=%s\n", __PRETTY_FUNCTION__, pszPath); */
188 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
189 return VERR_FILE_NOT_FOUND;
190 ARRAY_FROM_PATH(g_testRTDirOpen_szName, pszPath);
191 *phDir = g_testRTDirOpen_hDir;
192 g_testRTDirOpen_hDir = NIL_RTDIR;
193 if (!*phDir && g_fFailIfNotLowercase)
194 *phDir = (RTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
195 if (*phDir)
196 {
197 struct TESTDIRHANDLE *pRealDir = (struct TESTDIRHANDLE *)*phDir;
198 pRealDir->iEntry = 0;
199 pRealDir->iDir = 0;
200 const char *pszSlash = pszPath - 1;
201 while ((pszSlash = strpbrk(pszSlash + 1, "\\/")) != NULL)
202 pRealDir->iDir += 1;
203 /*RTPrintf("opendir %s = %d \n", pszPath, pRealDir->iDir);*/
204 }
205 return VINF_SUCCESS;
206}
207
208/** @todo Do something useful with the last two arguments. */
209extern int testRTDirOpenFiltered(RTDIR *phDir, const char *pszPath, RTDIRFILTER, uint32_t)
210{
211 /* RTPrintf("%s: pszPath=%s\n", __PRETTY_FUNCTION__, pszPath); */
212 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
213 return VERR_FILE_NOT_FOUND;
214 ARRAY_FROM_PATH(g_testRTDirOpen_szName, pszPath);
215 *phDir = g_testRTDirOpen_hDir;
216 g_testRTDirOpen_hDir = NIL_RTDIR;
217 if (!*phDir && g_fFailIfNotLowercase)
218 *phDir = (RTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
219 if (*phDir)
220 {
221 struct TESTDIRHANDLE *pRealDir = (struct TESTDIRHANDLE *)*phDir;
222 pRealDir->iEntry = 0;
223 pRealDir->iDir = 0;
224 const char *pszSlash = pszPath - 1;
225 while ((pszSlash = strpbrk(pszSlash + 1, "\\/")) != NULL)
226 pRealDir->iDir += 1;
227 pRealDir->iDir -= 1;
228 /*RTPrintf("openfiltered %s = %d\n", pszPath, pRealDir->iDir);*/
229 }
230 return VINF_SUCCESS;
231}
232
233static RTDIR g_testRTDirQueryInfo_hDir;
234static RTTIMESPEC g_testRTDirQueryInfo_ATime;
235
236extern int testRTDirQueryInfo(RTDIR hDir, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
237{
238 RT_NOREF1(enmAdditionalAttribs);
239 /* RTPrintf("%s: hDir=%p, enmAdditionalAttribs=0x%llx\n", __PRETTY_FUNCTION__,
240 hDir, LLUIFY(enmAdditionalAttribs)); */
241 g_testRTDirQueryInfo_hDir = hDir;
242 RT_ZERO(*pObjInfo);
243 pObjInfo->AccessTime = g_testRTDirQueryInfo_ATime;
244 RT_ZERO(g_testRTDirQueryInfo_ATime);
245 return VINF_SUCCESS;
246}
247
248extern int testRTDirRemove(const char *pszPath)
249{
250 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
251 return VERR_FILE_NOT_FOUND;
252 RTPrintf("%s\n", __PRETTY_FUNCTION__);
253 return 0;
254}
255
256static RTDIR g_testRTDirReadEx_hDir;
257
258extern int testRTDirReadEx(RTDIR hDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry,
259 RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
260{
261 RT_NOREF4(pDirEntry, pcbDirEntry, enmAdditionalAttribs, fFlags);
262 /* RTPrintf("%s: hDir=%p, pcbDirEntry=%d, enmAdditionalAttribs=%llu, fFlags=0x%llx\n",
263 __PRETTY_FUNCTION__, hDir, pcbDirEntry ? (int) *pcbDirEntry : -1,
264 LLUIFY(enmAdditionalAttribs), LLUIFY(fFlags)); */
265 g_testRTDirReadEx_hDir = hDir;
266 if (g_fFailIfNotLowercase && hDir != NIL_RTDIR)
267 {
268 struct TESTDIRHANDLE *pRealDir = (struct TESTDIRHANDLE *)hDir;
269 if (pRealDir->iDir == 2) /* /test/mapping/ */
270 {
271 if (pRealDir->iEntry == 0)
272 {
273 pRealDir->iEntry++;
274 RT_ZERO(*pDirEntry);
275 pDirEntry->Info.Attr.fMode = RTFS_TYPE_DIRECTORY | RTFS_DOS_DIRECTORY | RTFS_UNIX_IROTH | RTFS_UNIX_IXOTH;
276 pDirEntry->cbName = 4;
277 pDirEntry->cwcShortName = 4;
278 strcpy(pDirEntry->szName, "test");
279 RTUtf16CopyAscii(pDirEntry->wszShortName, RT_ELEMENTS(pDirEntry->wszShortName), "test");
280 /*RTPrintf("readdir: 'test'\n");*/
281 return VINF_SUCCESS;
282 }
283 }
284 else if (pRealDir->iDir == 3) /* /test/mapping/test/ */
285 {
286 if (pRealDir->iEntry == 0)
287 {
288 pRealDir->iEntry++;
289 RT_ZERO(*pDirEntry);
290 pDirEntry->Info.Attr.fMode = RTFS_TYPE_FILE | RTFS_DOS_NT_NORMAL | RTFS_UNIX_IROTH | RTFS_UNIX_IXOTH;
291 pDirEntry->cbName = 4;
292 pDirEntry->cwcShortName = 4;
293 strcpy(pDirEntry->szName, "file");
294 RTUtf16CopyAscii(pDirEntry->wszShortName, RT_ELEMENTS(pDirEntry->wszShortName), "file");
295 /*RTPrintf("readdir: 'file'\n");*/
296 return VINF_SUCCESS;
297 }
298 }
299 /*else RTPrintf("%s: iDir=%d\n", pRealDir->iDir);*/
300 }
301 return VERR_NO_MORE_FILES;
302}
303
304static uint64_t g_testRTDirSetMode_fMode;
305
306extern int testRTDirSetMode(RTDIR hDir, RTFMODE fMode)
307{
308 RT_NOREF1(hDir);
309 /* RTPrintf("%s: fMode=%llu\n", __PRETTY_FUNCTION__, LLUIFY(fMode)); */
310 g_testRTDirSetMode_fMode = fMode;
311 return VINF_SUCCESS;
312}
313
314static RTTIMESPEC g_testRTDirSetTimes_ATime;
315
316extern int testRTDirSetTimes(RTDIR hDir, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
317 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
318{
319 RT_NOREF4(hDir, pModificationTime, pChangeTime, pBirthTime);
320 /* RTPrintf("%s: hDir=%p, *pAccessTime=%lli, *pModificationTime=%lli, *pChangeTime=%lli, *pBirthTime=%lli\n",
321 __PRETTY_FUNCTION__, hDir,
322 pAccessTime ? (long long)RTTimeSpecGetNano(pAccessTime) : -1,
323 pModificationTime
324 ? (long long)RTTimeSpecGetNano(pModificationTime) : -1,
325 pChangeTime ? (long long)RTTimeSpecGetNano(pChangeTime) : -1,
326 pBirthTime ? (long long)RTTimeSpecGetNano(pBirthTime) : -1); */
327 if (pAccessTime)
328 g_testRTDirSetTimes_ATime = *pAccessTime;
329 else
330 RT_ZERO(g_testRTDirSetTimes_ATime);
331 return VINF_SUCCESS;
332}
333
334static RTFILE g_testRTFileClose_hFile;
335
336extern int testRTFileClose(RTFILE File)
337{
338 /* RTPrintf("%s: File=%p\n", __PRETTY_FUNCTION__, File); */
339 g_testRTFileClose_hFile = File;
340 return 0;
341}
342
343extern int testRTFileDelete(const char *pszFilename)
344{
345 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszFilename, "/\\")))
346 return VERR_FILE_NOT_FOUND;
347 RTPrintf("%s\n", __PRETTY_FUNCTION__);
348 return 0;
349}
350
351static RTFILE g_testRTFileFlush_hFile;
352
353extern int testRTFileFlush(RTFILE File)
354{
355 /* RTPrintf("%s: File=%p\n", __PRETTY_FUNCTION__, File); */
356 g_testRTFileFlush_hFile = File;
357 return VINF_SUCCESS;
358}
359
360static RTFILE g_testRTFileLock_hFile;
361static unsigned g_testRTFileLock_fLock;
362static int64_t g_testRTFileLock_offLock;
363static uint64_t g_testRTFileLock_cbLock;
364
365extern int testRTFileLock(RTFILE hFile, unsigned fLock, int64_t offLock, uint64_t cbLock)
366{
367 /* RTPrintf("%s: hFile=%p, fLock=%u, offLock=%lli, cbLock=%llu\n",
368 __PRETTY_FUNCTION__, hFile, fLock, (long long) offLock,
369 LLUIFY(cbLock)); */
370 g_testRTFileLock_hFile = hFile;
371 g_testRTFileLock_fLock = fLock;
372 g_testRTFileLock_offLock = offLock;
373 g_testRTFileLock_cbLock = cbLock;
374 return VINF_SUCCESS;
375}
376
377static char g_testRTFileOpen_szName[256];
378static uint64_t g_testRTFileOpen_fOpen;
379static RTFILE g_testRTFileOpen_hFile;
380
381extern int testRTFileOpenEx(const char *pszFilename, uint64_t fOpen, PRTFILE phFile, PRTFILEACTION penmActionTaken)
382{
383 /* RTPrintf("%s, pszFilename=%s, fOpen=0x%llx\n", __PRETTY_FUNCTION__,
384 pszFilename, LLUIFY(fOpen)); */
385 ARRAY_FROM_PATH(g_testRTFileOpen_szName, pszFilename);
386 g_testRTFileOpen_fOpen = fOpen;
387 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszFilename, "/\\")))
388 return VERR_FILE_NOT_FOUND;
389 *phFile = g_testRTFileOpen_hFile;
390 *penmActionTaken = RTFILEACTION_CREATED;
391 g_testRTFileOpen_hFile = 0;
392 return VINF_SUCCESS;
393}
394
395static RTFILE g_testRTFileQueryInfo_hFile;
396static RTTIMESPEC g_testRTFileQueryInfo_ATime;
397static uint32_t g_testRTFileQueryInfo_fMode;
398
399extern int testRTFileQueryInfo(RTFILE hFile, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
400{
401 RT_NOREF1(enmAdditionalAttribs);
402 /* RTPrintf("%s, hFile=%p, enmAdditionalAttribs=0x%llx\n",
403 __PRETTY_FUNCTION__, hFile, LLUIFY(enmAdditionalAttribs)); */
404 g_testRTFileQueryInfo_hFile = hFile;
405 RT_ZERO(*pObjInfo);
406 pObjInfo->AccessTime = g_testRTFileQueryInfo_ATime;
407 RT_ZERO(g_testRTDirQueryInfo_ATime);
408 pObjInfo->Attr.fMode = g_testRTFileQueryInfo_fMode;
409 g_testRTFileQueryInfo_fMode = 0;
410 return VINF_SUCCESS;
411}
412
413static const char *g_testRTFileRead_pszData;
414
415extern int testRTFileRead(RTFILE File, void *pvBuf, size_t cbToRead, size_t *pcbRead)
416{
417 RT_NOREF1(File);
418 /* RTPrintf("%s : File=%p, cbToRead=%llu\n", __PRETTY_FUNCTION__, File,
419 LLUIFY(cbToRead)); */
420 bufferFromPath((char *)pvBuf, cbToRead, g_testRTFileRead_pszData);
421 if (pcbRead)
422 {
423 size_t cchData = strlen(g_testRTFileRead_pszData) + 1;
424 *pcbRead = RT_MIN(cbToRead, cchData);
425 }
426 g_testRTFileRead_pszData = 0;
427 return VINF_SUCCESS;
428}
429
430extern int testRTFileReadAt(RTFILE hFile, uint64_t offFile, void *pvBuf, size_t cbToRead, size_t *pcbRead)
431{
432 RT_NOREF1(hFile);
433 RT_NOREF(offFile);
434 /* RTPrintf("%s : File=%p, cbToRead=%llu\n", __PRETTY_FUNCTION__, File,
435 LLUIFY(cbToRead)); */
436 bufferFromPath((char *)pvBuf, cbToRead, g_testRTFileRead_pszData);
437 if (pcbRead)
438 {
439 size_t cchData = strlen(g_testRTFileRead_pszData) + 1;
440 *pcbRead = RT_MIN(cbToRead, cchData);
441 }
442 g_testRTFileRead_pszData = 0;
443 return VINF_SUCCESS;
444}
445
446extern int testRTFileSeek(RTFILE hFile, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
447{
448 RT_NOREF3(hFile, offSeek, uMethod);
449 /* RTPrintf("%s : hFile=%p, offSeek=%llu, uMethod=%u\n", __PRETTY_FUNCTION__,
450 hFile, LLUIFY(offSeek), uMethod); */
451 if (poffActual)
452 *poffActual = 0;
453 return VINF_SUCCESS;
454}
455
456static uint64_t g_testRTFileSet_fMode;
457
458extern int testRTFileSetMode(RTFILE File, RTFMODE fMode)
459{
460 RT_NOREF1(File);
461 /* RTPrintf("%s: fMode=%llu\n", __PRETTY_FUNCTION__, LLUIFY(fMode)); */
462 g_testRTFileSet_fMode = fMode;
463 return VINF_SUCCESS;
464}
465
466static RTFILE g_testRTFileSetSize_hFile;
467static RTFOFF g_testRTFileSetSize_cbSize;
468
469extern int testRTFileSetSize(RTFILE File, uint64_t cbSize)
470{
471 /* RTPrintf("%s: File=%llu, cbSize=%llu\n", __PRETTY_FUNCTION__, LLUIFY(File),
472 LLUIFY(cbSize)); */
473 g_testRTFileSetSize_hFile = File;
474 g_testRTFileSetSize_cbSize = (RTFOFF) cbSize; /* Why was this signed before? */
475 return VINF_SUCCESS;
476}
477
478static RTTIMESPEC g_testRTFileSetTimes_ATime;
479
480extern int testRTFileSetTimes(RTFILE File, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
481 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
482{
483 RT_NOREF4(File, pModificationTime, pChangeTime, pBirthTime);
484 /* RTPrintf("%s: pFile=%p, *pAccessTime=%lli, *pModificationTime=%lli, *pChangeTime=%lli, *pBirthTime=%lli\n",
485 __PRETTY_FUNCTION__,
486 pAccessTime ? (long long)RTTimeSpecGetNano(pAccessTime) : -1,
487 pModificationTime
488 ? (long long)RTTimeSpecGetNano(pModificationTime) : -1,
489 pChangeTime ? (long long)RTTimeSpecGetNano(pChangeTime) : -1,
490 pBirthTime ? (long long)RTTimeSpecGetNano(pBirthTime) : -1); */
491 if (pAccessTime)
492 g_testRTFileSetTimes_ATime = *pAccessTime;
493 else
494 RT_ZERO(g_testRTFileSetTimes_ATime);
495 return VINF_SUCCESS;
496}
497
498static RTFILE g_testRTFileUnlock_hFile;
499static int64_t g_testRTFileUnlock_offLock;
500static uint64_t g_testRTFileUnlock_cbLock;
501
502extern int testRTFileUnlock(RTFILE File, int64_t offLock, uint64_t cbLock)
503{
504 /* RTPrintf("%s: hFile=%p, ofLock=%lli, cbLock=%llu\n", __PRETTY_FUNCTION__,
505 File, (long long) offLock, LLUIFY(cbLock)); */
506 g_testRTFileUnlock_hFile = File;
507 g_testRTFileUnlock_offLock = offLock;
508 g_testRTFileUnlock_cbLock = cbLock;
509 return VINF_SUCCESS;
510}
511
512static char g_testRTFileWrite_szData[256];
513
514extern int testRTFileWrite(RTFILE File, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
515{
516 RT_NOREF2(File, cbToWrite);
517 /* RTPrintf("%s: File=%p, pvBuf=%.*s, cbToWrite=%llu\n", __PRETTY_FUNCTION__,
518 File, cbToWrite, (const char *)pvBuf, LLUIFY(cbToWrite)); */
519 ARRAY_FROM_PATH(g_testRTFileWrite_szData, (const char *)pvBuf);
520 if (pcbWritten)
521 *pcbWritten = strlen(g_testRTFileWrite_szData) + 1;
522 return VINF_SUCCESS;
523}
524
525extern int testRTFileWriteAt(RTFILE File, uint64_t offFile, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
526{
527 RT_NOREF3(File, cbToWrite, offFile);
528 /* RTPrintf("%s: File=%p, pvBuf=%.*s, cbToWrite=%llu\n", __PRETTY_FUNCTION__,
529 File, cbToWrite, (const char *)pvBuf, LLUIFY(cbToWrite)); */
530 ARRAY_FROM_PATH(g_testRTFileWrite_szData, (const char *)pvBuf);
531 if (pcbWritten)
532 *pcbWritten = strlen(g_testRTFileWrite_szData) + 1;
533 return VINF_SUCCESS;
534}
535
536extern int testRTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
537{
538 RT_NOREF1(pszFsPath);
539 /* RTPrintf("%s, pszFsPath=%s\n", __PRETTY_FUNCTION__, pszFsPath);
540 RT_ZERO(*pProperties); */
541 pProperties->cbMaxComponent = 256;
542 pProperties->fCaseSensitive = true;
543 return VINF_SUCCESS;
544}
545
546extern int testRTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial)
547{
548 RT_NOREF2(pszFsPath, pu32Serial);
549 RTPrintf("%s\n", __PRETTY_FUNCTION__);
550 return 0;
551}
552extern int testRTFsQuerySizes(const char *pszFsPath, PRTFOFF pcbTotal, RTFOFF *pcbFree, uint32_t *pcbBlock, uint32_t *pcbSector)
553{
554 RT_NOREF5(pszFsPath, pcbTotal, pcbFree, pcbBlock, pcbSector);
555 RTPrintf("%s\n", __PRETTY_FUNCTION__);
556 return 0;
557}
558
559extern int testRTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
560{
561 RT_NOREF2(enmAdditionalAttribs, fFlags);
562 /* RTPrintf("%s: pszPath=%s, enmAdditionalAttribs=0x%x, fFlags=0x%x\n",
563 __PRETTY_FUNCTION__, pszPath, (unsigned) enmAdditionalAttribs,
564 (unsigned) fFlags); */
565 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszPath, "/\\")))
566 return VERR_FILE_NOT_FOUND;
567 RT_ZERO(*pObjInfo);
568 return VINF_SUCCESS;
569}
570
571extern int testRTSymlinkDelete(const char *pszSymlink, uint32_t fDelete)
572{
573 RT_NOREF2(pszSymlink, fDelete);
574 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszSymlink, "/\\")))
575 return VERR_FILE_NOT_FOUND;
576 RTPrintf("%s\n", __PRETTY_FUNCTION__);
577 return 0;
578}
579
580extern int testRTSymlinkRead(const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead)
581{
582 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszSymlink, "/\\")))
583 return VERR_FILE_NOT_FOUND;
584 RT_NOREF4(pszSymlink, pszTarget, cbTarget, fRead);
585 RTPrintf("%s\n", __PRETTY_FUNCTION__);
586 return 0;
587}
588
589extern int testRTSymlinkCreate(const char *pszSymlink, const char *pszTarget, RTSYMLINKTYPE enmType, uint32_t fCreate)
590{
591 if (g_fFailIfNotLowercase && !RTStrIsLowerCased(strpbrk(pszSymlink, "/\\")))
592 return VERR_FILE_NOT_FOUND;
593 RT_NOREF4(pszSymlink, pszTarget, enmType, fCreate);
594 return 0;
595}
596
597
598/*********************************************************************************************************************************
599* Tests *
600*********************************************************************************************************************************/
601
602/* Sub-tests for testMappingsQuery(). */
603void testMappingsQuerySimple(RTTEST hTest) { RT_NOREF1(hTest); }
604void testMappingsQueryTooFewBuffers(RTTEST hTest) { RT_NOREF1(hTest); }
605void testMappingsQueryAutoMount(RTTEST hTest) { RT_NOREF1(hTest); }
606void testMappingsQueryArrayWrongSize(RTTEST hTest) { RT_NOREF1(hTest); }
607
608/* Sub-tests for testMappingsQueryName(). */
609void testMappingsQueryNameValid(RTTEST hTest) { RT_NOREF1(hTest); }
610void testMappingsQueryNameInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
611void testMappingsQueryNameBadBuffer(RTTEST hTest) { RT_NOREF1(hTest); }
612
613/* Sub-tests for testMapFolder(). */
614void testMapFolderValid(RTTEST hTest) { RT_NOREF1(hTest); }
615void testMapFolderInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
616void testMapFolderTwice(RTTEST hTest) { RT_NOREF1(hTest); }
617void testMapFolderDelimiter(RTTEST hTest) { RT_NOREF1(hTest); }
618void testMapFolderCaseSensitive(RTTEST hTest) { RT_NOREF1(hTest); }
619void testMapFolderCaseInsensitive(RTTEST hTest) { RT_NOREF1(hTest); }
620void testMapFolderBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
621
622/* Sub-tests for testUnmapFolder(). */
623void testUnmapFolderValid(RTTEST hTest) { RT_NOREF1(hTest); }
624void testUnmapFolderInvalid(RTTEST hTest) { RT_NOREF1(hTest); }
625void testUnmapFolderBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
626
627/* Sub-tests for testCreate(). */
628void testCreateBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
629
630/* Sub-tests for testClose(). */
631void testCloseBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
632
633/* Sub-tests for testRead(). */
634void testReadBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
635
636/* Sub-tests for testWrite(). */
637void testWriteBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
638
639/* Sub-tests for testLock(). */
640void testLockBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
641
642/* Sub-tests for testFlush(). */
643void testFlushBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
644
645/* Sub-tests for testDirList(). */
646void testDirListBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
647
648/* Sub-tests for testReadLink(). */
649void testReadLinkBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
650
651/* Sub-tests for testFSInfo(). */
652void testFSInfoBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
653
654/* Sub-tests for testRemove(). */
655void testRemoveBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
656
657/* Sub-tests for testRename(). */
658void testRenameBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
659
660/* Sub-tests for testSymlink(). */
661void testSymlinkBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
662
663/* Sub-tests for testMappingsAdd(). */
664void testMappingsAddBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
665
666/* Sub-tests for testMappingsRemove(). */
667void testMappingsRemoveBadParameters(RTTEST hTest) { RT_NOREF1(hTest); }
668
669union TESTSHFLSTRING
670{
671 SHFLSTRING string;
672 char acData[256];
673};
674
675static void fillTestShflString(union TESTSHFLSTRING *pDest,
676 const char *pcszSource)
677{
678 const size_t cchSource = strlen(pcszSource);
679 AssertRelease( cchSource * 2 + 2
680 < sizeof(*pDest) - RT_UOFFSETOF(SHFLSTRING, String));
681 pDest->string.u16Length = (uint16_t)(cchSource * sizeof(RTUTF16));
682 pDest->string.u16Size = pDest->string.u16Length + sizeof(RTUTF16);
683 /* Copy pcszSource ASCIIZ, including the trailing 0, to the UTF16 pDest->string.String.ucs2. */
684 for (unsigned i = 0; i <= cchSource; ++i)
685 pDest->string.String.ucs2[i] = (uint16_t)pcszSource[i];
686}
687
688static void fillTestShflStringUtf8(union TESTSHFLSTRING *pDest,
689 const char *pcszSource)
690{
691 const size_t cchSource = strlen(pcszSource);
692 AssertRelease( cchSource * 2 + 2
693 < sizeof(*pDest) - RT_UOFFSETOF(SHFLSTRING, String));
694 pDest->string.u16Length = (uint16_t)cchSource;
695 pDest->string.u16Size = pDest->string.u16Length + 1;
696 memcpy(pDest->string.String.utf8, pcszSource, pDest->string.u16Size);
697}
698
699static SHFLROOT initWithWritableMapping(RTTEST hTest,
700 VBOXHGCMSVCFNTABLE *psvcTable,
701 VBOXHGCMSVCHELPERS *psvcHelpers,
702 const char *pcszFolderName,
703 const char *pcszMapping,
704 bool fCaseSensitive = true,
705 SymlinkPolicy_T enmSymlinkPolicy = SymlinkPolicy_AllowedToAnyTarget)
706{
707 VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_ADD_MAPPING,
708 SHFL_CPARMS_MAP_FOLDER)];
709 union TESTSHFLSTRING FolderName;
710 union TESTSHFLSTRING Mapping;
711 union TESTSHFLSTRING AutoMountPoint;
712 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
713 int rc;
714
715 initTable(psvcTable, psvcHelpers);
716 rc = VBoxHGCMSvcLoad(psvcTable);
717 AssertReleaseRC(rc);
718 AssertRelease( psvcTable->pvService
719 = RTTestGuardedAllocTail(hTest, psvcTable->cbClient));
720 RT_BZERO(psvcTable->pvService, psvcTable->cbClient);
721 fillTestShflString(&FolderName, pcszFolderName);
722 fillTestShflString(&Mapping, pcszMapping);
723 fillTestShflString(&AutoMountPoint, "");
724 HGCMSvcSetPv(&aParms[0], &FolderName, RT_UOFFSETOF(SHFLSTRING, String)
725 + FolderName.string.u16Size);
726 HGCMSvcSetPv(&aParms[1], &Mapping, RT_UOFFSETOF(SHFLSTRING, String)
727 + Mapping.string.u16Size);
728 HGCMSvcSetU32(&aParms[2], SHFL_ADD_MAPPING_F_WRITABLE | SHFL_ADD_MAPPING_F_CREATE_SYMLINKS);
729 HGCMSvcSetPv(&aParms[3], &AutoMountPoint, SHFLSTRING_HEADER_SIZE + AutoMountPoint.string.u16Size);
730 HGCMSvcSetU32(&aParms[4], enmSymlinkPolicy);
731 rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_ADD_MAPPING,
732 SHFL_CPARMS_ADD_MAPPING, aParms);
733 AssertReleaseRC(rc);
734 HGCMSvcSetPv(&aParms[0], &Mapping, RT_UOFFSETOF(SHFLSTRING, String)
735 + Mapping.string.u16Size);
736 HGCMSvcSetU32(&aParms[1], 0); /* root */
737 HGCMSvcSetU32(&aParms[2], '/'); /* delimiter */
738 HGCMSvcSetU32(&aParms[3], fCaseSensitive);
739 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
740 psvcTable->pvService, SHFL_FN_MAP_FOLDER,
741 SHFL_CPARMS_MAP_FOLDER, aParms, 0);
742 AssertReleaseRC(callHandle.rc);
743 return aParms[1].u.uint32;
744}
745
746/** @todo Mappings should be automatically removed by unloading the service,
747 * but unloading is currently a no-op! */
748static void unmapAndRemoveMapping(RTTEST hTest, VBOXHGCMSVCFNTABLE *psvcTable,
749 SHFLROOT root, const char *pcszFolderName)
750{
751 RT_NOREF1(hTest);
752 VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_UNMAP_FOLDER,
753 SHFL_CPARMS_REMOVE_MAPPING)];
754 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
755 union TESTSHFLSTRING FolderName;
756 int rc;
757
758 HGCMSvcSetU32(&aParms[0], root);
759 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
760 psvcTable->pvService, SHFL_FN_UNMAP_FOLDER,
761 SHFL_CPARMS_UNMAP_FOLDER, aParms, 0);
762 AssertReleaseRC(callHandle.rc);
763 fillTestShflString(&FolderName, pcszFolderName);
764 HGCMSvcSetPv(&aParms[0], &FolderName, RT_UOFFSETOF(SHFLSTRING, String)
765 + FolderName.string.u16Size);
766 rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_REMOVE_MAPPING,
767 SHFL_CPARMS_REMOVE_MAPPING, aParms);
768 AssertReleaseRC(rc);
769}
770
771static int createFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
772 const char *pcszFilename, uint32_t fCreateFlags,
773 SHFLHANDLE *pHandle, SHFLCREATERESULT *pResult)
774{
775 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_CREATE];
776 union TESTSHFLSTRING Path;
777 SHFLCREATEPARMS CreateParms;
778 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
779
780 fillTestShflString(&Path, pcszFilename);
781 RT_ZERO(CreateParms);
782 CreateParms.CreateFlags = fCreateFlags;
783 HGCMSvcSetU32(&aParms[0], Root);
784 HGCMSvcSetPv(&aParms[1], &Path, RT_UOFFSETOF(SHFLSTRING, String)
785 + Path.string.u16Size);
786 HGCMSvcSetPv(&aParms[2], &CreateParms, sizeof(CreateParms));
787 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
788 psvcTable->pvService, SHFL_FN_CREATE,
789 RT_ELEMENTS(aParms), aParms, 0);
790 if (RT_FAILURE(callHandle.rc))
791 return callHandle.rc;
792 if (pHandle)
793 *pHandle = CreateParms.Handle;
794 if (pResult)
795 *pResult = CreateParms.Result;
796 return VINF_SUCCESS;
797}
798
799static int createSymlink(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
800 const char *pcszSourcePath, const char *pcszSymlinkPath)
801{
802 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_SYMLINK];
803 union TESTSHFLSTRING sourcePath;
804 union TESTSHFLSTRING symlinkPath;
805 SHFLFSOBJINFO ObjInfo;
806 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
807
808 /* vbsfSymlink() only supports UTF-8 */
809 fillTestShflStringUtf8(&sourcePath, pcszSourcePath);
810 fillTestShflStringUtf8(&symlinkPath, pcszSymlinkPath);
811 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
812 psvcTable->pvService, SHFL_FN_SET_UTF8,
813 RT_ELEMENTS(aParms), aParms, 0);
814
815 RT_ZERO(ObjInfo);
816 HGCMSvcSetU32(&aParms[0], Root);
817 HGCMSvcSetPv(&aParms[1], &symlinkPath, RT_UOFFSETOF(SHFLSTRING, String)
818 + symlinkPath.string.u16Size);
819 HGCMSvcSetPv(&aParms[2], &sourcePath, RT_UOFFSETOF(SHFLSTRING, String)
820 + sourcePath.string.u16Size);
821 HGCMSvcSetPv(&aParms[3], &ObjInfo, sizeof(ObjInfo));
822 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
823 psvcTable->pvService, SHFL_FN_SYMLINK,
824 RT_ELEMENTS(aParms), aParms, 0);
825 return callHandle.rc;
826}
827
828static int readFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
829 SHFLHANDLE hFile, uint64_t offSeek, uint32_t cbRead,
830 uint32_t *pcbRead, void *pvBuf, uint32_t cbBuf)
831{
832 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_READ];
833 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
834
835 HGCMSvcSetU32(&aParms[0], Root);
836 HGCMSvcSetU64(&aParms[1], (uint64_t) hFile);
837 HGCMSvcSetU64(&aParms[2], offSeek);
838 HGCMSvcSetU32(&aParms[3], cbRead);
839 HGCMSvcSetPv(&aParms[4], pvBuf, cbBuf);
840 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
841 psvcTable->pvService, SHFL_FN_READ,
842 RT_ELEMENTS(aParms), aParms, 0);
843 if (pcbRead)
844 *pcbRead = aParms[3].u.uint32;
845 return callHandle.rc;
846}
847
848static int writeFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT Root,
849 SHFLHANDLE hFile, uint64_t offSeek, uint32_t cbWrite,
850 uint32_t *pcbWritten, const void *pvBuf, uint32_t cbBuf)
851{
852 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_WRITE];
853 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
854
855 HGCMSvcSetU32(&aParms[0], Root);
856 HGCMSvcSetU64(&aParms[1], (uint64_t) hFile);
857 HGCMSvcSetU64(&aParms[2], offSeek);
858 HGCMSvcSetU32(&aParms[3], cbWrite);
859 HGCMSvcSetPv(&aParms[4], (void *)pvBuf, cbBuf);
860 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
861 psvcTable->pvService, SHFL_FN_WRITE,
862 RT_ELEMENTS(aParms), aParms, 0);
863 if (pcbWritten)
864 *pcbWritten = aParms[3].u.uint32;
865 return callHandle.rc;
866}
867
868static int flushFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
869 SHFLHANDLE handle)
870{
871 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_FLUSH];
872 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
873
874 HGCMSvcSetU32(&aParms[0], root);
875 HGCMSvcSetU64(&aParms[1], handle);
876 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
877 psvcTable->pvService, SHFL_FN_FLUSH,
878 SHFL_CPARMS_FLUSH, aParms, 0);
879 return callHandle.rc;
880}
881
882static int listDir(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
883 SHFLHANDLE handle, uint32_t fFlags,
884 const char *pcszPath, void *pvBuf, uint32_t cbBuf,
885 uint32_t resumePoint, uint32_t *pcFiles)
886{
887 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_LIST];
888 union TESTSHFLSTRING Path;
889 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
890
891 HGCMSvcSetU32(&aParms[0], root);
892 HGCMSvcSetU64(&aParms[1], handle);
893 HGCMSvcSetU32(&aParms[2], fFlags);
894 HGCMSvcSetU32(&aParms[3], cbBuf);
895 if (pcszPath)
896 {
897 fillTestShflString(&Path, pcszPath);
898 HGCMSvcSetPv(&aParms[4], &Path, RT_UOFFSETOF(SHFLSTRING, String)
899 + Path.string.u16Size);
900 }
901 else
902 HGCMSvcSetPv(&aParms[4], NULL, 0);
903 HGCMSvcSetPv(&aParms[5], pvBuf, cbBuf);
904 HGCMSvcSetU32(&aParms[6], resumePoint);
905 HGCMSvcSetU32(&aParms[7], 0);
906 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
907 psvcTable->pvService, SHFL_FN_LIST,
908 RT_ELEMENTS(aParms), aParms, 0);
909 if (pcFiles)
910 *pcFiles = aParms[7].u.uint32;
911 return callHandle.rc;
912}
913
914static int sfInformation(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
915 SHFLHANDLE handle, uint32_t fFlags, uint32_t cb,
916 SHFLFSOBJINFO *pInfo)
917{
918 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_INFORMATION];
919 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
920
921 HGCMSvcSetU32(&aParms[0], root);
922 HGCMSvcSetU64(&aParms[1], handle);
923 HGCMSvcSetU32(&aParms[2], fFlags);
924 HGCMSvcSetU32(&aParms[3], cb);
925 HGCMSvcSetPv(&aParms[4], pInfo, cb);
926 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
927 psvcTable->pvService, SHFL_FN_INFORMATION,
928 RT_ELEMENTS(aParms), aParms, 0);
929 return callHandle.rc;
930}
931
932static int lockFile(VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root,
933 SHFLHANDLE handle, int64_t offLock, uint64_t cbLock,
934 uint32_t fFlags)
935{
936 VBOXHGCMSVCPARM aParms[SHFL_CPARMS_LOCK];
937 VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
938
939 HGCMSvcSetU32(&aParms[0], root);
940 HGCMSvcSetU64(&aParms[1], handle);
941 HGCMSvcSetU64(&aParms[2], offLock);
942 HGCMSvcSetU64(&aParms[3], cbLock);
943 HGCMSvcSetU32(&aParms[4], fFlags);
944 psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0,
945 psvcTable->pvService, SHFL_FN_LOCK,
946 RT_ELEMENTS(aParms), aParms, 0);
947 return callHandle.rc;
948}
949
950void testCreateFileSimple(RTTEST hTest)
951{
952 VBOXHGCMSVCFNTABLE svcTable;
953 VBOXHGCMSVCHELPERS svcHelpers;
954 SHFLROOT Root;
955 const RTFILE hFile = (RTFILE) 0x10000;
956 SHFLCREATERESULT Result;
957 int rc;
958
959 RTTestSub(hTest, "Create file simple");
960 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
961 "/test/mapping", "testname");
962 g_testRTFileOpen_hFile = hFile;
963 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, NULL,
964 &Result);
965 RTTEST_CHECK_RC_OK(hTest, rc);
966 RTTEST_CHECK_MSG(hTest,
967 !strcmp(&g_testRTFileOpen_szName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
968 "/test/mapping/test/file"),
969 (hTest, "pszFilename=%s\n", &g_testRTFileOpen_szName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
970 RTTEST_CHECK_MSG(hTest, g_testRTFileOpen_fOpen == 0x181,
971 (hTest, "fOpen=%llu\n", LLUIFY(g_testRTFileOpen_fOpen)));
972 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
973 (hTest, "Result=%d\n", (int) Result));
974 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
975 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
976 AssertReleaseRC(rc);
977 rc = svcTable.pfnUnload(NULL);
978 AssertReleaseRC(rc);
979 RTTestGuardedFree(hTest, svcTable.pvService);
980 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile,
981 (hTest, "File=%u\n", (uintptr_t)g_testRTFileClose_hFile));
982}
983
984void testCreateFileSimpleCaseInsensitive(RTTEST hTest)
985{
986 VBOXHGCMSVCFNTABLE svcTable;
987 VBOXHGCMSVCHELPERS svcHelpers;
988 SHFLROOT Root;
989 const RTFILE hFile = (RTFILE) 0x10000;
990 SHFLCREATERESULT Result;
991 int rc;
992
993 g_fFailIfNotLowercase = true;
994
995 RTTestSub(hTest, "Create file case insensitive");
996 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
997 "/test/mapping", "testname", false /*fCaseSensitive*/);
998 g_testRTFileOpen_hFile = hFile;
999 rc = createFile(&svcTable, Root, "/TesT/FilE", SHFL_CF_ACCESS_READ, NULL,
1000 &Result);
1001 RTTEST_CHECK_RC_OK(hTest, rc);
1002
1003 RTTEST_CHECK_MSG(hTest,
1004 !strcmp(&g_testRTFileOpen_szName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
1005 "/test/mapping/test/file"),
1006 (hTest, "pszFilename=%s\n", &g_testRTFileOpen_szName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
1007 RTTEST_CHECK_MSG(hTest, g_testRTFileOpen_fOpen == 0x181,
1008 (hTest, "fOpen=%llu\n", LLUIFY(g_testRTFileOpen_fOpen)));
1009 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
1010 (hTest, "Result=%d\n", (int) Result));
1011 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1012 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1013 AssertReleaseRC(rc);
1014 rc = svcTable.pfnUnload(NULL);
1015 AssertReleaseRC(rc);
1016 RTTestGuardedFree(hTest, svcTable.pvService);
1017 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile,
1018 (hTest, "File=%u\n", (uintptr_t)g_testRTFileClose_hFile));
1019
1020 g_fFailIfNotLowercase = false;
1021}
1022
1023void testCreateDirSimple(RTTEST hTest)
1024{
1025 VBOXHGCMSVCFNTABLE svcTable;
1026 VBOXHGCMSVCHELPERS svcHelpers;
1027 SHFLROOT Root;
1028 RTDIR hDir = (RTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
1029 SHFLCREATERESULT Result;
1030 int rc;
1031
1032 RTTestSub(hTest, "Create directory simple");
1033 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1034 "/test/mapping", "testname");
1035 g_testRTDirOpen_hDir = hDir;
1036 rc = createFile(&svcTable, Root, "test/dir",
1037 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, NULL, &Result);
1038 RTTEST_CHECK_RC_OK(hTest, rc);
1039 RTTEST_CHECK_MSG(hTest,
1040 !strcmp(&g_testRTDirCreate_szPath[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
1041 "/test/mapping/test/dir"),
1042 (hTest, "pszPath=%s\n", &g_testRTDirCreate_szPath[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
1043 RTTEST_CHECK_MSG(hTest,
1044 !strcmp(&g_testRTDirOpen_szName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
1045 "/test/mapping/test/dir"),
1046 (hTest, "pszFilename=%s\n", &g_testRTDirOpen_szName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
1047 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
1048 (hTest, "Result=%d\n", (int) Result));
1049 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1050 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1051 AssertReleaseRC(rc);
1052 rc = svcTable.pfnUnload(NULL);
1053 AssertReleaseRC(rc);
1054 RTTestGuardedFree(hTest, svcTable.pvService);
1055 RTTEST_CHECK_MSG(hTest, g_testRTDirClose_hDir == hDir, (hTest, "hDir=%p\n", g_testRTDirClose_hDir));
1056}
1057
1058static int testSymlinkCreationForSpecificPolicy(RTTEST hTest, SymlinkPolicy_T enmSymlinkPolicy)
1059{
1060 VBOXHGCMSVCFNTABLE svcTable;
1061 VBOXHGCMSVCHELPERS svcHelpers;
1062 SHFLROOT Root;
1063 const RTFILE hFile = (RTFILE) 0x10000;
1064 SHFLCREATERESULT Result;
1065 int rc;
1066
1067 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1068 "/test/mapping", "testname",
1069 true, enmSymlinkPolicy);
1070 g_testRTFileOpen_hFile = hFile;
1071 rc = createFile(&svcTable, Root, "file", SHFL_CF_ACCESS_READ, NULL, &Result);
1072 RTTEST_CHECK_RC_OK(hTest, rc);
1073 RTTEST_CHECK_MSG(hTest,
1074 !strcmp(&g_testRTFileOpen_szName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0],
1075 "/test/mapping/file"),
1076 (hTest, "pszFilename=%s\n", &g_testRTFileOpen_szName[RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS ? 2 : 0]));
1077 RTTEST_CHECK_MSG(hTest, g_testRTFileOpen_fOpen == 0x181,
1078 (hTest, "fOpen=%llu\n", LLUIFY(g_testRTFileOpen_fOpen)));
1079 RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED,
1080 (hTest, "Result=%d\n", (int)Result));
1081
1082 /* regular symlink creation should succeed unless no symlinks allowed */
1083 rc = createSymlink(&svcTable, Root, "file", "symlink");
1084 if (enmSymlinkPolicy == SymlinkPolicy_Forbidden)
1085 RTTEST_CHECK_MSG(hTest, rc == VERR_WRITE_PROTECT,
1086 (hTest, "enmSymlinkPolicy=SymlinkPolicy_Forbidden 'ln -s file symlink' failed: rc=%Rrc\n", rc));
1087 else
1088 RTTEST_CHECK_RC_OK(hTest, rc);
1089
1090 /* absolute path to symlink sources only allowed for the 'any' policy */
1091 rc = createSymlink(&svcTable, Root, "/path/to/file", "abs-symlink");
1092 if (enmSymlinkPolicy == SymlinkPolicy_AllowedToAnyTarget)
1093 RTTEST_CHECK_RC_OK(hTest, rc);
1094 else
1095 RTTEST_CHECK_MSG(hTest, rc == VERR_WRITE_PROTECT,
1096 (hTest, "enmSymlinkPolicy=%d 'ln -s file /absolute/path/symlink' failed: rc=%Rrc\n",
1097 enmSymlinkPolicy, rc));
1098
1099 /* relative path symlink sources with '..' components allowed only with 'relative' policy */
1100 rc = createSymlink(&svcTable, Root, "./directory/../file", "rel-symlink");
1101 if ( enmSymlinkPolicy == SymlinkPolicy_Forbidden
1102 || enmSymlinkPolicy == SymlinkPolicy_AllowedInShareSubtree)
1103 RTTEST_CHECK_MSG(hTest, rc == VERR_WRITE_PROTECT,
1104 (hTest, "enmSymlinkPolicy=%d 'ln -s ./path/../symlink' failed: rc=%Rrc\n",
1105 enmSymlinkPolicy, rc));
1106 else
1107 RTTEST_CHECK_RC_OK(hTest, rc);
1108
1109 /* relative path symlink source with no '..' components always OK */
1110 rc = createSymlink(&svcTable, Root, "./directory/file", "dotslash-symlink");
1111 if (enmSymlinkPolicy == SymlinkPolicy_Forbidden)
1112 RTTEST_CHECK_MSG(hTest, rc == VERR_WRITE_PROTECT,
1113 (hTest, "enmSymlinkPolicy=%d 'ln -s ./path/../symlink' failed: rc=%Rrc\n",
1114 enmSymlinkPolicy, rc));
1115 else
1116 RTTEST_CHECK_RC_OK(hTest, rc);
1117
1118 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1119 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1120 AssertReleaseRC(rc);
1121 rc = svcTable.pfnUnload(NULL);
1122 AssertReleaseRC(rc);
1123 RTTestGuardedFree(hTest, svcTable.pvService);
1124 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile,
1125 (hTest, "File=%u\n", (uintptr_t)g_testRTFileClose_hFile));
1126
1127 return rc;
1128}
1129
1130void testSymlinkCreation(RTTEST hTest)
1131{
1132 SymlinkPolicy_T aEnmSymlinkPolicy[4] = {
1133 SymlinkPolicy_AllowedToAnyTarget,
1134 SymlinkPolicy_AllowedInShareSubtree,
1135 SymlinkPolicy_AllowedToRelativeTargets,
1136 SymlinkPolicy_Forbidden
1137 };
1138
1139 RTTestSub(hTest, "Create variety of symlinks with different symlink policies");
1140 for (size_t i = 0; i < RT_ELEMENTS(aEnmSymlinkPolicy); i++)
1141 testSymlinkCreationForSpecificPolicy(hTest, aEnmSymlinkPolicy[i]);
1142}
1143
1144void testReadFileSimple(RTTEST hTest)
1145{
1146 VBOXHGCMSVCFNTABLE svcTable;
1147 VBOXHGCMSVCHELPERS svcHelpers;
1148 SHFLROOT Root;
1149 const RTFILE hFile = (RTFILE) 0x10000;
1150 SHFLHANDLE Handle;
1151 const char *pcszReadData = "Data to read";
1152 char achBuf[sizeof(pcszReadData) + 10];
1153 uint32_t cbRead;
1154 int rc;
1155
1156 RTTestSub(hTest, "Read file simple");
1157 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1158 "/test/mapping", "testname");
1159 g_testRTFileOpen_hFile = hFile;
1160 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1161 &Handle, NULL);
1162 RTTEST_CHECK_RC_OK(hTest, rc);
1163 g_testRTFileRead_pszData = pcszReadData;
1164 memset(achBuf, 'f', sizeof(achBuf));
1165 rc = readFile(&svcTable, Root, Handle, 0, (uint32_t)strlen(pcszReadData) + 1,
1166 &cbRead, achBuf, (uint32_t)sizeof(achBuf));
1167 RTTEST_CHECK_RC_OK(hTest, rc);
1168 RTTEST_CHECK_MSG(hTest,
1169 !strncmp(achBuf, pcszReadData, sizeof(achBuf)),
1170 (hTest, "pvBuf=%.*s Handle=%#RX64\n", sizeof(achBuf), achBuf, Handle));
1171 RTTEST_CHECK_MSG(hTest, cbRead == strlen(pcszReadData) + 1,
1172 (hTest, "cbRead=%llu\n", LLUIFY(cbRead)));
1173 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1174 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile, (hTest, "File=%u\n", g_testRTFileClose_hFile));
1175 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1176 AssertReleaseRC(rc);
1177 rc = svcTable.pfnUnload(NULL);
1178 AssertReleaseRC(rc);
1179 RTTestGuardedFree(hTest, svcTable.pvService);
1180}
1181
1182void testWriteFileSimple(RTTEST hTest)
1183{
1184 VBOXHGCMSVCFNTABLE svcTable;
1185 VBOXHGCMSVCHELPERS svcHelpers;
1186 SHFLROOT Root;
1187 const RTFILE hFile = (RTFILE) 0x10000;
1188 SHFLHANDLE Handle;
1189 const char *pcszWrittenData = "Data to write";
1190 uint32_t cbToWrite = (uint32_t)strlen(pcszWrittenData) + 1;
1191 uint32_t cbWritten;
1192 int rc;
1193
1194 RTTestSub(hTest, "Write file simple");
1195 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1196 "/test/mapping", "testname");
1197 g_testRTFileOpen_hFile = hFile;
1198 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1199 &Handle, NULL);
1200 RTTEST_CHECK_RC_OK(hTest, rc);
1201 rc = writeFile(&svcTable, Root, Handle, 0, cbToWrite, &cbWritten,
1202 pcszWrittenData, cbToWrite);
1203 RTTEST_CHECK_RC_OK(hTest, rc);
1204 RTTEST_CHECK_MSG(hTest,
1205 !strcmp(g_testRTFileWrite_szData, pcszWrittenData),
1206 (hTest, "pvBuf=%s\n", g_testRTFileWrite_szData));
1207 RTTEST_CHECK_MSG(hTest, cbWritten == cbToWrite,
1208 (hTest, "cbWritten=%llu\n", LLUIFY(cbWritten)));
1209 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1210 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile, (hTest, "File=%u\n", g_testRTFileClose_hFile));
1211 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1212 AssertReleaseRC(rc);
1213 rc = svcTable.pfnUnload(NULL);
1214 AssertReleaseRC(rc);
1215 RTTestGuardedFree(hTest, svcTable.pvService);
1216}
1217
1218void testFlushFileSimple(RTTEST hTest)
1219{
1220 VBOXHGCMSVCFNTABLE svcTable;
1221 VBOXHGCMSVCHELPERS svcHelpers;
1222 SHFLROOT Root;
1223 const RTFILE hFile = (RTFILE) 0x10000;
1224 SHFLHANDLE Handle;
1225 int rc;
1226
1227 RTTestSub(hTest, "Flush file simple");
1228 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1229 "/test/mapping", "testname");
1230 g_testRTFileOpen_hFile = hFile;
1231 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1232 &Handle, NULL);
1233 RTTEST_CHECK_RC_OK(hTest, rc);
1234 rc = flushFile(&svcTable, Root, Handle);
1235 RTTEST_CHECK_RC_OK(hTest, rc);
1236 RTTEST_CHECK_MSG(hTest, g_testRTFileFlush_hFile == hFile, (hTest, "File=%u\n", g_testRTFileFlush_hFile));
1237 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1238 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1239 AssertReleaseRC(rc);
1240 rc = svcTable.pfnUnload(NULL);
1241 AssertReleaseRC(rc);
1242 RTTestGuardedFree(hTest, svcTable.pvService);
1243 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile, (hTest, "File=%u\n", g_testRTFileClose_hFile));
1244}
1245
1246void testDirListEmpty(RTTEST hTest)
1247{
1248 VBOXHGCMSVCFNTABLE svcTable;
1249 VBOXHGCMSVCHELPERS svcHelpers;
1250 SHFLROOT Root;
1251 RTDIR hDir = (RTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
1252 SHFLHANDLE Handle;
1253 union
1254 {
1255 SHFLDIRINFO DirInfo;
1256 uint8_t abBuffer[sizeof(SHFLDIRINFO) + 2 * sizeof(RTUTF16)];
1257 } Buf;
1258 uint32_t cFiles;
1259 int rc;
1260
1261 RTTestSub(hTest, "List empty directory");
1262 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1263 "/test/mapping", "testname");
1264 g_testRTDirOpen_hDir = hDir;
1265 rc = createFile(&svcTable, Root, "test/dir",
1266 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, &Handle, NULL);
1267 RTTEST_CHECK_RC_OK(hTest, rc);
1268 rc = listDir(&svcTable, Root, Handle, 0, NULL, &Buf.DirInfo, sizeof(Buf), 0, &cFiles);
1269 RTTEST_CHECK_RC(hTest, rc, VERR_NO_MORE_FILES);
1270 RTTEST_CHECK_MSG(hTest, g_testRTDirReadEx_hDir == hDir, (hTest, "Dir=%p\n", g_testRTDirReadEx_hDir));
1271 RTTEST_CHECK_MSG(hTest, cFiles == 0,
1272 (hTest, "cFiles=%llu\n", LLUIFY(cFiles)));
1273 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1274 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1275 AssertReleaseRC(rc);
1276 rc = svcTable.pfnUnload(NULL);
1277 AssertReleaseRC(rc);
1278 RTTestGuardedFree(hTest, svcTable.pvService);
1279 RTTEST_CHECK_MSG(hTest, g_testRTDirClose_hDir == hDir, (hTest, "hDir=%p\n", g_testRTDirClose_hDir));
1280}
1281
1282void testFSInfoQuerySetFMode(RTTEST hTest)
1283{
1284 VBOXHGCMSVCFNTABLE svcTable;
1285 VBOXHGCMSVCHELPERS svcHelpers;
1286 SHFLROOT Root;
1287 const RTFILE hFile = (RTFILE) 0x10000;
1288 const uint32_t fMode = 0660;
1289 SHFLFSOBJINFO Info;
1290 int rc;
1291
1292 RTTestSub(hTest, "Query and set file size");
1293 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1294 "/test/mapping", "testname");
1295 SHFLHANDLE Handle = SHFL_HANDLE_NIL;
1296 g_testRTFileOpen_hFile = hFile;
1297 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1298 &Handle, NULL);
1299 RTTEST_CHECK_RC_OK_RETV(hTest, rc);
1300
1301 RT_ZERO(Info);
1302 g_testRTFileQueryInfo_fMode = fMode;
1303 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1304 &Info);
1305 RTTEST_CHECK_RC_OK(hTest, rc);
1306 RTTEST_CHECK_MSG(hTest, g_testRTFileQueryInfo_hFile == hFile, (hTest, "File=%u\n", g_testRTFileQueryInfo_hFile));
1307 RTTEST_CHECK_MSG(hTest, Info.Attr.fMode == fMode,
1308 (hTest, "cbObject=%llu\n", LLUIFY(Info.cbObject)));
1309 RT_ZERO(Info);
1310 Info.Attr.fMode = fMode;
1311 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1312 sizeof(Info), &Info);
1313 RTTEST_CHECK_RC_OK(hTest, rc);
1314 RTTEST_CHECK_MSG(hTest, g_testRTFileSet_fMode == fMode,
1315 (hTest, "Size=%llu\n", LLUIFY(g_testRTFileSet_fMode)));
1316 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1317 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1318 AssertReleaseRC(rc);
1319 rc = svcTable.pfnUnload(NULL);
1320 AssertReleaseRC(rc);
1321 RTTestGuardedFree(hTest, svcTable.pvService);
1322 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile, (hTest, "File=%u\n", g_testRTFileClose_hFile));
1323}
1324
1325void testFSInfoQuerySetDirATime(RTTEST hTest)
1326{
1327 VBOXHGCMSVCFNTABLE svcTable;
1328 VBOXHGCMSVCHELPERS svcHelpers;
1329 SHFLROOT Root;
1330 const RTDIR hDir = (RTDIR)&g_aTestDirHandles[g_iNextDirHandle++ % RT_ELEMENTS(g_aTestDirHandles)];
1331 const int64_t ccAtimeNano = 100000;
1332 SHFLFSOBJINFO Info;
1333 SHFLHANDLE Handle;
1334 int rc;
1335
1336 RTTestSub(hTest, "Query and set directory atime");
1337 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1338 "/test/mapping", "testname");
1339 g_testRTDirOpen_hDir = hDir;
1340 rc = createFile(&svcTable, Root, "test/dir",
1341 SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, &Handle, NULL);
1342 RTTEST_CHECK_RC_OK(hTest, rc);
1343 RT_ZERO(Info);
1344 RTTimeSpecSetNano(&g_testRTDirQueryInfo_ATime, ccAtimeNano);
1345 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1346 &Info);
1347 RTTEST_CHECK_RC_OK(hTest, rc);
1348 RTTEST_CHECK_MSG(hTest, g_testRTDirQueryInfo_hDir == hDir, (hTest, "Dir=%p\n", g_testRTDirQueryInfo_hDir));
1349 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&Info.AccessTime) == ccAtimeNano,
1350 (hTest, "ATime=%llu\n",
1351 LLUIFY(RTTimeSpecGetNano(&Info.AccessTime))));
1352 RT_ZERO(Info);
1353 RTTimeSpecSetNano(&Info.AccessTime, ccAtimeNano);
1354 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1355 sizeof(Info), &Info);
1356 RTTEST_CHECK_RC_OK(hTest, rc);
1357 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&g_testRTDirSetTimes_ATime)
1358 == ccAtimeNano,
1359 (hTest, "ATime=%llu\n",
1360 LLUIFY(RTTimeSpecGetNano(&g_testRTDirSetTimes_ATime))));
1361 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1362 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1363 AssertReleaseRC(rc);
1364 rc = svcTable.pfnUnload(NULL);
1365 AssertReleaseRC(rc);
1366 RTTestGuardedFree(hTest, svcTable.pvService);
1367 RTTEST_CHECK_MSG(hTest, g_testRTDirClose_hDir == hDir, (hTest, "hDir=%p\n", g_testRTDirClose_hDir));
1368}
1369
1370void testFSInfoQuerySetFileATime(RTTEST hTest)
1371{
1372 VBOXHGCMSVCFNTABLE svcTable;
1373 VBOXHGCMSVCHELPERS svcHelpers;
1374 SHFLROOT Root;
1375 const RTFILE hFile = (RTFILE) 0x10000;
1376 const int64_t ccAtimeNano = 100000;
1377 SHFLFSOBJINFO Info;
1378 SHFLHANDLE Handle;
1379 int rc;
1380
1381 RTTestSub(hTest, "Query and set file atime");
1382 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1383 "/test/mapping", "testname");
1384 g_testRTFileOpen_hFile = hFile;
1385 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1386 &Handle, NULL);
1387 RTTEST_CHECK_RC_OK(hTest, rc);
1388 RT_ZERO(Info);
1389 RTTimeSpecSetNano(&g_testRTFileQueryInfo_ATime, ccAtimeNano);
1390 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info),
1391 &Info);
1392 RTTEST_CHECK_RC_OK(hTest, rc);
1393 RTTEST_CHECK_MSG(hTest, g_testRTFileQueryInfo_hFile == hFile, (hTest, "File=%u\n", g_testRTFileQueryInfo_hFile));
1394 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&Info.AccessTime) == ccAtimeNano,
1395 (hTest, "ATime=%llu\n",
1396 LLUIFY(RTTimeSpecGetNano(&Info.AccessTime))));
1397 RT_ZERO(Info);
1398 RTTimeSpecSetNano(&Info.AccessTime, ccAtimeNano);
1399 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
1400 sizeof(Info), &Info);
1401 RTTEST_CHECK_RC_OK(hTest, rc);
1402 RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&g_testRTFileSetTimes_ATime)
1403 == ccAtimeNano,
1404 (hTest, "ATime=%llu\n",
1405 LLUIFY(RTTimeSpecGetNano(&g_testRTFileSetTimes_ATime))));
1406 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1407 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1408 AssertReleaseRC(rc);
1409 rc = svcTable.pfnUnload(NULL);
1410 AssertReleaseRC(rc);
1411 RTTestGuardedFree(hTest, svcTable.pvService);
1412 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile, (hTest, "File=%u\n", g_testRTFileClose_hFile));
1413}
1414
1415void testFSInfoQuerySetEndOfFile(RTTEST hTest)
1416{
1417 VBOXHGCMSVCFNTABLE svcTable;
1418 VBOXHGCMSVCHELPERS svcHelpers;
1419 SHFLROOT Root;
1420 const RTFILE hFile = (RTFILE) 0x10000;
1421 const RTFOFF cbNew = 50000;
1422 SHFLFSOBJINFO Info;
1423 SHFLHANDLE Handle;
1424 int rc;
1425
1426 RTTestSub(hTest, "Set end of file position");
1427 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1428 "/test/mapping", "testname");
1429 g_testRTFileOpen_hFile = hFile;
1430 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1431 &Handle, NULL);
1432 RTTEST_CHECK_RC_OK(hTest, rc);
1433 RT_ZERO(Info);
1434 Info.cbObject = cbNew;
1435 rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_SIZE,
1436 sizeof(Info), &Info);
1437 RTTEST_CHECK_RC_OK(hTest, rc);
1438 RTTEST_CHECK_MSG(hTest, g_testRTFileSetSize_hFile == hFile, (hTest, "File=%u\n", g_testRTFileSetSize_hFile));
1439 RTTEST_CHECK_MSG(hTest, g_testRTFileSetSize_cbSize == cbNew,
1440 (hTest, "Size=%llu\n", LLUIFY(g_testRTFileSetSize_cbSize)));
1441 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1442 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1443 AssertReleaseRC(rc);
1444 rc = svcTable.pfnUnload(NULL);
1445 AssertReleaseRC(rc);
1446 RTTestGuardedFree(hTest, svcTable.pvService);
1447 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile, (hTest, "File=%u\n", g_testRTFileClose_hFile));
1448}
1449
1450void testLockFileSimple(RTTEST hTest)
1451{
1452 VBOXHGCMSVCFNTABLE svcTable;
1453 VBOXHGCMSVCHELPERS svcHelpers;
1454 SHFLROOT Root;
1455 const RTFILE hFile = (RTFILE) 0x10000;
1456 const int64_t offLock = 50000;
1457 const uint64_t cbLock = 4000;
1458 SHFLHANDLE Handle;
1459 int rc;
1460
1461 RTTestSub(hTest, "Simple file lock and unlock");
1462 Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers,
1463 "/test/mapping", "testname");
1464 g_testRTFileOpen_hFile = hFile;
1465 rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ,
1466 &Handle, NULL);
1467 RTTEST_CHECK_RC_OK(hTest, rc);
1468 rc = lockFile(&svcTable, Root, Handle, offLock, cbLock, SHFL_LOCK_SHARED);
1469 RTTEST_CHECK_RC_OK(hTest, rc);
1470#ifdef RT_OS_WINDOWS /* Locking is a no-op elsewhere. */
1471 RTTEST_CHECK_MSG(hTest, g_testRTFileLock_hFile == hFile, (hTest, "File=%u\n", g_testRTFileLock_hFile));
1472 RTTEST_CHECK_MSG(hTest, g_testRTFileLock_fLock == 0,
1473 (hTest, "fLock=%u\n", g_testRTFileLock_fLock));
1474 RTTEST_CHECK_MSG(hTest, g_testRTFileLock_offLock == offLock,
1475 (hTest, "Offs=%llu\n", (long long) g_testRTFileLock_offLock));
1476 RTTEST_CHECK_MSG(hTest, g_testRTFileLock_cbLock == cbLock,
1477 (hTest, "Size=%llu\n", LLUIFY(g_testRTFileLock_cbLock)));
1478#endif
1479 rc = lockFile(&svcTable, Root, Handle, offLock, cbLock, SHFL_LOCK_CANCEL);
1480 RTTEST_CHECK_RC_OK(hTest, rc);
1481#ifdef RT_OS_WINDOWS
1482 RTTEST_CHECK_MSG(hTest, g_testRTFileUnlock_hFile == hFile, (hTest, "File=%u\n", g_testRTFileUnlock_hFile));
1483 RTTEST_CHECK_MSG(hTest, g_testRTFileUnlock_offLock == offLock,
1484 (hTest, "Offs=%llu\n",
1485 (long long) g_testRTFileUnlock_offLock));
1486 RTTEST_CHECK_MSG(hTest, g_testRTFileUnlock_cbLock == cbLock,
1487 (hTest, "Size=%llu\n", LLUIFY(g_testRTFileUnlock_cbLock)));
1488#endif
1489 unmapAndRemoveMapping(hTest, &svcTable, Root, "testname");
1490 rc = svcTable.pfnDisconnect(NULL, 0, svcTable.pvService);
1491 AssertReleaseRC(rc);
1492 rc = svcTable.pfnUnload(NULL);
1493 AssertReleaseRC(rc);
1494 RTTestGuardedFree(hTest, svcTable.pvService);
1495 RTTEST_CHECK_MSG(hTest, g_testRTFileClose_hFile == hFile, (hTest, "File=%u\n", g_testRTFileClose_hFile));
1496}
1497
1498
1499/*********************************************************************************************************************************
1500* Main code *
1501*********************************************************************************************************************************/
1502
1503static void testAPI(RTTEST hTest)
1504{
1505 testMappingsQuery(hTest);
1506 testMappingsQueryName(hTest);
1507 testMapFolder(hTest);
1508 testUnmapFolder(hTest);
1509 testCreate(hTest);
1510 testClose(hTest);
1511 testRead(hTest);
1512 testWrite(hTest);
1513 testLock(hTest);
1514 testFlush(hTest);
1515 testDirList(hTest);
1516 testReadLink(hTest);
1517 testFSInfo(hTest);
1518 testRemove(hTest);
1519 testRename(hTest);
1520 testSymlink(hTest);
1521 testMappingsAdd(hTest);
1522 testMappingsRemove(hTest);
1523 /* testSetStatusLed(hTest); */
1524}
1525
1526int main(int argc, char **argv)
1527{
1528 RT_NOREF1(argc);
1529 RTEXITCODE rcExit = RTTestInitAndCreate(RTPathFilename(argv[0]), &g_hTest);
1530 if (rcExit != RTEXITCODE_SUCCESS)
1531 return rcExit;
1532 RTTestBanner(g_hTest);
1533 testAPI(g_hTest);
1534 return RTTestSummaryAndDestroy(g_hTest);
1535}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette