VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedFolders/testcase/tstShflCase.cpp@ 103285

Last change on this file since 103285 was 103285, checked in by vboxsync, 13 months ago

Re-applied r161549 again (Got rid of a lot of deprecated strcpy / strcat calls; now using the IPRT pendants (found by Parfait)), left out some stuff which wasn't wanted, less bloated version of DrvAudio.cpp. bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.0 KB
Line 
1/** @file
2 * Testcase for shared folder case conversion code.
3 *
4 * @todo r=andy Testcase needs to be rewritten using the test framework.
5 * Otherwise it's almost pointless to run this on the testboxes.
6 */
7
8/*
9 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
10 *
11 * This file is part of VirtualBox base platform packages, as
12 * available from https://www.virtualbox.org.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation, in version 3 of the
17 * License.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <https://www.gnu.org/licenses>.
26 *
27 * SPDX-License-Identifier: GPL-3.0-only
28 */
29
30
31/*********************************************************************************************************************************
32* Header Files *
33*********************************************************************************************************************************/
34#define LOG_GROUP LOG_GROUP_MISC
35#define LOG_ENABLED
36#include <VBox/shflsvc.h>
37#include <VBox/log.h>
38#include <iprt/assert.h>
39#include <iprt/err.h>
40#include <iprt/file.h>
41#include <iprt/fs.h>
42#include <iprt/dir.h>
43#include <iprt/initterm.h>
44#include <iprt/mem.h>
45#include <iprt/path.h>
46#include <iprt/string.h>
47#include <iprt/test.h>
48#include <iprt/uni.h>
49#include <stdio.h>
50
51
52/*********************************************************************************************************************************
53* Defined Constants And Macros *
54*********************************************************************************************************************************/
55/* Override slash for non-windows hosts. */
56#undef RTPATH_DELIMITER
57#define RTPATH_DELIMITER '\\'
58
59/* Use our own RTPath and RTDir methods. */
60#define RTPathQueryInfo rtPathQueryInfo
61#define RTDirOpenFiltered rtDirOpenFiltered
62#define RTDirClose rtDirClose
63#define RTDirReadEx rtDirReadEx
64
65
66/*********************************************************************************************************************************
67* Global Variables *
68*********************************************************************************************************************************/
69static int iDirList = 0;
70static int iDirFile = 0;
71
72static const char *g_apszDirs[] =
73{
74 "c:",
75 "c:\\test dir",
76 "c:\\test dir\\SUBDIR",
77};
78
79static const char *g_apszDirsC[] =
80{
81 ".",
82 "..",
83 "test dir"
84};
85
86static const char *g_apszTestdirEntries[] =
87{
88 ".",
89 "..",
90 "SUBDIR",
91 "a.bat",
92 "aTestJe.bat",
93 "aTestje.bat",
94 "b.bat",
95 "c.bat",
96 "d.bat",
97 "e.bat",
98 "f.bat",
99 "g.bat",
100 "h.bat",
101 "x.bat",
102 "z.bat",
103};
104
105static const char *g_apszSUBDIREntries[] =
106{
107 ".",
108 "..",
109 "a.bat",
110 "aTestJe.bat",
111 "aTestje.bat",
112 "b.bat",
113 "c.bat",
114 "d.bat",
115 "e.bat",
116 "f.bat",
117 "g.bat",
118 "h.bat",
119 "x.bat",
120 "z.bat",
121};
122
123static int rtDirOpenFiltered(RTDIR *phDir, const char *pszPath, RTDIRFILTER enmFilter, uint32_t fFlags)
124{
125 RT_NOREF2(enmFilter, fFlags);
126 if (!strcmp(pszPath, "c:\\*"))
127 iDirList = 1;
128 else if (!strcmp(pszPath, "c:\\test dir\\*"))
129 iDirList = 2;
130 else if (!strcmp(pszPath, "c:\\test dir\\SUBDIR\\*"))
131 iDirList = 3;
132 else
133 AssertFailed();
134
135 *phDir = (RTDIR)1;
136 return VINF_SUCCESS;
137}
138
139static int rtDirClose(RTDIR hDir)
140{
141 RT_NOREF1(hDir);
142 iDirFile = 0;
143 return VINF_SUCCESS;
144}
145
146static int rtDirReadEx(RTDIR hDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
147{
148 RT_NOREF4(hDir, pcbDirEntry, enmAdditionalAttribs, fFlags);
149 switch (iDirList)
150 {
151 case 1:
152 if (iDirFile == RT_ELEMENTS(g_apszDirsC))
153 return VERR_NO_MORE_FILES;
154 pDirEntry->cbName = (uint16_t)strlen(g_apszDirsC[iDirFile]);
155 strcpy(pDirEntry->szName, g_apszDirsC[iDirFile++]);
156 break;
157 case 2:
158 if (iDirFile == RT_ELEMENTS(g_apszTestdirEntries))
159 return VERR_NO_MORE_FILES;
160 pDirEntry->cbName = (uint16_t)strlen(g_apszTestdirEntries[iDirFile]);
161 strcpy(pDirEntry->szName, g_apszTestdirEntries[iDirFile++]);
162 break;
163 case 3:
164 if (iDirFile == RT_ELEMENTS(g_apszSUBDIREntries))
165 return VERR_NO_MORE_FILES;
166 pDirEntry->cbName = (uint16_t)strlen(g_apszSUBDIREntries[iDirFile]);
167 strcpy(pDirEntry->szName, g_apszSUBDIREntries[iDirFile++]);
168 break;
169 }
170 return VINF_SUCCESS;
171}
172
173static int rtPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
174{
175 RT_NOREF2(pObjInfo, enmAdditionalAttribs);
176 int cMax;
177
178 /* first try g_apszDirs */
179 for (unsigned int i=0;i<RT_ELEMENTS(g_apszDirs);i++)
180 {
181 if(!strcmp(pszPath, g_apszDirs[i]))
182 return VINF_SUCCESS;
183 }
184
185 const char **papszDirList;
186 switch (iDirList)
187 {
188 case 1:
189 cMax = RT_ELEMENTS(g_apszDirsC);
190 papszDirList = g_apszDirsC;
191 break;
192 case 2:
193 cMax = RT_ELEMENTS(g_apszTestdirEntries);
194 papszDirList = g_apszTestdirEntries;
195 break;
196 case 3:
197 cMax = RT_ELEMENTS(g_apszSUBDIREntries);
198 papszDirList = g_apszSUBDIREntries;
199 break;
200 default:
201 return VERR_FILE_NOT_FOUND;
202 }
203 for (int i = 0; i < cMax; i++)
204 {
205 if (!strcmp(pszPath, papszDirList[i]))
206 return VINF_SUCCESS;
207 }
208 return VERR_FILE_NOT_FOUND;
209}
210
211static int vbsfCorrectCasing(char *pszFullPath, char *pszStartComponent, size_t cbStartComponent)
212{
213 PRTDIRENTRYEX pDirEntry = NULL;
214 uint32_t cbDirEntry;
215 size_t cbComponent;
216 int rc = VERR_FILE_NOT_FOUND;
217 RTDIR hSearch = NIL_RTDIR;
218 char szWildCard[4];
219
220 Log2(("vbsfCorrectCasing: %s %s\n", pszFullPath, pszStartComponent));
221
222 cbComponent = strlen(pszStartComponent);
223
224 cbDirEntry = 4096;
225 pDirEntry = (PRTDIRENTRYEX)RTMemAlloc(cbDirEntry);
226 if (pDirEntry == 0)
227 {
228 AssertFailed();
229 return VERR_NO_MEMORY;
230 }
231
232 /** @todo this is quite inefficient, especially for directories with many files */
233 Assert(pszFullPath < pszStartComponent-1);
234 Assert(*(pszStartComponent-1) == RTPATH_DELIMITER);
235 *(pszStartComponent-1) = 0;
236 rc = RTStrCopy(pDirEntry->szName, sizeof(pDirEntry->szName), pszFullPath);
237 if (RT_FAILURE(rc))
238 goto end;
239 szWildCard[0] = RTPATH_DELIMITER;
240 szWildCard[1] = '*';
241 szWildCard[2] = 0;
242 rc = RTStrCat(pDirEntry->szName, sizeof(pDirEntry->szName), szWildCard);
243 if (RT_FAILURE(rc))
244 goto end;
245 rc = RTDirOpenFiltered(&hSearch, pDirEntry->szName, RTDIRFILTER_WINNT, 0 /*fFlags*/);
246 *(pszStartComponent-1) = RTPATH_DELIMITER;
247 if (RT_FAILURE(rc))
248 goto end;
249
250 for(;;)
251 {
252 size_t cbDirEntrySize = cbDirEntry;
253
254 rc = RTDirReadEx(hSearch, pDirEntry, &cbDirEntrySize, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
255 if (rc == VERR_NO_MORE_FILES)
256 break;
257
258 if (VINF_SUCCESS != rc && rc != VWRN_NO_DIRENT_INFO)
259 {
260 AssertFailed();
261 if (rc != VERR_NO_TRANSLATION)
262 break;
263 else
264 continue;
265 }
266
267 Log2(("vbsfCorrectCasing: found %s\n", &pDirEntry->szName[0]));
268 if ( pDirEntry->cbName == cbComponent
269 && !RTStrICmp(pszStartComponent, &pDirEntry->szName[0]))
270 {
271 Log(("Found original name %s (%s)\n", &pDirEntry->szName[0], pszStartComponent));
272 rc = RTStrCopy(pszStartComponent, cbStartComponent, &pDirEntry->szName[0]);
273 break;
274 }
275 }
276 if (RT_FAILURE(rc))
277 Log(("vbsfCorrectCasing %s failed with %d\n", pszStartComponent, rc));
278
279end:
280 if (pDirEntry)
281 RTMemFree(pDirEntry);
282
283 if (hSearch)
284 RTDirClose(hSearch);
285 return rc;
286}
287
288
289
290static int testCase(char *pszFullPath, size_t cbFullPath, bool fWildCard = false)
291{
292 int rc;
293 RTFSOBJINFO info;
294 char *pszWildCardComponent = NULL;
295
296 if (fWildCard)
297 {
298 /* strip off the last path component, that contains the wildcard(s) */
299 size_t cchLlen = strlen(pszFullPath);
300 char *pszSrc = pszFullPath + cchLlen - 1;
301
302 while(pszSrc > pszFullPath)
303 {
304 if (*pszSrc == RTPATH_DELIMITER)
305 break;
306 pszSrc--;
307 }
308 if (*pszSrc == RTPATH_DELIMITER)
309 {
310 bool fHaveWildcards = false;
311 char *temp = pszSrc;
312
313 while(*temp)
314 {
315 char uc = *temp;
316 /** @todo should depend on the guest OS */
317 if (uc == '*' || uc == '?' || uc == '>' || uc == '<' || uc == '"')
318 {
319 fHaveWildcards = true;
320 break;
321 }
322 temp++;
323 }
324
325 if (fHaveWildcards)
326 {
327 pszWildCardComponent = pszSrc;
328 *pszWildCardComponent = 0;
329 }
330 }
331 }
332
333 rc = RTPathQueryInfo(pszFullPath, &info, RTFSOBJATTRADD_NOTHING);
334 if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND)
335 {
336 size_t cchLen = strlen(pszFullPath);
337 char *pszSrc = pszFullPath + cchLen - 1;
338
339 Log(("Handle case insensitive guest fs on top of host case sensitive fs for %s\n", pszFullPath));
340
341 /* Find partial path that's valid */
342 while(pszSrc > pszFullPath)
343 {
344 if (*pszSrc == RTPATH_DELIMITER)
345 {
346 *pszSrc = 0;
347 rc = RTPathQueryInfo (pszFullPath, &info, RTFSOBJATTRADD_NOTHING);
348 *pszSrc = RTPATH_DELIMITER;
349 if (rc == VINF_SUCCESS)
350 {
351#ifdef DEBUG
352 *pszSrc = 0;
353 Log(("Found valid partial path %s\n", pszFullPath));
354 *pszSrc = RTPATH_DELIMITER;
355#endif
356 break;
357 }
358 }
359
360 pszSrc--;
361 }
362 Assert(*pszSrc == RTPATH_DELIMITER && RT_SUCCESS(rc));
363 if ( *pszSrc == RTPATH_DELIMITER
364 && RT_SUCCESS(rc))
365 {
366 pszSrc++;
367 for(;;)
368 {
369 char *end = pszSrc;
370 bool fEndOfString = true;
371
372 while(*end)
373 {
374 if (*end == RTPATH_DELIMITER)
375 break;
376 end++;
377 }
378
379 if (*end == RTPATH_DELIMITER)
380 {
381 fEndOfString = false;
382 *end = 0;
383 rc = RTPathQueryInfo(pszSrc, &info, RTFSOBJATTRADD_NOTHING);
384 Assert(rc == VINF_SUCCESS || rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND);
385 }
386 else
387 if (end == pszSrc)
388 rc = VINF_SUCCESS; /* trailing delimiter */
389 else
390 rc = VERR_FILE_NOT_FOUND;
391
392 if (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND)
393 {
394 /* path component is invalid; try to correct the casing */
395 rc = vbsfCorrectCasing(pszFullPath, pszSrc, cbFullPath - (pszFullPath - pszSrc));
396 if (RT_FAILURE(rc))
397 {
398 if (!fEndOfString)
399 *end = RTPATH_DELIMITER;
400 break;
401 }
402 }
403
404 if (fEndOfString)
405 break;
406
407 *end = RTPATH_DELIMITER;
408 pszSrc = end + 1;
409 }
410 if (RT_FAILURE(rc))
411 Log(("Unable to find suitable component rc=%d\n", rc));
412 }
413 else
414 rc = VERR_FILE_NOT_FOUND;
415
416 }
417 if (pszWildCardComponent)
418 *pszWildCardComponent = RTPATH_DELIMITER;
419
420 if (RT_SUCCESS(rc))
421 Log(("New valid path %s\n", pszFullPath));
422 else
423 Log(("Old invalid path %s\n", pszFullPath));
424 return rc;
425}
426
427
428int main()
429{
430 char szTest[128];
431
432 RTR3InitExeNoArguments(0);
433 RTLogFlush(NULL);
434 RTLogDestinations(NULL, "stdout");
435 RTLogGroupSettings(NULL, "misc=~0");
436 RTLogFlags(NULL, "unbuffered");
437
438 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\test Dir\\z.bAt"));
439 testCase(szTest, sizeof(szTest));
440 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\test dir\\z.bAt"));
441 testCase(szTest, sizeof(szTest));
442 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\test dir\\SUBDIR\\z.bAt"));
443 testCase(szTest, sizeof(szTest));
444 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\test dir\\SUBDiR\\atestje.bat"));
445 testCase(szTest, sizeof(szTest));
446 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\TEST dir\\subDiR\\aTestje.baT"));
447 testCase(szTest, sizeof(szTest));
448 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\TEST dir\\subDiR\\*"));
449 testCase(szTest, sizeof(szTest), true);
450 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\TEST dir\\subDiR\\"));
451 testCase(szTest ,sizeof(szTest), true);
452 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\test dir\\SUBDIR\\"));
453 testCase(szTest, sizeof(szTest));
454 RTTESTI_CHECK_RC_OK(RTStrCopy(szTest, sizeof(szTest), "c:\\test dir\\invalid\\SUBDIR\\test.bat"));
455 testCase(szTest, sizeof(szTest));
456 return 0;
457}
458
Note: See TracBrowser for help on using the repository browser.

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