VirtualBox

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

Last change on this file was 79110, checked in by vboxsync, 5 years ago

os2/VBoxSF: Forgot to set fpGEAList to NULL when full EAs are queried. FC/2 paniced the guest copying files off shared folder.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.6 KB
Line 
1/** $Id: VBoxSFUtil.cpp 79110 2019-06-13 00:17:25Z 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 <bird-src-spam@anduin.net>
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.fpGEA2List = (PGEA2LIST)0xfefefef7;
335 EaOp.fpFEA2List = &u.FeaList;
336 EaOp.oError = 0;
337 memset(&u, '\0', sizeof(u));
338 u.FeaList.cbList = sizeof(u);
339 rc = DosQueryPathInfo(argv[i], 4, &EaOp, sizeof(EaOp));
340 printf("%s: FIL_QUERYALLEAS/4 -> %u\n", argv[i], rc);
341 if (rc == NO_ERROR)
342 printf(" Lvl4: FeaList.cbList=%#lx oError=%#lx\n", u.FeaList.cbList, EaOp.oError);
343
344 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
345 EaOp.fpFEA2List = &u.FeaList;
346 EaOp.oError = 0;
347 memset(&u, '\0', sizeof(u));
348 u.FeaList.cbList = sizeof(u);
349 rc = DosQueryPathInfo(argv[i], 14, &EaOp, sizeof(EaOp));
350 if (rc != ERROR_INVALID_LEVEL)
351 printf("%s: FIL_QUERYALLEASL/14 -> %u\n", argv[i], rc);
352
353 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
354 EaOp.fpFEA2List = &u.FeaList;
355 EaOp.oError = 0;
356 memset(&u, '\0', sizeof(u));
357 u.FeaList.cbList = sizeof(u);
358 rc = DosQueryPathInfo(argv[i], 8, &EaOp, sizeof(EaOp));
359 printf("%s: FIL_QUERYALLEAS/8 -> %u\n", argv[i], rc);
360 if (rc == NO_ERROR)
361 printf(" Lvl8: FeaList.cbList=%#lx oError=%#lx\n", u.FeaList.cbList, EaOp.oError);
362
363 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
364 EaOp.fpFEA2List = &u.FeaList;
365 EaOp.oError = 0;
366 memset(&u, '\0', sizeof(u));
367 u.FeaList.cbList = sizeof(u);
368 rc = DosQueryPathInfo(argv[i], 18, &EaOp, sizeof(EaOp));
369 if (rc != ERROR_INVALID_LEVEL)
370 printf("%s: FIL_QUERYALLEASL/18 -> %u\n", argv[i], rc);
371
372 EaOp.fpGEA2List = (PGEA2LIST)memcpy(&Gea2List, &Gea2ListOrg, sizeof(Gea2List));
373 EaOp.fpFEA2List = &u.FeaList;
374 EaOp.oError = 0;
375 memset(&u, '\0', sizeof(u));
376 u.FeaList.cbList = sizeof(u);
377 rc = DosQueryPathInfo(argv[i], 15, &EaOp, sizeof(EaOp));
378 if (rc != ERROR_INVALID_LEVEL)
379 printf("%s: FIL_QUERYALLEASL/15 -> %u\n", argv[i], rc);
380
381 memset(&u, '\0', sizeof(u));
382 rc = DosQueryPathInfo(argv[i], 0, &u, sizeof(u));
383 if (rc != ERROR_INVALID_LEVEL)
384 printf("%s: 0 -> %u\n", argv[i], rc);
385 }
386 return 0;
387}
388
389
390int vboxSfOs2UtilFindFile(int argc, char **argv)
391{
392 unsigned cMaxMatches = 1;
393 unsigned cbBuf = 1024;
394 unsigned uLevel = FIL_STANDARDL;
395 unsigned fAttribs = FILE_DIRECTORY | FILE_HIDDEN | FILE_SYSTEM;
396 bool fOptions = true;
397
398 uint8_t *pbBuf = NULL;
399 for (int i = 1; i < argc; i++)
400 {
401 const char *pszArg = argv[i];
402
403 /*
404 * Deal with options.
405 */
406 if (fOptions && *pszArg == '-')
407 {
408 pszArg++;
409 if (*pszArg == '-')
410 {
411 pszArg++;
412 if (!*pszArg)
413 {
414 fOptions = false;
415 continue;
416 }
417 if (strcmp(pszArg, "attribs") == 0)
418 pszArg = "a";
419 else if (strcmp(pszArg, "buffer-size") == 0)
420 pszArg = "b";
421 else if (strcmp(pszArg, "level") == 0)
422 pszArg = "l";
423 else if (strcmp(pszArg, "matches") == 0)
424 pszArg = "m";
425 else if (strcmp(pszArg, "help") == 0)
426 pszArg = "h";
427 else
428 return syntaxError("Unknown option: %s\n", argv[i]);
429 }
430 do
431 {
432 const char *pszValue = NULL;
433 char chOpt = *pszArg++;
434 if (strchr("ablm", chOpt) != NULL)
435 {
436 if (*pszArg != '\0')
437 pszValue = *pszArg == ':' || *pszArg == '=' ? ++pszArg : pszArg;
438 else if (i + 1 < argc)
439 pszValue = argv[++i];
440 else
441 return syntaxError("-%c takes a value\n", chOpt);
442 pszArg = "";
443 }
444 switch (chOpt)
445 {
446 case 'a':
447 fAttribs = atoi(pszValue);
448 break;
449 case 'b':
450 cbBuf = atoi(pszValue);
451 free(pbBuf);
452 pbBuf = NULL;
453 break;
454 case 'l':
455 uLevel = atoi(pszValue);
456 break;
457 case 'm':
458 cMaxMatches = atoi(pszValue);
459 break;
460 case 'h':
461 printf("usage: findfile [-a|--attribs <mask>] [-b|--buffer-size <bytes>]\n"
462 " [-l|--level <num>] [-m|--matches <num>] [--] <dir1> [dir2..N]\n");
463 return 0;
464 default:
465 return syntaxError("Unknown option '%c' (%s)\n", chOpt, argv[i - (pszValue != NULL)]);
466 }
467
468 } while (pszArg && *pszArg != '\0');
469 }
470 else
471 {
472 /*
473 * Search the specified directory/whatever.
474 */
475 if (!pbBuf)
476 {
477 pbBuf = (uint8_t *)malloc(cbBuf);
478 if (!pbBuf)
479 return error("out of memory (cbBuf=%#x)\n", cbBuf);
480 }
481
482 HDIR hDir = HDIR_CREATE;
483 ULONG cMatches = cMaxMatches;
484 memset(pbBuf, 0xf6, cbBuf);
485 APIRET rc = DosFindFirst(pszArg, &hDir, fAttribs, pbBuf, cbBuf, &cMatches, uLevel);
486 printf("DosFindFirst -> %lu hDir=%#lx cMatches=%#lx\n", rc, hDir, cMatches);
487 if (rc == NO_ERROR)
488 {
489 do
490 {
491 uint8_t *pbTmp = pbBuf;
492 for (uint32_t iMatch = 0; iMatch < cMatches; iMatch++)
493 {
494 uint32_t offNext = *(uint32_t *)pbTmp;
495 switch (uLevel)
496 {
497 case FIL_STANDARD:
498 {
499 PFILEFINDBUF3 pBuf = (PFILEFINDBUF3)pbTmp;
500 printf("#%u: nx=%#lx sz=%#lx at=%#lx nm=%#x:%s\n",
501 iMatch, pBuf->oNextEntryOffset, pBuf->cbFile, pBuf->attrFile, pBuf->cchName, pBuf->achName);
502 if (strlen(pBuf->achName) != pBuf->cchName)
503 printf("Bad name length!\n");
504 break;
505 }
506 case FIL_STANDARDL:
507 {
508 PFILEFINDBUF3L pBuf = (PFILEFINDBUF3L)pbTmp;
509 printf("#%u: nx=%#lx sz=%#llx at=%#lx nm=%#x:%s\n",
510 iMatch, pBuf->oNextEntryOffset, pBuf->cbFile, pBuf->attrFile, pBuf->cchName, pBuf->achName);
511 if (strlen(pBuf->achName) != pBuf->cchName)
512 printf("Bad name length!\n");
513 break;
514 }
515 case FIL_QUERYEASIZE:
516 {
517 PFILEFINDBUF4 pBuf = (PFILEFINDBUF4)pbTmp;
518 printf("#%u: nx=%#lx sz=%#lx at=%#lx nm=%#x:%s\n",
519 iMatch, pBuf->oNextEntryOffset, pBuf->cbFile, pBuf->attrFile, pBuf->cchName, pBuf->achName);
520 if (strlen(pBuf->achName) != pBuf->cchName)
521 printf("Bad name length!\n");
522 break;
523 }
524 case FIL_QUERYEASIZEL:
525 {
526 PFILEFINDBUF4L pBuf = (PFILEFINDBUF4L)pbTmp;
527 printf("#%u: nx=%#lx sz=%#llx at=%#lx nm=%#x:%s\n",
528 iMatch, pBuf->oNextEntryOffset, pBuf->cbFile, pBuf->attrFile, pBuf->cchName, pBuf->achName);
529 if (strlen(pBuf->achName) != pBuf->cchName)
530 printf("Bad name length!\n");
531 break;
532 }
533
534 }
535
536 pbTmp += offNext;
537 }
538
539 /* Next bunch. */
540 memset(pbBuf, 0xf6, cbBuf);
541 cMatches = cMaxMatches;
542 rc = DosFindNext(hDir, pbBuf, cbBuf, &cMatches);
543 printf("DosFindNext -> %lu hDir=%#lx cMatches=%#lx\n", rc, hDir, cMatches);
544 } while (rc == NO_ERROR);
545
546 rc = DosFindClose(hDir);
547 printf("DosFindClose -> %lu\n", rc);
548 }
549 }
550 }
551 return 0;
552}
553
554
555static int vboxSfOs2UtilMkDir(int argc, char **argv)
556{
557 for (int i = 1; i < argc; i++)
558 {
559 APIRET rc = DosCreateDir(argv[i], NULL);
560 printf("DosCreateDir -> %lu for '%s'\n", rc, argv[i]);
561 }
562 return 0;
563}
564
565
566static int vboxSfOs2UtilBenchFStat(int argc, char **argv)
567{
568 int rcRet = 0;
569 bool fOptions = true;
570 unsigned msRuntime = 5*1000;
571 for (int i = 1; i < argc; i++)
572 {
573 /*
574 * Parse arguments.
575 */
576 const char *pszArg = argv[i];
577 if (*pszArg == '-' && fOptions)
578 {
579 if (*++pszArg == '-')
580 {
581 pszArg++;
582 if (*pszArg == '\0')
583 {
584 fOptions = false;
585 continue;
586 }
587 if (strcmp(pszArg, "runtime") == 0)
588 pszArg = "r";
589 else if (strcmp(pszArg, "help") == 0)
590 pszArg = "h";
591 else
592 return syntaxError("Unknown option: %s", argv[i]);
593 }
594
595 while (*pszArg != '\0')
596 {
597 char chOpt = *pszArg++;
598 const char *pszValue = NULL;
599 if (chOpt == 'r')
600 {
601 if (*pszArg != '\0')
602 {
603 pszValue = *pszArg == ':' || *pszArg == '=' ? pszArg + 1 : pszArg;
604 pszArg = "";
605 }
606 else if (i + 1 < argc)
607 pszValue = argv[++i];
608 else
609 return syntaxError("Expected value after -%c.", chOpt);
610 }
611 switch (chOpt)
612 {
613 case 'r':
614 msRuntime = atoi(pszValue);
615 break;
616
617 default:
618 return syntaxError("Unknown option: -%c", chOpt);
619 }
620 }
621 }
622 /*
623 * Run tests on the file.
624 */
625 else
626 {
627 ULONG ulAction = 0;
628 HFILE hFile = NULLHANDLE;
629 APIRET rc = DosOpen(pszArg, &hFile, &ulAction, 0 /*cbFile*/, FILE_NORMAL,
630 OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
631 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | OPEN_FLAGS_FAIL_ON_ERROR, NULL /*pEaBuf*/);
632 if (rc == NO_ERROR)
633 {
634 /* Do a test run. */
635 FILESTATUS3 Info;
636 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &Info, sizeof(Info));
637 if (rc == NO_ERROR)
638 {
639 printf("Testing '%s'...\n", pszArg);
640
641 /* Tread water till the microsecond count changes. */
642 ULONG msStart = g_pGInfoSeg->msecs;
643 while (g_pGInfoSeg->msecs == msStart)
644 { /* nothing */ }
645
646 /* Do the actual testing. */
647 msStart = g_pGInfoSeg->msecs;
648 ULONG cCalls = 0;
649 uint64_t cTscElapsed = ASMReadTSC();
650 do
651 {
652 cCalls++;
653 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &Info, sizeof(Info));
654 } while (rc == NO_ERROR && g_pGInfoSeg->msecs - msStart < msRuntime );
655 cTscElapsed = ASMReadTSC() - cTscElapsed;
656
657 if (rc == NO_ERROR)
658 printf("%7lu calls in %14lu ms - %6llu ns per call\n"
659 "%7lu calls in %14llu ticks - %6llu ticks per call\n",
660 cCalls, msRuntime, msRuntime * (uint64_t)1000000 / cCalls,
661 cCalls, cTscElapsed, cTscElapsed / cCalls);
662 else
663 rcRet = error("DosQueryFileInfo failed on '%s' after %u calls: %u", pszArg, cCalls, rc);
664 }
665 else
666 rcRet = error("DosQueryFileInfo failed on '%s': %u", pszArg, rc);
667 DosClose(hFile);
668 }
669 else
670 rcRet = error("DosOpen failed on '%s': %u", pszArg, rc);
671 }
672 }
673 return rcRet;
674}
675
676
677int main(int argc, char **argv)
678{
679 g_pGInfoSeg = GETGINFOSEG();
680 DosGetInfoBlocks(&g_pTib, &g_pPib);
681
682 /*
683 * Parse input.
684 */
685 for (int i = 1; i < argc; i++)
686 {
687 const char *pszArg = argv[i];
688 if (strcmp(pszArg, "use") == 0)
689 return vboxSfOs2UtilUse(argc - i, argv + i);
690 if (strcmp(pszArg, "qpathinfo") == 0)
691 return vboxSfOs2UtilQPathInfo(argc - i, argv + i);
692 if (strcmp(pszArg, "findfile") == 0)
693 return vboxSfOs2UtilFindFile(argc - i, argv + i);
694 if (strcmp(pszArg, "mkdir") == 0)
695 return vboxSfOs2UtilMkDir(argc - i, argv + i);
696 if (strcmp(pszArg, "benchfstat") == 0)
697 return vboxSfOs2UtilBenchFStat(argc - i, argv + i);
698
699 fprintf(stderr, "Unknown command/option: %s\n", pszArg);
700 return 2;
701 }
702 fprintf(stderr,
703 "usage: VBoxSFUtil.exe use [drive] [shared-folder]\n"
704 " or VBoxSFUtil.exe unuse [drive|shared-folder] [..]\n"
705 " or VBoxSFUtil.exe list\n");
706 return 2;
707}
708
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use