VirtualBox

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

Last change on this file since 3853 was 3779, checked in by vboxsync, 18 years ago

Compile fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/** @file
2 *
3 * VBox HDD container maintenance/conversion utility
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
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/runtime.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 * Prints a done message indicating success or failure.
69 * @returns rc
70 * @param rc Status code.
71 */
72static int PrintDone(int rc)
73{
74 if (rc == VINF_SUCCESS)
75 RTPrintf("The operation completed successfully!\n");
76 else if (VBOX_SUCCESS(rc))
77 RTPrintf("The operation completed successfully! (rc=%Rrc)\n", rc);
78 else
79 RTPrintf("FAILURE: %Rrf (%Rrc)\n", rc, rc);
80 return rc;
81}
82
83static int NewImage(const char *pszFilename, uint32_t cMBs)
84{
85 RTPrintf("Creating VDI: file=\"%s\" size=%u MB...\n",
86 pszFilename, cMBs);
87 int rc = VDICreateBaseImage(pszFilename,
88 VDI_IMAGE_TYPE_NORMAL,
89 (uint64_t)cMBs * (uint64_t)(1024 * 1024),
90 "Newly created test image", NULL, NULL);
91 return PrintDone(rc);
92}
93
94static int ConvertDDImage(const char *pszFilename, const char *pszDDFilename)
95{
96 RTPrintf("Converting VDI: from DD image file=\"%s\" to file=\"%s\"...\n",
97 pszDDFilename, pszFilename);
98
99 /* open raw image file. */
100 RTFILE File;
101 int rc = RTFileOpen(&File, pszDDFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
102 if (VBOX_FAILURE(rc))
103 {
104 RTPrintf("File=\"%s\" open error: %Rrf\n", pszDDFilename, rc);
105 return rc;
106 }
107
108 /* get image size. */
109 uint64_t cbFile;
110 rc = RTFileGetSize(File, &cbFile);
111 if (VBOX_SUCCESS(rc))
112 {
113 RTPrintf("Creating fixed image with size %u Bytes...\n", (unsigned)cbFile);
114 rc = VDICreateBaseImage(pszFilename,
115 VDI_IMAGE_TYPE_FIXED,
116 cbFile,
117 "Converted from DD test image", NULL, NULL);
118 PrintDone(rc);
119 if (VBOX_SUCCESS(rc))
120 {
121 RTPrintf("Writing data...\n");
122 PVDIDISK pVdi = VDIDiskCreate();
123 rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_NORMAL);
124 if (VBOX_SUCCESS(rc))
125 {
126 /* alloc work buffer. */
127 void *pvBuf = RTMemAlloc(VDIDiskGetBufferSize(pVdi));
128 if (pvBuf)
129 {
130 uint64_t off = 0;
131 while (off < cbFile)
132 {
133 unsigned cbRead = 0;
134 rc = RTFileRead(File, pvBuf, VDIDiskGetBufferSize(pVdi), &cbRead);
135 if (VBOX_FAILURE(rc) || !cbRead)
136 break;
137 rc = VDIDiskWrite(pVdi, off, pvBuf, cbRead);
138 if (VBOX_FAILURE(rc))
139 break;
140 off += cbRead;
141 }
142
143 RTMemFree(pvBuf);
144 }
145 else
146 rc = VERR_NO_MEMORY;
147
148 VDIDiskCloseImage(pVdi);
149 }
150
151 if (VBOX_FAILURE(rc))
152 {
153 /* delete image on error */
154 VDIDeleteImage(pszFilename);
155 }
156 PrintDone(rc);
157 }
158 }
159 RTFileClose(File);
160
161 return rc;
162}
163
164static DECLCALLBACK(int) ProcessCallback(PVM pVM, unsigned uPercent, void *pvUser)
165{
166 unsigned *pPercent = (unsigned *)pvUser;
167
168 if (*pPercent != uPercent)
169 {
170 *pPercent = uPercent;
171 RTPrintf(".");
172 if ((uPercent % 10) == 0 && uPercent)
173 RTPrintf("%d%%", uPercent);
174 RTStrmFlush(g_pStdOut);
175 }
176
177 return VINF_SUCCESS;
178}
179
180static int ConvertOldImage(const char *pszFilename)
181{
182 RTPrintf("Converting VDI image file=\"%s\" to a new format...\n"
183 "progress: 0%%",
184 pszFilename);
185 unsigned uPercent = 0;
186 int rc = VDIConvertImage(pszFilename, ProcessCallback, &uPercent);
187 RTPrintf("\n");
188 return PrintDone(rc);
189}
190
191static int DumpImage(const char *pszFilename)
192{
193 RTPrintf("Dumping VDI image file=\"%s\" into the log file...\n", pszFilename);
194 PVDIDISK pVdi = VDIDiskCreate();
195 int rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_READONLY);
196 if (VBOX_SUCCESS(rc))
197 {
198 VDIDiskDumpImages(pVdi);
199 VDIDiskCloseAllImages(pVdi);
200 }
201 return PrintDone(rc);
202}
203
204static int ResetImageGeometry(const char *pszFilename)
205{
206 RTPrintf("Resetting geometry info of VDI image file=\"%s\"\n", pszFilename);
207 PVDIDISK pVdi = VDIDiskCreate();
208 int rc = VDIDiskOpenImage(pVdi, pszFilename, VDI_OPEN_FLAGS_NORMAL);
209 if (VBOX_SUCCESS(rc))
210 {
211 rc = VDIDiskSetGeometry(pVdi, 0, 0, 0);
212 if (VBOX_SUCCESS(rc))
213 rc = VDIDiskSetTranslation(pVdi, PDMBIOSTRANSLATION_AUTO);
214 }
215 VDIDiskCloseImage(pVdi);
216 return PrintDone(rc);
217}
218
219static int CopyImage(const char *pszDstFile, const char *pszSrcFile)
220{
221 RTPrintf("Copying VDI image file=\"%s\" to image file=\"%s\"...\n"
222 "progress: 0%%",
223 pszSrcFile, pszDstFile);
224 unsigned uPrecent = 0;
225 int rc = VDICopyImage(pszDstFile, pszSrcFile, NULL, ProcessCallback, &uPrecent);
226 RTPrintf("\n");
227 return PrintDone(rc);
228}
229
230static int CopyToDD(const char *pszDstFile, const char *pszSrcFile)
231{
232 RTPrintf("Copying VDI image file=\"%s\" to DD file=\"%s\"...\n",
233 pszSrcFile, pszDstFile);
234 PVDIDISK pVdi = VDIDiskCreate();
235 int rc = VDIDiskOpenImage(pVdi, pszSrcFile, VDI_OPEN_FLAGS_NORMAL);
236 if (VBOX_SUCCESS(rc))
237 {
238 RTFILE FileDst;
239 rc = RTFileOpen(&FileDst, pszDstFile, RTFILE_O_CREATE | RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE);
240 if (VBOX_SUCCESS(rc))
241 {
242 uint64_t cbSrc = VDIDiskGetSize(pVdi);
243 const unsigned cbBuf = VDIDiskGetBlockSize(pVdi); /* or perhaps VDIDiskGetBufferSize(pVdi)? */
244 void *pvBuf = RTMemAlloc(cbBuf);
245 if (pvBuf)
246 {
247 uint64_t off = 0;
248 while (off < cbSrc)
249 {
250 rc = VDIDiskRead(pVdi, off, pvBuf, cbBuf);
251 if (VBOX_FAILURE(rc))
252 break;
253 rc = RTFileWrite(FileDst, pvBuf, cbBuf, NULL);
254 if (VBOX_FAILURE(rc))
255 break;
256 off += cbBuf;
257 }
258 RTMemFree(pvBuf);
259 }
260 RTFileClose(FileDst);
261 }
262 }
263 VDIDiskCloseImage(pVdi);
264 return PrintDone(rc);
265}
266
267static int ShrinkImage(const char *pszFilename)
268{
269 RTPrintf("Shrinking VDI image file=\"%s\"...\n"
270 "progress: 0%%",
271 pszFilename);
272 unsigned uPrecent;
273 int rc = VDIShrinkImage(pszFilename, ProcessCallback, &uPrecent);
274 RTPrintf("\n");
275 return PrintDone(rc);
276}
277
278int main(int argc, char **argv)
279{
280 putenv("VBOX_LOG_DEST=stdout");
281 putenv("VBOX_LOG_FLAGS=");
282
283 RTR3Init();
284 RTPrintf("vditool Copyright (c) 2004-2005 innotek GmbH.\n\n");
285
286 /*
287 * Do cmd line parsing.
288 */
289 if (argc < 2)
290 return UsageExit();
291
292 char szCmd[16];
293 if (strlen(argv[1]) >= sizeof(szCmd))
294 return SyntaxError("Invalid command!");
295 strcpy(szCmd, argv[1]);
296 ascii2upper(szCmd);
297
298 PRTLOGGER pLogger;
299 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
300 int rc = RTLogCreate(&pLogger, 0, "all",
301 NULL, ELEMENTS(s_apszGroups), s_apszGroups,
302 RTLOGDEST_STDOUT, NULL);
303 RTLogRelSetDefaultInstance(pLogger);
304
305 if (strcmp(szCmd, "NEW") == 0)
306 {
307 if (argc != 4)
308 return SyntaxError("Invalid argument count!");
309
310 uint32_t cMBs;
311 rc = RTStrToUInt32Ex(argv[3], NULL, 10, &cMBs);
312 if (VBOX_FAILURE(rc))
313 return SyntaxError("Invalid number!");
314 if ( cMBs < 2
315 || cMBs > 1024*1024)
316 {
317 RTPrintf("error: Disk size %RU32 (MB) is not within the range %u-%u!\n",
318 cMBs, 2, 1024*1024);
319 return 1;
320 }
321
322 rc = NewImage(argv[2], cMBs);
323 }
324 else if (strcmp(szCmd, "DD") == 0)
325 {
326 if (argc != 4)
327 return SyntaxError("Invalid argument count!");
328 rc = ConvertDDImage(argv[2], argv[3]);
329 }
330 else if (strcmp(szCmd, "CONVERT") == 0)
331 {
332 if (argc != 3)
333 return SyntaxError("Invalid argument count!");
334 rc = ConvertOldImage(argv[2]);
335 }
336 else if (strcmp(szCmd, "DUMP") == 0)
337 {
338 if (argc != 3)
339 return SyntaxError("Invalid argument count!");
340 rc = DumpImage(argv[2]);
341 }
342 else if (strcmp(szCmd, "RESETGEO") == 0)
343 {
344 if (argc != 3)
345 return SyntaxError("Invalid argument count!");
346 rc = ResetImageGeometry(argv[2]);
347 }
348 else if (strcmp(szCmd, "COPY") == 0)
349 {
350 if (argc != 4)
351 return SyntaxError("Invalid argument count!");
352 rc = CopyImage(argv[3], argv[2]);
353 }
354 else if (strcmp(szCmd, "COPYDD") == 0)
355 {
356 if (argc != 4)
357 return SyntaxError("Invalid argument count!");
358 rc = CopyToDD(argv[3], argv[2]);
359 }
360 else if (strcmp(szCmd, "SHRINK") == 0)
361 {
362 if (argc != 3)
363 return SyntaxError("Invalid argument count!");
364 rc = ShrinkImage(argv[2]);
365 }
366 else
367 return SyntaxError("Invalid command!");
368
369 RTLogFlush(NULL);
370 return !VBOX_SUCCESS(rc);
371}
Note: See TracBrowser for help on using the repository browser.

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