VirtualBox

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

Last change on this file since 16873 was 14831, checked in by vboxsync, 16 years ago

whole bunch: avoid runtime.h, include individual headers indead.

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