VirtualBox

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

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

Copyright year updates by scm.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 61.7 KB
 
1/* $Id: tstSharedFolderService.cpp 106061 2024-09-16 14:03:52Z 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-2024 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