VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/testcase/vditool.cpp@ 33000

Last change on this file since 33000 was 32536, checked in by vboxsync, 14 years ago

Storage/VBoxHDD: replace custom open flags with regular IPRT file open flags, introduce user-providable filesystem access interface, eliminate dependency on PGM geometry structure, change pvBuffer/cbBuffer parameter ordering to the usual conventions, eliminate the remains of the old I/O code, make more plugin methods optional to reduce redundancy, lots of cleanups

Storage/DrvVD+testcases,Main/Medium+Frontends: adapt to VBoxHDD changes, logging fixes

Storage/VDI+VMDK+DMG+Raw+VHD+Parallels+VCI: made as similar to each other as possible, added inline VFS wrappers to improve readability, full VFS support, VDI files are now 4K aligned, eliminate the remains of the old I/O code, various more or less severe bugfixes, code sort

Storage/iSCSI: support disks bigger than 2T, streamline the code to be more similar to the file-based backends, memory leak fix, error code usage like file-based backends, code sort

log+err: added new error codes/log groups and eliminated unused old ones

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.4 KB
Line 
1/** @file
2 *
3 * VBox HDD container maintenance/conversion utility
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#include <VBox/VBoxHDD.h>
22#include <iprt/alloc.h>
23#include <iprt/file.h>
24#include <iprt/stream.h>
25#include <iprt/string.h>
26#include <iprt/initterm.h>
27#include <VBox/err.h>
28#include <VBox/log.h>
29
30#include <stdlib.h>
31
32
33
34static void ascii2upper(char *psz)
35{
36 for (;*psz; psz++)
37 if (*psz >= 'a' && *psz <= 'z')
38 *psz += 'A' - 'a';
39}
40
41static int UsageExit()
42{
43 RTPrintf("Usage: vditool <Command> [Params]\n"
44 "Commands and params:\n"
45 " NEW Filename Mbytes - create new image\n"
46#if 0
47 " DD Filename DDFilename - create new image from DD format image\n"
48 " CONVERT Filename - convert VDI image from old format\n"
49 " DUMP Filename - debug dump\n"
50 " RESETGEO Filename - reset geometry information\n"
51 " COPY FromImage ToImage - make image copy\n"
52 " COPYDD FromImage DDFilename - make a DD copy of the image\n"
53 " SHRINK Filename - optimize (reduce) VDI image size\n"
54#endif
55 );
56 return 1;
57}
58
59static int SyntaxError(const char *pszMsg)
60{
61 RTPrintf("Syntax error: %s\n\n", pszMsg);
62 UsageExit();
63 return 1;
64}
65
66/**
67 * Our internal functions use UTF8
68 */
69static int FilenameToUtf8(char **pszUtf8Filename, const char *pszFilename)
70{
71 int rc = RTStrCurrentCPToUtf8(pszUtf8Filename, pszFilename);
72 if (RT_FAILURE(rc))
73 RTPrintf("Error converting filename '%s' to UTF8! (rc=%Rrc)\n",
74 pszFilename, rc);
75 return rc;
76}
77
78/**
79 * Prints a done message indicating success or failure.
80 * @returns rc
81 * @param rc Status code.
82 */
83static int PrintDone(int rc)
84{
85 if (rc == VINF_SUCCESS)
86 RTPrintf("The operation completed successfully!\n");
87 else if (RT_SUCCESS(rc))
88 RTPrintf("The operation completed successfully! (rc=%Rrc)\n", rc);
89 else
90 RTPrintf("FAILURE: %Rrf (%Rrc)\n", rc, rc);
91 return rc;
92}
93
94static int NewImage(const char *pszFilename, uint32_t cMBs)
95{
96 RTPrintf("Creating VDI: file=\"%s\" size=%u MB...\n",
97 pszFilename, cMBs);
98
99 /* translate argv[] to UTF8 */
100 char *pszUtf8Filename;
101 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
102 if (RT_FAILURE(rc))
103 return rc;
104
105 PVBOXHDD hdd;
106 rc = VDCreate(NULL, &hdd);
107 if (RT_FAILURE(rc))
108 return PrintDone(rc);
109
110 VDGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */
111 rc = VDCreateBase(hdd, "vdi", pszUtf8Filename,
112 (uint64_t)cMBs * _1M,
113 VD_IMAGE_FLAGS_NONE,
114 "Newly created test image",
115 &geo, &geo, NULL,
116 VD_OPEN_FLAGS_NORMAL,
117 NULL, NULL);
118 return PrintDone(rc);
119}
120
121#if 0
122static int ConvertDDImage(const char *pszFilename, const char *pszDDFilename)
123{
124 RTPrintf("Converting VDI: from DD image file=\"%s\" to file=\"%s\"...\n",
125 pszDDFilename, pszFilename);
126
127 /* translate argv[] to UTF8 */
128 char *pszUtf8Filename, *pszUtf8DDFilename;
129 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
130 if (RT_FAILURE(rc))
131 return rc;
132 rc = FilenameToUtf8(&pszUtf8DDFilename, pszDDFilename);
133 if (RT_FAILURE(rc))
134 return rc;
135
136 /* open raw image file. */
137 RTFILE File;
138 rc = RTFileOpen(&File, pszUtf8DDFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
139 if (RT_FAILURE(rc))
140 {
141 RTPrintf("File=\"%s\" open error: %Rrf\n", pszDDFilename, rc);
142 return rc;
143 }
144
145 /* get image size. */
146 uint64_t cbFile;
147 rc = RTFileGetSize(File, &cbFile);
148 if (RT_SUCCESS(rc))
149 {
150 RTPrintf("Creating fixed image with size %u Bytes...\n", (unsigned)cbFile);
151 rc = VDICreateBaseImage(pszUtf8Filename,
152 VDI_IMAGE_TYPE_FIXED,
153 cbFile,
154 "Converted from DD test image", NULL, NULL);
155 PrintDone(rc);
156 if (RT_SUCCESS(rc))
157 {
158 RTPrintf("Writing data...\n");
159 PVDIDISK pVdi = VDIDiskCreate();
160 rc = VDIDiskOpenImage(pVdi, pszUtf8Filename, VDI_OPEN_FLAGS_NORMAL);
161 if (RT_SUCCESS(rc))
162 {
163 /* alloc work buffer. */
164 void *pvBuf = RTMemAlloc(VDIDiskGetBufferSize(pVdi));
165 if (pvBuf)
166 {
167 uint64_t off = 0;
168 while (off < cbFile)
169 {
170 size_t cbRead = 0;
171 rc = RTFileRead(File, pvBuf, VDIDiskGetBufferSize(pVdi), &cbRead);
172 if (RT_FAILURE(rc) || !cbRead)
173 break;
174 rc = VDIDiskWrite(pVdi, off, pvBuf, cbRead);
175 if (RT_FAILURE(rc))
176 break;
177 off += cbRead;
178 }
179
180 RTMemFree(pvBuf);
181 }
182 else
183 rc = VERR_NO_MEMORY;
184
185 VDIDiskCloseImage(pVdi);
186 }
187
188 if (RT_FAILURE(rc))
189 {
190 /* delete image on error */
191 VDIDeleteImage(pszUtf8Filename);
192 }
193 PrintDone(rc);
194 }
195 }
196 RTFileClose(File);
197
198 return rc;
199}
200#endif
201
202#if 0
203static DECLCALLBACK(int) ProcessCallback(PVM pVM, unsigned uPercent, void *pvUser)
204{
205 unsigned *pPercent = (unsigned *)pvUser;
206
207 if (*pPercent != uPercent)
208 {
209 *pPercent = uPercent;
210 RTPrintf(".");
211 if ((uPercent % 10) == 0 && uPercent)
212 RTPrintf("%d%%", uPercent);
213 RTStrmFlush(g_pStdOut);
214 }
215
216 return VINF_SUCCESS;
217}
218#endif
219
220#if 0
221static int ConvertOldImage(const char *pszFilename)
222{
223 RTPrintf("Converting VDI image file=\"%s\" to a new format...\n"
224 "progress: 0%%",
225 pszFilename);
226
227 /* translate argv[] to UTF8 */
228 char *pszUtf8Filename;
229 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
230 if (RT_FAILURE(rc))
231 return rc;
232
233 unsigned uPercent = 0;
234 rc = VDIConvertImage(pszUtf8Filename, ProcessCallback, &uPercent);
235 RTPrintf("\n");
236 return PrintDone(rc);
237}
238#endif
239
240#if 0
241static int DumpImage(const char *pszFilename)
242{
243 RTPrintf("Dumping VDI image file=\"%s\" into the log file...\n", pszFilename);
244 PVDIDISK pVdi = VDIDiskCreate();
245
246 /* translate argv[] to UTF8 */
247 char *pszUtf8Filename;
248 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
249 if (RT_FAILURE(rc))
250 return rc;
251 rc = VDIDiskOpenImage(pVdi, pszUtf8Filename, VDI_OPEN_FLAGS_READONLY);
252 if (RT_SUCCESS(rc))
253 {
254 VDIDiskDumpImages(pVdi);
255 VDIDiskCloseAllImages(pVdi);
256 }
257 return PrintDone(rc);
258}
259#endif
260
261#if 0
262static int ResetImageGeometry(const char *pszFilename)
263{
264 RTPrintf("Resetting geometry info of VDI image file=\"%s\"\n", pszFilename);
265 PVDIDISK pVdi = VDIDiskCreate();
266
267 /* translate argv[] to UTF8 */
268 char *pszUtf8Filename;
269 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
270 if (RT_FAILURE(rc))
271 return rc;
272
273 rc = VDIDiskOpenImage(pVdi, pszUtf8Filename, VDI_OPEN_FLAGS_NORMAL);
274 if (RT_SUCCESS(rc))
275 {
276 VDGEOMETRY LCHSGeometry = {0, 0, 0};
277 rc = VDIDiskSetLCHSGeometry(pVdi, &LCHSGeometry);
278 }
279 VDIDiskCloseImage(pVdi);
280 return PrintDone(rc);
281}
282#endif
283
284#if 0
285static int CopyImage(const char *pszDstFile, const char *pszSrcFile)
286{
287 RTPrintf("Copying VDI image file=\"%s\" to image file=\"%s\"...\n"
288 "progress: 0%%",
289 pszSrcFile, pszDstFile);
290
291 /* translate argv[] to UTF8 */
292 char *pszUtf8SrcFile, *pszUtf8DstFile;
293 int rc = FilenameToUtf8(&pszUtf8SrcFile, pszSrcFile);
294 if (RT_FAILURE(rc))
295 return rc;
296 rc = FilenameToUtf8(&pszUtf8DstFile, pszDstFile);
297 if (RT_FAILURE(rc))
298 return rc;
299
300 unsigned uPrecent = 0;
301 rc = VDICopyImage(pszUtf8DstFile, pszUtf8SrcFile, NULL, ProcessCallback, &uPrecent);
302 RTPrintf("\n");
303 return PrintDone(rc);
304}
305#endif
306
307#if 0
308static int CopyToDD(const char *pszDstFile, const char *pszSrcFile)
309{
310 RTPrintf("Copying VDI image file=\"%s\" to DD file=\"%s\"...\n",
311 pszSrcFile, pszDstFile);
312 PVDIDISK pVdi = VDIDiskCreate();
313
314 /* translate argv[] to UTF8 */
315 char *pszUtf8SrcFile, *pszUtf8DstFile;
316 int rc = FilenameToUtf8(&pszUtf8SrcFile, pszSrcFile);
317 if (RT_FAILURE(rc))
318 return rc;
319 rc = FilenameToUtf8(&pszUtf8DstFile, pszDstFile);
320 if (RT_FAILURE(rc))
321 return rc;
322
323 rc = VDIDiskOpenImage(pVdi, pszUtf8SrcFile, VDI_OPEN_FLAGS_NORMAL);
324 if (RT_SUCCESS(rc))
325 {
326 RTFILE FileDst;
327 rc = RTFileOpen(&FileDst, pszUtf8DstFile, RTFILE_O_CREATE | RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE);
328 if (RT_SUCCESS(rc))
329 {
330 uint64_t cbSrc = VDIDiskGetSize(pVdi);
331 const unsigned cbBuf = VDIDiskGetBlockSize(pVdi); /* or perhaps VDIDiskGetBufferSize(pVdi)? */
332 void *pvBuf = RTMemAlloc(cbBuf);
333 if (pvBuf)
334 {
335 uint64_t off = 0;
336 while (off < cbSrc)
337 {
338 rc = VDIDiskRead(pVdi, off, pvBuf, cbBuf);
339 if (RT_FAILURE(rc))
340 break;
341 rc = RTFileWrite(FileDst, pvBuf, cbBuf, NULL);
342 if (RT_FAILURE(rc))
343 break;
344 off += cbBuf;
345 }
346 RTMemFree(pvBuf);
347 }
348 RTFileClose(FileDst);
349 }
350 }
351 VDIDiskCloseImage(pVdi);
352 return PrintDone(rc);
353}
354#endif
355
356#if 0
357static int ShrinkImage(const char *pszFilename)
358{
359 RTPrintf("Shrinking VDI image file=\"%s\"...\n"
360 "progress: 0%%",
361 pszFilename);
362
363 /* translate argv[] to UTF8 */
364 char *pszUtf8Filename;
365 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
366 if (RT_FAILURE(rc))
367 return rc;
368
369 unsigned uPrecent;
370 rc = VDIShrinkImage(pszUtf8Filename, ProcessCallback, &uPrecent);
371 RTPrintf("\n");
372 return PrintDone(rc);
373}
374#endif
375
376int main(int argc, char **argv)
377{
378 putenv((char*)"VBOX_LOG_DEST=stdout");
379 putenv((char*)"VBOX_LOG_FLAGS=");
380
381 RTR3Init();
382 RTPrintf("vditool -- for internal use only!\n"
383 "Copyright (c) 2009 Oracle Corporation\n\n");
384
385 /*
386 * Do cmd line parsing.
387 */
388 if (argc < 2)
389 return UsageExit();
390
391 char szCmd[16];
392 if (strlen(argv[1]) >= sizeof(szCmd))
393 return SyntaxError("Invalid command!");
394 strcpy(szCmd, argv[1]);
395 ascii2upper(szCmd);
396
397 PRTLOGGER pLogger;
398 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
399 int rc = RTLogCreate(&pLogger, 0, "all",
400 NULL, RT_ELEMENTS(s_apszGroups), s_apszGroups,
401 RTLOGDEST_STDOUT, NULL);
402 RTLogRelSetDefaultInstance(pLogger);
403
404 if (strcmp(szCmd, "NEW") == 0)
405 {
406 if (argc != 4)
407 return SyntaxError("Invalid argument count!");
408
409 uint32_t cMBs;
410 rc = RTStrToUInt32Ex(argv[3], NULL, 10, &cMBs);
411 if (RT_FAILURE(rc))
412 return SyntaxError("Invalid number!");
413 if (cMBs < 2 || cMBs > _1M)
414 {
415 RTPrintf("error: Disk size %RU32 (MB) is not within the range %u-%u!\n",
416 cMBs, 2, _1M);
417 return 1;
418 }
419
420 rc = NewImage(argv[2], cMBs);
421 }
422#if 0
423 else if (strcmp(szCmd, "DD") == 0)
424 {
425 if (argc != 4)
426 return SyntaxError("Invalid argument count!");
427 rc = ConvertDDImage(argv[2], argv[3]);
428 }
429 else if (strcmp(szCmd, "CONVERT") == 0)
430 {
431 if (argc != 3)
432 return SyntaxError("Invalid argument count!");
433 rc = ConvertOldImage(argv[2]);
434 }
435 else if (strcmp(szCmd, "DUMP") == 0)
436 {
437 if (argc != 3)
438 return SyntaxError("Invalid argument count!");
439 rc = DumpImage(argv[2]);
440 }
441 else if (strcmp(szCmd, "RESETGEO") == 0)
442 {
443 if (argc != 3)
444 return SyntaxError("Invalid argument count!");
445 rc = ResetImageGeometry(argv[2]);
446 }
447 else if (strcmp(szCmd, "COPY") == 0)
448 {
449 if (argc != 4)
450 return SyntaxError("Invalid argument count!");
451 rc = CopyImage(argv[3], argv[2]);
452 }
453 else if (strcmp(szCmd, "COPYDD") == 0)
454 {
455 if (argc != 4)
456 return SyntaxError("Invalid argument count!");
457 rc = CopyToDD(argv[3], argv[2]);
458 }
459 else if (strcmp(szCmd, "SHRINK") == 0)
460 {
461 if (argc != 3)
462 return SyntaxError("Invalid argument count!");
463 rc = ShrinkImage(argv[2]);
464 }
465#endif
466 else
467 return SyntaxError("Invalid command!");
468
469 RTLogFlush(NULL);
470 return !RT_SUCCESS(rc);
471}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use