VirtualBox

source: vbox/trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFUtil.cpp@ 78425

Last change on this file since 78425 was 75542, checked in by vboxsync, 6 years ago

os2/VBoxSF: Extended VBoxSFUtil with a simple fstat() benchmark.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.5 KB
Line 
1/** $Id: VBoxSFUtil.cpp 75542 2018-11-17 03:56:04Z vboxsync $ */
2/** @file
3 * VBoxSF - OS/2 Shared Folders, Utility for attaching and testing.
4 */
5
6/*
7 * Copyright (c) 2016-2018 knut st. osmundsen <[email protected]>
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include <string.h>
36#include <stdarg.h>
37#include <stdio.h>
38#include <stdint.h>
39#include <stdlib.h>
40#define INCL_BASE
41#define INCL_DOSINFOSEG
42#define OS2EMX_PLAIN_CHAR
43#include <os2.h>
44#include <iprt/asm-amd64-x86.h>
45
46
47/*********************************************************************************************************************************
48* Internal Functions *
49*********************************************************************************************************************************/
50extern "C" APIRET __cdecl CallDosQFileMode(const char *pszFilename, PUSHORT pfAttr, ULONG ulReserved);
51
52#ifndef GETGINFOSEG
53typedef struct _GINFOSEG
54{
55 ULONG time;
56 ULONG msecs;
57 UCHAR hour;
58 UCHAR minutes;
59 UCHAR seconds;
60 UCHAR hundredths;
61 USHORT timezone;
62 USHORT cusecTimerInterval;
63 UCHAR day;
64 UCHAR month;
65 USHORT year;
66 UCHAR weekday;
67 UCHAR uchMajorVersion;
68 UCHAR uchMinorVersion;
69 UCHAR chRevisionLetter;
70 UCHAR sgCurrent;
71 UCHAR sgMax;
72 UCHAR cHugeShift;
73 UCHAR fProtectModeOnly;
74 USHORT pidForeground;
75 UCHAR fDynamicSched;
76 UCHAR csecMaxWait;
77 USHORT cmsecMinSlice;
78 USHORT cmsecMaxSlice;
79 USHORT bootdrive;
80 UCHAR amecRAS[32];
81 UCHAR csgWindowableVioMax;
82 UCHAR csgPMMax;
83 USHORT SIS_Syslog;
84 USHORT SIS_MMIOBase;
85 USHORT SIS_MMIOAddr;
86 UCHAR SIS_MaxVDMs;
87 UCHAR SIS_Reserved;
88} GINFOSEG;
89typedef GINFOSEG *PGINFOSEG;
90
91extern "C" void _System DOS16GLOBALINFO(void);
92# define GETGINFOSEG() ((PGINFOSEG)(void *)(((unsigned)&DOS16GLOBALINFO & 0xfff8) << 13))
93
94#endif
95
96
97/*********************************************************************************************************************************
98* Global Variables *
99*********************************************************************************************************************************/
100static GINFOSEG volatile *g_pGInfoSeg;
101static PTIB g_pTib;
102static PPIB g_pPib;
103
104
105static int syntaxError(const char *pszFormat, ...)
106{
107 fprintf(stderr, "syntax error: ");
108 va_list va;
109 va_start(va, pszFormat);
110 vfprintf(stderr, pszFormat, va);
111 va_end(va);
112 if (strchr(pszFormat, '\0')[-1] != '\n')
113 fputc('\n', stderr);
114 return 2;
115}
116
117
118static int error(const char *pszFormat, ...)
119{
120 fprintf(stderr, "error: ");
121 va_list va;
122 va_start(va, pszFormat);
123 vfprintf(stderr, pszFormat, va);
124 va_end(va);
125 if (strchr(pszFormat, '\0')[-1] != '\n')
126 fputc('\n', stderr);
127 return 1;
128}
129
130
131int vboxSfOs2UtilUse(int argc, char **argv)
132{
133 /*
134 * Continue parsing.
135 */
136 if (argc != 3)
137 return syntaxError("Expected three arguments to 'use' command\n");
138
139 /* The drive letter. */
140 const char *pszDrive = argv[1];
141 if ( ( (pszDrive[0] >= 'A' && pszDrive[0] <= 'Z')
142 || (pszDrive[0] >= 'a' && pszDrive[0] <= 'z'))
143 && pszDrive[1] == ':'
144 && pszDrive[2] == '\0')
145 { /* likely */ }
146 else
147 return syntaxError("Invalid drive specification '%s', expected something like 'K:'.\n", pszDrive);
148
149 /* The shared folder. */
150 const char *pszFolder = argv[2];
151 size_t cchFolder = strlen(pszFolder);
152 if (cchFolder <= 80 && cchFolder != 0)
153 { /* likely */ }
154 else
155 return syntaxError("Shared folder name '%s' is too %s!\n", pszFolder, cchFolder >= 1 ? "long" : "short");
156
157 /*
158 * Try attach it.
159 */
160 APIRET rc = DosFSAttach(pszDrive, "VBOXSF", (void *)pszFolder, cchFolder + 1, FS_ATTACH);
161 if (rc == NO_ERROR)
162 {
163 printf("done\n");
164 return 0;
165 }
166 return error("DosFSAttach failed: %lu\n", rc);
167}
168
169
170int vboxSfOs2UtilQPathInfo(int argc, char **argv)
171{
172 for (int i = 1; i < argc; i++)
173 {
174 union
175 {
176 USHORT fAttribs;
177 FILESTATUS Lvl1r1;
178 FILESTATUS3 Lvl1r3;
179 FILESTATUS3L Lvl11;
180 FILESTATUS2 Lvl2r2;
181 FILESTATUS4 Lvl2r4;
182 FILESTATUS4L Lvl12;
183 FEA2LIST FeaList;
184 char szFullName[260];
185 //char szTest1[sizeof(FILESTATUS3) == sizeof(FILESTATUS)];
186 //char szTest2[sizeof(FILESTATUS4) == sizeof(FILESTATUS2)];
187 } u;
188
189 u.fAttribs = 0xffff;
190 int rc = CallDosQFileMode(argv[i], &u.fAttribs, 0 /* reserved */);
191 printf("%s: DosQFileMode -> %u, %#x\n", argv[i], rc, u.fAttribs);
192
193 memset(&u, 0xaa, sizeof(u));
194 rc = DosQueryPathInfo(argv[i], FIL_STANDARD, &u.Lvl1r1, sizeof(u.Lvl1r1));
195 printf("%s: FIL_STANDARD/%#x -> %u\n", argv[i], sizeof(u.Lvl1r1), rc);
196#define D(x) (*(uint16_t *)&(x))
197#define T(x) (*(uint16_t *)&(x))
198 if (rc == NO_ERROR)
199 {
200 printf(" Lvl1r1: creation=%u:%u write=%u:%u access=%u:%u\n",
201 D(u.Lvl1r1.fdateCreation), T(u.Lvl1r1.ftimeCreation), D(u.Lvl1r1.fdateLastWrite), T(u.Lvl1r1.ftimeLastWrite),
202 D(u.Lvl1r1.fdateLastAccess), T(u.Lvl1r1.ftimeLastAccess));
203 printf(" Lvl1r1: attrib=%#x size=%lu alloc=%lu\n", u.Lvl1r1.attrFile, u.Lvl1r1.cbFile, u.Lvl1r1.cbFileAlloc);
204
205 }
206
207 memset(&u, 0xbb, sizeof(u));
208 rc = DosQueryPathInfo(argv[i], FIL_STANDARD, &u.Lvl1r3, sizeof(u.Lvl1r3));
209 printf("%s: FIL_STANDARD/%#x-> %u\n", argv[i], sizeof(u.Lvl1r3), rc);
210 if (rc == NO_ERROR)
211 {
212 printf(" Lvl1r3: creation=%u:%u write=%u:%u access=%u:%u\n",
213 D(u.Lvl1r3.fdateCreation), T(u.Lvl1r3.ftimeCreation), D(u.Lvl1r3.fdateLastWrite), T(u.Lvl1r3.ftimeLastWrite),
214 D(u.Lvl1r3.fdateLastAccess), T(u.Lvl1r3.ftimeLastAccess));
215 printf(" Lvl1r3: attrib=%#lx size=%lu alloc=%lu\n", u.Lvl1r3.attrFile, u.Lvl1r3.cbFile, u.Lvl1r3.cbFileAlloc);
216
217 }
218
219 memset(&u, 0xdd, sizeof(u));
220 rc = DosQueryPathInfo(argv[i], FIL_STANDARDL, &u.Lvl11, sizeof(u.Lvl11));
221 printf("%s: FIL_STANDARDL/%#x -> %u\n", argv[i], sizeof(u.Lvl11), rc);
222 if (rc == NO_ERROR)
223 {
224 printf(" Lvl11: creation=%u:%u write=%u:%u access=%u:%u\n",
225 D(u.Lvl11.fdateCreation), T(u.Lvl11.ftimeCreation), D(u.Lvl11.fdateLastWrite), T(u.Lvl11.ftimeLastWrite),
226 D(u.Lvl11.fdateLastAccess), T(u.Lvl11.ftimeLastAccess));
227 printf(" Lvl11: attrib=%#lx size=%llu alloc=%llu\n", u.Lvl11.attrFile, u.Lvl11.cbFile, u.Lvl11.cbFileAlloc);
228 }
229
230 memset(&u, 0xee, sizeof(u));
231 rc = DosQueryPathInfo(argv[i], FIL_QUERYEASIZE, &u.Lvl2r2, sizeof(u.Lvl2r2));
232 printf("%s: FIL_QUERYEASIZE/%#x -> %u\n", argv[i], sizeof(u.Lvl2r2), rc);
233 if (rc == NO_ERROR)
234 {
235 printf(" Lvl2: creation=%u:%u write=%u:%u access=%u:%u\n",
236 D(u.Lvl2r2.fdateCreation), T(u.Lvl2r2.ftimeCreation), D(u.Lvl2r2.fdateLastWrite), T(u.Lvl2r2.ftimeLastWrite),
237 D(u.Lvl2r2.fdateLastAccess), T(u.Lvl2r2.ftimeLastAccess));
238 printf(" Lvl2: attrib=%#x size=%lu alloc=%lu cbList=%#lx\n",
239 u.Lvl2r2.attrFile, u.Lvl2r2.cbFile, u.Lvl2r2.cbFileAlloc, u.Lvl2r4.cbList);
240 }
241
242 memset(&u, 0x55, sizeof(u));
243 rc = DosQueryPathInfo(argv[i], FIL_QUERYEASIZE, &u.Lvl2r4, sizeof(u.Lvl2r4));
244 printf("%s: FIL_QUERYEASIZE/%#x -> %u\n", argv[i], sizeof(u.Lvl2r4), rc);
245 if (rc == NO_ERROR)
246 {
247 printf(" Lvl2: creation=%u:%u write=%u:%u access=%u:%u\n",
248 D(u.Lvl2r4.fdateCreation), T(u.Lvl2r4.ftimeCreation), D(u.Lvl2r4.fdateLastWrite), T(u.Lvl2r4.ftimeLastWrite),
249 D(u.Lvl2r4.fdateLastAccess), T(u.Lvl2r4.ftimeLastAccess));
250 printf(" Lvl2: attrib=%#lx size=%lu alloc=%lu cbList=%#lx\n",
251 u.Lvl2r4.attrFile, u.Lvl2r4.cbFile, u.Lvl2r4.cbFileAlloc, u.Lvl2r4.cbList);
252 }
253
254 memset(&u, 0x99, sizeof(u));
255 rc = DosQueryPathInfo(argv[i], FIL_QUERYEASIZEL, &u.Lvl12, sizeof(u.Lvl12));
256 printf("%s: FIL_QUERYEASIZEL/%#x -> %u\n", argv[i], sizeof(u.Lvl12), rc);
257 if (rc == NO_ERROR)
258 {
259 printf(" Lvl12: creation=%u:%u write=%u:%u access=%u:%u\n",
260 D(u.Lvl12.fdateCreation), T(u.Lvl12.ftimeCreation), D(u.Lvl12.fdateLastWrite), T(u.Lvl12.ftimeLastWrite),
261 D(u.Lvl12.fdateLastAccess), T(u.Lvl12.ftimeLastAccess));
262 printf(" Lvl12: attrib=%#lx size=%llu alloc=%llu cbList=%#lx\n",
263 u.Lvl12.attrFile, u.Lvl12.cbFile, u.Lvl12.cbFileAlloc, u.Lvl12.cbList);
264 }
265
266 memset(&u, 0x44, sizeof(u));
267 rc = DosQueryPathInfo(argv[i], FIL_QUERYFULLNAME, &u.szFullName[0], sizeof(u.szFullName));
268 printf("%s: FIL_QUERYFULLNAME -> %u\n", argv[i], rc);
269 if (rc == NO_ERROR)
270 printf(" Lvl5: %s<eol>\n", u.szFullName);
271
272 size_t cchInput = strlen(argv[i]);
273 if (cchInput >= sizeof(u.szFullName))
274 cchInput = sizeof(u.szFullName) - 1;
275
276 /** @todo Cannot get to level 6 thru 32-bit, need 16-bit. DOSCALL1.DLL
277 * chickens out on us. Sigh. */
278 memcpy(u.szFullName, argv[i], cchInput);
279 u.szFullName[0] = '\0';
280 rc = DosQueryPathInfo(argv[i], 6 /*FIL_VERIFY_SYNTAX*/, &u.szFullName[0], sizeof(u.szFullName));
281 printf("%s: FIL_VERIFY_SYNTAX -> %u\n", argv[i], rc);
282 if (rc == NO_ERROR)
283 printf(" Lvl6: %s<eol>\n", u.szFullName);
284
285 memcpy(u.szFullName, argv[i], cchInput);
286 u.szFullName[0] = '\0';
287 rc = DosQueryPathInfo(argv[i], 16 /*FIL_VERIFY_SYNTAX_L*/, &u.szFullName[0], sizeof(u.szFullName));
288 printf("%s: FIL_VERIFY_SYNTAX_L -> %u\n", argv[i], rc);
289 if (rc == NO_ERROR)
290 printf(" Lvl6L: %s<eol>\n", u.szFullName);
291
292 memcpy(u.szFullName, argv[i], cchInput);
293 u.szFullName[0] = '\0';
294 rc = DosQueryPathInfo(argv[i], 7 /*FIL_FIX_CASE*/, &u.szFullName[0], sizeof(u.szFullName));
295 printf("%s: FIL_FIX_CASE -> %u\n", argv[i], rc);
296 if (rc == NO_ERROR)
297 printf(" Lvl7: %s<eol>\n", u.szFullName);
298
299 memcpy(u.szFullName, argv[i], cchInput);
300 u.szFullName[0] = '\0';
301 rc = DosQueryPathInfo(argv[i], 17 /*FIL_FIX_CASE_L*/, &u.szFullName[0], sizeof(u.szFullName));
302 printf("%s: FIL_FIX_CASE_L -> %u\n", argv[i], rc);
303 if (rc == NO_ERROR)
304 printf(" Lvl17: %s<eol>\n", u.szFullName);
305
306 struct
307 {
308 ULONG cbList;
309 ULONG oNext;
310 BYTE cchName;
311 char szName[10];
312 } Gea2List, Gea2ListOrg = { sizeof(Gea2List), 0, sizeof(".LONGNAME") - 1, ".LONGNAME" };
313 EAOP2 EaOp;
314 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
315 EaOp.fpFEA2List = &u.FeaList;
316 EaOp.oError = 0;
317 memset(&u, '\0', sizeof(u));
318 u.FeaList.cbList = sizeof(u);
319 rc = DosQueryPathInfo(argv[i], FIL_QUERYEASFROMLIST, &EaOp, sizeof(EaOp));
320 printf("%s: FIL_QUERYEASFROMLIST -> %u\n", argv[i], rc);
321 if (rc == NO_ERROR)
322 printf(" Lvl3: FeaList.cbList=%#lx oError=%#lx\n", u.FeaList.cbList, EaOp.oError);
323
324 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
325 EaOp.fpFEA2List = &u.FeaList;
326 EaOp.oError = 0;
327 memset(&u, '\0', sizeof(u));
328 u.FeaList.cbList = sizeof(u);
329 rc = DosQueryPathInfo(argv[i], FIL_QUERYEASFROMLISTL, &EaOp, sizeof(EaOp));
330 if (rc != ERROR_INVALID_LEVEL)
331 printf("%s: FIL_QUERYEASFROMLISTL -> %u\n", argv[i], rc);
332
333 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
334 EaOp.fpFEA2List = &u.FeaList;
335 EaOp.oError = 0;
336 memset(&u, '\0', sizeof(u));
337 u.FeaList.cbList = sizeof(u);
338 rc = DosQueryPathInfo(argv[i], 4, &EaOp, sizeof(EaOp));
339 printf("%s: FIL_QUERYALLEAS/4 -> %u\n", argv[i], rc);
340 if (rc == NO_ERROR)
341 printf(" Lvl4: FeaList.cbList=%#lx oError=%#lx\n", u.FeaList.cbList, EaOp.oError);
342
343 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
344 EaOp.fpFEA2List = &u.FeaList;
345 EaOp.oError = 0;
346 memset(&u, '\0', sizeof(u));
347 u.FeaList.cbList = sizeof(u);
348 rc = DosQueryPathInfo(argv[i], 14, &EaOp, sizeof(EaOp));
349 if (rc != ERROR_INVALID_LEVEL)
350 printf("%s: FIL_QUERYALLEASL/14 -> %u\n", argv[i], rc);
351
352 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
353 EaOp.fpFEA2List = &u.FeaList;
354 EaOp.oError = 0;
355 memset(&u, '\0', sizeof(u));
356 u.FeaList.cbList = sizeof(u);
357 rc = DosQueryPathInfo(argv[i], 8, &EaOp, sizeof(EaOp));
358 printf("%s: FIL_QUERYALLEAS/8 -> %u\n", argv[i], rc);
359 if (rc == NO_ERROR)
360 printf(" Lvl8: FeaList.cbList=%#lx oError=%#lx\n", u.FeaList.cbList, EaOp.oError);
361
362 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
363 EaOp.fpFEA2List = &u.FeaList;
364 EaOp.oError = 0;
365 memset(&u, '\0', sizeof(u));
366 u.FeaList.cbList = sizeof(u);
367 rc = DosQueryPathInfo(argv[i], 18, &EaOp, sizeof(EaOp));
368 if (rc != ERROR_INVALID_LEVEL)
369 printf("%s: FIL_QUERYALLEASL/18 -> %u\n", argv[i], rc);
370
371 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
372 EaOp.fpFEA2List = &u.FeaList;
373 EaOp.oError = 0;
374 memset(&u, '\0', sizeof(u));
375 u.FeaList.cbList = sizeof(u);
376 rc = DosQueryPathInfo(argv[i], 15, &EaOp, sizeof(EaOp));
377 if (rc != ERROR_INVALID_LEVEL)
378 printf("%s: FIL_QUERYALLEASL/15 -> %u\n", argv[i], rc);
379
380 memset(&u, '\0', sizeof(u));
381 rc = DosQueryPathInfo(argv[i], 0, &u, sizeof(u));
382 if (rc != ERROR_INVALID_LEVEL)
383 printf("%s: 0 -> %u\n", argv[i], rc);
384 }
385 return 0;
386}
387
388
389int vboxSfOs2UtilFindFile(int argc, char **argv)
390{
391 unsigned cMaxMatches = 1;
392 unsigned cbBuf = 1024;
393 unsigned uLevel = FIL_STANDARDL;
394 unsigned fAttribs = FILE_DIRECTORY | FILE_HIDDEN | FILE_SYSTEM;
395 bool fOptions = true;
396
397 uint8_t *pbBuf = NULL;
398 for (int i = 1; i < argc; i++)
399 {
400 const char *pszArg = argv[i];
401
402 /*
403 * Deal with options.
404 */
405 if (fOptions && *pszArg == '-')
406 {
407 pszArg++;
408 if (*pszArg == '-')
409 {
410 pszArg++;
411 if (!*pszArg)
412 {
413 fOptions = false;
414 continue;
415 }
416 if (strcmp(pszArg, "attribs") == 0)
417 pszArg = "a";
418 else if (strcmp(pszArg, "buffer-size") == 0)
419 pszArg = "b";
420 else if (strcmp(pszArg, "level") == 0)
421 pszArg = "l";
422 else if (strcmp(pszArg, "matches") == 0)
423 pszArg = "m";
424 else if (strcmp(pszArg, "help") == 0)
425 pszArg = "h";
426 else
427 return syntaxError("Unknown option: %s\n", argv[i]);
428 }
429 do
430 {
431 const char *pszValue = NULL;
432 char chOpt = *pszArg++;
433 if (strchr("ablm", chOpt) != NULL)
434 {
435 if (*pszArg != '\0')
436 pszValue = *pszArg == ':' || *pszArg == '=' ? ++pszArg : pszArg;
437 else if (i + 1 < argc)
438 pszValue = argv[++i];
439 else
440 return syntaxError("-%c takes a value\n", chOpt);
441 pszArg = "";
442 }
443 switch (chOpt)
444 {
445 case 'a':
446 fAttribs = atoi(pszValue);
447 break;
448 case 'b':
449 cbBuf = atoi(pszValue);
450 free(pbBuf);
451 pbBuf = NULL;
452 break;
453 case 'l':
454 uLevel = atoi(pszValue);
455 break;
456 case 'm':
457 cMaxMatches = atoi(pszValue);
458 break;
459 case 'h':
460 printf("usage: findfile [-a|--attribs <mask>] [-b|--buffer-size <bytes>]\n"
461 " [-l|--level <num>] [-m|--matches <num>] [--] <dir1> [dir2..N]\n");
462 return 0;
463 default:
464 return syntaxError("Unknown option '%c' (%s)\n", chOpt, argv[i - (pszValue != NULL)]);
465 }
466
467 } while (pszArg && *pszArg != '\0');
468 }
469 else
470 {
471 /*
472 * Search the specified directory/whatever.
473 */
474 if (!pbBuf)
475 {
476 pbBuf = (uint8_t *)malloc(cbBuf);
477 if (!pbBuf)
478 return error("out of memory (cbBuf=%#x)\n", cbBuf);
479 }
480
481 HDIR hDir = HDIR_CREATE;
482 ULONG cMatches = cMaxMatches;
483 memset(pbBuf, 0xf6, cbBuf);
484 APIRET rc = DosFindFirst(pszArg, &hDir, fAttribs, pbBuf, cbBuf, &cMatches, uLevel);
485 printf("DosFindFirst -> %lu hDir=%#lx cMatches=%#lx\n", rc, hDir, cMatches);
486 if (rc == NO_ERROR)
487 {
488 do
489 {
490 uint8_t *pbTmp = pbBuf;
491 for (uint32_t iMatch = 0; iMatch < cMatches; iMatch++)
492 {
493 uint32_t offNext = *(uint32_t *)pbTmp;
494 switch (uLevel)
495 {
496 case FIL_STANDARD:
497 {
498 PFILEFINDBUF3 pBuf = (PFILEFINDBUF3)pbTmp;
499 printf("#%u: nx=%#lx sz=%#lx at=%#lx nm=%#x:%s\n",
500 iMatch, pBuf->oNextEntryOffset, pBuf->cbFile, pBuf->attrFile, pBuf->cchName, pBuf->achName);
501 if (strlen(pBuf->achName) != pBuf->cchName)
502 printf("Bad name length!\n");
503 break;
504 }
505 case FIL_STANDARDL:
506 {
507 PFILEFINDBUF3L pBuf = (PFILEFINDBUF3L)pbTmp;
508 printf("#%u: nx=%#lx sz=%#llx at=%#lx nm=%#x:%s\n",
509 iMatch, pBuf->oNextEntryOffset, pBuf->cbFile, pBuf->attrFile, pBuf->cchName, pBuf->achName);
510 if (strlen(pBuf->achName) != pBuf->cchName)
511 printf("Bad name length!\n");
512 break;
513 }
514 case FIL_QUERYEASIZE:
515 {
516 PFILEFINDBUF4 pBuf = (PFILEFINDBUF4)pbTmp;
517 printf("#%u: nx=%#lx sz=%#lx at=%#lx nm=%#x:%s\n",
518 iMatch, pBuf->oNextEntryOffset, pBuf->cbFile, pBuf->attrFile, pBuf->cchName, pBuf->achName);
519 if (strlen(pBuf->achName) != pBuf->cchName)
520 printf("Bad name length!\n");
521 break;
522 }
523 case FIL_QUERYEASIZEL:
524 {
525 PFILEFINDBUF4L pBuf = (PFILEFINDBUF4L)pbTmp;
526 printf("#%u: nx=%#lx sz=%#llx at=%#lx nm=%#x:%s\n",
527 iMatch, pBuf->oNextEntryOffset, pBuf->cbFile, pBuf->attrFile, pBuf->cchName, pBuf->achName);
528 if (strlen(pBuf->achName) != pBuf->cchName)
529 printf("Bad name length!\n");
530 break;
531 }
532
533 }
534
535 pbTmp += offNext;
536 }
537
538 /* Next bunch. */
539 memset(pbBuf, 0xf6, cbBuf);
540 cMatches = cMaxMatches;
541 rc = DosFindNext(hDir, pbBuf, cbBuf, &cMatches);
542 printf("DosFindNext -> %lu hDir=%#lx cMatches=%#lx\n", rc, hDir, cMatches);
543 } while (rc == NO_ERROR);
544
545 rc = DosFindClose(hDir);
546 printf("DosFindClose -> %lu\n", rc);
547 }
548 }
549 }
550 return 0;
551}
552
553
554static int vboxSfOs2UtilMkDir(int argc, char **argv)
555{
556 for (int i = 1; i < argc; i++)
557 {
558 APIRET rc = DosCreateDir(argv[i], NULL);
559 printf("DosCreateDir -> %lu for '%s'\n", rc, argv[i]);
560 }
561 return 0;
562}
563
564
565static int vboxSfOs2UtilBenchFStat(int argc, char **argv)
566{
567 int rcRet = 0;
568 bool fOptions = true;
569 unsigned msRuntime = 5*1000;
570 for (int i = 1; i < argc; i++)
571 {
572 /*
573 * Parse arguments.
574 */
575 const char *pszArg = argv[i];
576 if (*pszArg == '-' && fOptions)
577 {
578 if (*++pszArg == '-')
579 {
580 pszArg++;
581 if (*pszArg == '\0')
582 {
583 fOptions = false;
584 continue;
585 }
586 if (strcmp(pszArg, "runtime") == 0)
587 pszArg = "r";
588 else if (strcmp(pszArg, "help") == 0)
589 pszArg = "h";
590 else
591 return syntaxError("Unknown option: %s", argv[i]);
592 }
593
594 while (*pszArg != '\0')
595 {
596 char chOpt = *pszArg++;
597 const char *pszValue = NULL;
598 if (chOpt == 'r')
599 {
600 if (*pszArg != '\0')
601 {
602 pszValue = *pszArg == ':' || *pszArg == '=' ? pszArg + 1 : pszArg;
603 pszArg = "";
604 }
605 else if (i + 1 < argc)
606 pszValue = argv[++i];
607 else
608 return syntaxError("Expected value after -%c.", chOpt);
609 }
610 switch (chOpt)
611 {
612 case 'r':
613 msRuntime = atoi(pszValue);
614 break;
615
616 default:
617 return syntaxError("Unknown option: -%c", chOpt);
618 }
619 }
620 }
621 /*
622 * Run tests on the file.
623 */
624 else
625 {
626 ULONG ulAction = 0;
627 HFILE hFile = NULLHANDLE;
628 APIRET rc = DosOpen(pszArg, &hFile, &ulAction, 0 /*cbFile*/, FILE_NORMAL,
629 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
630 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | OPEN_FLAGS_FAIL_ON_ERROR, NULL /*pEaBuf*/);
631 if (rc == NO_ERROR)
632 {
633 /* Do a test run. */
634 FILESTATUS3 Info;
635 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &Info, sizeof(Info));
636 if (rc == NO_ERROR)
637 {
638 printf("Testing '%s'...\n", pszArg);
639
640 /* Tread water till the microsecond count changes. */
641 ULONG msStart = g_pGInfoSeg->msecs;
642 while (g_pGInfoSeg->msecs == msStart)
643 { /* nothing */ }
644
645 /* Do the actual testing. */
646 msStart = g_pGInfoSeg->msecs;
647 ULONG cCalls = 0;
648 uint64_t cTscElapsed = ASMReadTSC();
649 do
650 {
651 cCalls++;
652 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &Info, sizeof(Info));
653 } while (rc == NO_ERROR && g_pGInfoSeg->msecs - msStart < msRuntime );
654 cTscElapsed = ASMReadTSC() - cTscElapsed;
655
656 if (rc == NO_ERROR)
657 printf("%7lu calls in %14lu ms - %6llu ns per call\n"
658 "%7lu calls in %14llu ticks - %6llu ticks per call\n",
659 cCalls, msRuntime, msRuntime * (uint64_t)1000000 / cCalls,
660 cCalls, cTscElapsed, cTscElapsed / cCalls);
661 else
662 rcRet = error("DosQueryFileInfo failed on '%s' after %u calls: %u", pszArg, cCalls, rc);
663 }
664 else
665 rcRet = error("DosQueryFileInfo failed on '%s': %u", pszArg, rc);
666 DosClose(hFile);
667 }
668 else
669 rcRet = error("DosOpen failed on '%s': %u", pszArg, rc);
670 }
671 }
672 return rcRet;
673}
674
675
676int main(int argc, char **argv)
677{
678 g_pGInfoSeg = GETGINFOSEG();
679 DosGetInfoBlocks(&g_pTib, &g_pPib);
680
681 /*
682 * Parse input.
683 */
684 for (int i = 1; i < argc; i++)
685 {
686 const char *pszArg = argv[i];
687 if (strcmp(pszArg, "use") == 0)
688 return vboxSfOs2UtilUse(argc - i, argv + i);
689 if (strcmp(pszArg, "qpathinfo") == 0)
690 return vboxSfOs2UtilQPathInfo(argc - i, argv + i);
691 if (strcmp(pszArg, "findfile") == 0)
692 return vboxSfOs2UtilFindFile(argc - i, argv + i);
693 if (strcmp(pszArg, "mkdir") == 0)
694 return vboxSfOs2UtilMkDir(argc - i, argv + i);
695 if (strcmp(pszArg, "benchfstat") == 0)
696 return vboxSfOs2UtilBenchFStat(argc - i, argv + i);
697
698 fprintf(stderr, "Unknown command/option: %s\n", pszArg);
699 return 2;
700 }
701 fprintf(stderr,
702 "usage: VBoxSFUtil.exe use [drive] [shared-folder]\n"
703 " or VBoxSFUtil.exe unuse [drive|shared-folder] [..]\n"
704 " or VBoxSFUtil.exe list\n");
705 return 2;
706}
707
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