VirtualBox

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

Last change on this file since 55747 was 54574, checked in by vboxsync, 10 years ago

Storage/vditool: copyright

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 KB
Line 
1/** @file
2 *
3 * VBox HDD container maintenance/conversion utility
4 */
5
6/*
7 * Copyright (C) 2006-2011 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/vd.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#include <VBox/version.h>
30
31#include <stdlib.h>
32
33
34
35static void ascii2upper(char *psz)
36{
37 for (;*psz; psz++)
38 if (*psz >= 'a' && *psz <= 'z')
39 *psz += 'A' - 'a';
40}
41
42static int UsageExit()
43{
44 RTPrintf("Usage: vditool <Command> [Params]\n"
45 "Commands and params:\n"
46 " NEW Filename Mbytes - create new image\n"
47#if 0
48 " DD Filename DDFilename - create new image from DD format image\n"
49 " CONVERT Filename - convert VDI image from old format\n"
50 " DUMP Filename - debug dump\n"
51 " RESETGEO Filename - reset geometry information\n"
52 " COPY FromImage ToImage - make image copy\n"
53 " COPYDD FromImage DDFilename - make a DD copy of the image\n"
54 " SHRINK Filename - optimize (reduce) VDI image size\n"
55#endif
56 );
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, uint64_t cMBs)
96{
97 RTPrintf("Creating VDI: file=\"%s\" size=%RU64MB...\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 PVBOXHDD hdd;
107 rc = VDCreate(NULL, VDTYPE_HDD, &hdd);
108 if (RT_FAILURE(rc))
109 return PrintDone(rc);
110
111 VDGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */
112 rc = VDCreateBase(hdd, "vdi", pszUtf8Filename,
113 (uint64_t)cMBs * _1M,
114 VD_IMAGE_FLAGS_NONE,
115 "Newly created test image",
116 &geo, &geo, NULL,
117 VD_OPEN_FLAGS_NORMAL,
118 NULL, NULL);
119 return PrintDone(rc);
120}
121
122#if 0
123static int ConvertDDImage(const char *pszFilename, const char *pszDDFilename)
124{
125 RTPrintf("Converting VDI: from DD image file=\"%s\" to file=\"%s\"...\n",
126 pszDDFilename, pszFilename);
127
128 /* translate argv[] to UTF8 */
129 char *pszUtf8Filename, *pszUtf8DDFilename;
130 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
131 if (RT_FAILURE(rc))
132 return rc;
133 rc = FilenameToUtf8(&pszUtf8DDFilename, pszDDFilename);
134 if (RT_FAILURE(rc))
135 return rc;
136
137 /* open raw image file. */
138 RTFILE File;
139 rc = RTFileOpen(&File, pszUtf8DDFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
140 if (RT_FAILURE(rc))
141 {
142 RTPrintf("File=\"%s\" open error: %Rrf\n", pszDDFilename, rc);
143 return rc;
144 }
145
146 /* get image size. */
147 uint64_t cbFile;
148 rc = RTFileGetSize(File, &cbFile);
149 if (RT_SUCCESS(rc))
150 {
151 RTPrintf("Creating fixed image with size %u Bytes...\n", (unsigned)cbFile);
152 rc = VDICreateBaseImage(pszUtf8Filename,
153 VDI_IMAGE_TYPE_FIXED,
154 cbFile,
155 "Converted from DD test image", NULL, NULL);
156 PrintDone(rc);
157 if (RT_SUCCESS(rc))
158 {
159 RTPrintf("Writing data...\n");
160 PVDIDISK pVdi = VDIDiskCreate();
161 rc = VDIDiskOpenImage(pVdi, pszUtf8Filename, VDI_OPEN_FLAGS_NORMAL);
162 if (RT_SUCCESS(rc))
163 {
164 /* alloc work buffer. */
165 void *pvBuf = RTMemAlloc(VDIDiskGetBufferSize(pVdi));
166 if (pvBuf)
167 {
168 uint64_t off = 0;
169 while (off < cbFile)
170 {
171 size_t cbRead = 0;
172 rc = RTFileRead(File, pvBuf, VDIDiskGetBufferSize(pVdi), &cbRead);
173 if (RT_FAILURE(rc) || !cbRead)
174 break;
175 rc = VDIDiskWrite(pVdi, off, pvBuf, cbRead);
176 if (RT_FAILURE(rc))
177 break;
178 off += cbRead;
179 }
180
181 RTMemFree(pvBuf);
182 }
183 else
184 rc = VERR_NO_MEMORY;
185
186 VDIDiskCloseImage(pVdi);
187 }
188
189 if (RT_FAILURE(rc))
190 {
191 /* delete image on error */
192 VDIDeleteImage(pszUtf8Filename);
193 }
194 PrintDone(rc);
195 }
196 }
197 RTFileClose(File);
198
199 return rc;
200}
201#endif
202
203#if 0
204static DECLCALLBACK(int) ProcessCallback(PVM pVM, unsigned uPercent, void *pvUser)
205{
206 unsigned *pPercent = (unsigned *)pvUser;
207
208 if (*pPercent != uPercent)
209 {
210 *pPercent = uPercent;
211 RTPrintf(".");
212 if ((uPercent % 10) == 0 && uPercent)
213 RTPrintf("%d%%", uPercent);
214 RTStrmFlush(g_pStdOut);
215 }
216
217 return VINF_SUCCESS;
218}
219#endif
220
221#if 0
222static int ConvertOldImage(const char *pszFilename)
223{
224 RTPrintf("Converting VDI image file=\"%s\" to a new format...\n"
225 "progress: 0%%",
226 pszFilename);
227
228 /* translate argv[] to UTF8 */
229 char *pszUtf8Filename;
230 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
231 if (RT_FAILURE(rc))
232 return rc;
233
234 unsigned uPercent = 0;
235 rc = VDIConvertImage(pszUtf8Filename, ProcessCallback, &uPercent);
236 RTPrintf("\n");
237 return PrintDone(rc);
238}
239#endif
240
241#if 0
242static int DumpImage(const char *pszFilename)
243{
244 RTPrintf("Dumping VDI image file=\"%s\" into the log file...\n", pszFilename);
245 PVDIDISK pVdi = VDIDiskCreate();
246
247 /* translate argv[] to UTF8 */
248 char *pszUtf8Filename;
249 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
250 if (RT_FAILURE(rc))
251 return rc;
252 rc = VDIDiskOpenImage(pVdi, pszUtf8Filename, VDI_OPEN_FLAGS_READONLY);
253 if (RT_SUCCESS(rc))
254 {
255 VDIDiskDumpImages(pVdi);
256 VDIDiskCloseAllImages(pVdi);
257 }
258 return PrintDone(rc);
259}
260#endif
261
262#if 0
263static int ResetImageGeometry(const char *pszFilename)
264{
265 RTPrintf("Resetting geometry info of VDI image file=\"%s\"\n", pszFilename);
266 PVDIDISK pVdi = VDIDiskCreate();
267
268 /* translate argv[] to UTF8 */
269 char *pszUtf8Filename;
270 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
271 if (RT_FAILURE(rc))
272 return rc;
273
274 rc = VDIDiskOpenImage(pVdi, pszUtf8Filename, VDI_OPEN_FLAGS_NORMAL);
275 if (RT_SUCCESS(rc))
276 {
277 VDGEOMETRY LCHSGeometry = {0, 0, 0};
278 rc = VDIDiskSetLCHSGeometry(pVdi, &LCHSGeometry);
279 }
280 VDIDiskCloseImage(pVdi);
281 return PrintDone(rc);
282}
283#endif
284
285#if 0
286static int CopyImage(const char *pszDstFile, const char *pszSrcFile)
287{
288 RTPrintf("Copying VDI image file=\"%s\" to image file=\"%s\"...\n"
289 "progress: 0%%",
290 pszSrcFile, pszDstFile);
291
292 /* translate argv[] to UTF8 */
293 char *pszUtf8SrcFile, *pszUtf8DstFile;
294 int rc = FilenameToUtf8(&pszUtf8SrcFile, pszSrcFile);
295 if (RT_FAILURE(rc))
296 return rc;
297 rc = FilenameToUtf8(&pszUtf8DstFile, pszDstFile);
298 if (RT_FAILURE(rc))
299 return rc;
300
301 unsigned uPrecent = 0;
302 rc = VDICopyImage(pszUtf8DstFile, pszUtf8SrcFile, NULL, ProcessCallback, &uPrecent);
303 RTPrintf("\n");
304 return PrintDone(rc);
305}
306#endif
307
308#if 0
309static int CopyToDD(const char *pszDstFile, const char *pszSrcFile)
310{
311 RTPrintf("Copying VDI image file=\"%s\" to DD file=\"%s\"...\n",
312 pszSrcFile, pszDstFile);
313 PVDIDISK pVdi = VDIDiskCreate();
314
315 /* translate argv[] to UTF8 */
316 char *pszUtf8SrcFile, *pszUtf8DstFile;
317 int rc = FilenameToUtf8(&pszUtf8SrcFile, pszSrcFile);
318 if (RT_FAILURE(rc))
319 return rc;
320 rc = FilenameToUtf8(&pszUtf8DstFile, pszDstFile);
321 if (RT_FAILURE(rc))
322 return rc;
323
324 rc = VDIDiskOpenImage(pVdi, pszUtf8SrcFile, VDI_OPEN_FLAGS_NORMAL);
325 if (RT_SUCCESS(rc))
326 {
327 RTFILE FileDst;
328 rc = RTFileOpen(&FileDst, pszUtf8DstFile, RTFILE_O_CREATE | RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE);
329 if (RT_SUCCESS(rc))
330 {
331 uint64_t cbSrc = VDIDiskGetSize(pVdi);
332 const unsigned cbBuf = VDIDiskGetBlockSize(pVdi); /* or perhaps VDIDiskGetBufferSize(pVdi)? */
333 void *pvBuf = RTMemAlloc(cbBuf);
334 if (pvBuf)
335 {
336 uint64_t off = 0;
337 while (off < cbSrc)
338 {
339 rc = VDIDiskRead(pVdi, off, pvBuf, cbBuf);
340 if (RT_FAILURE(rc))
341 break;
342 rc = RTFileWrite(FileDst, pvBuf, cbBuf, NULL);
343 if (RT_FAILURE(rc))
344 break;
345 off += cbBuf;
346 }
347 RTMemFree(pvBuf);
348 }
349 RTFileClose(FileDst);
350 }
351 }
352 VDIDiskCloseImage(pVdi);
353 return PrintDone(rc);
354}
355#endif
356
357#if 0
358static int ShrinkImage(const char *pszFilename)
359{
360 RTPrintf("Shrinking VDI image file=\"%s\"...\n"
361 "progress: 0%%",
362 pszFilename);
363
364 /* translate argv[] to UTF8 */
365 char *pszUtf8Filename;
366 int rc = FilenameToUtf8(&pszUtf8Filename, pszFilename);
367 if (RT_FAILURE(rc))
368 return rc;
369
370 unsigned uPrecent;
371 rc = VDIShrinkImage(pszUtf8Filename, ProcessCallback, &uPrecent);
372 RTPrintf("\n");
373 return PrintDone(rc);
374}
375#endif
376
377int main(int argc, char **argv)
378{
379 putenv((char*)"VBOX_LOG_DEST=stdout");
380 putenv((char*)"VBOX_LOG_FLAGS=");
381
382 RTR3InitExe(argc, &argv, 0);
383 RTPrintf("vditool -- for internal use only!\n"
384 "Copyright (C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n\n");
385
386 /*
387 * Do cmd line parsing.
388 */
389 if (argc < 2)
390 return UsageExit();
391
392 char szCmd[16];
393 if (strlen(argv[1]) >= sizeof(szCmd))
394 return SyntaxError("Invalid command!");
395 strcpy(szCmd, argv[1]);
396 ascii2upper(szCmd);
397
398 PRTLOGGER pLogger;
399 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
400 int rc = RTLogCreate(&pLogger, 0, "all",
401 NULL, RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_STDOUT,
402 NULL /* pfnBeginEnd */, 0 /* cHistory */, 0 /* cbHistoryFileMax */, 0 /* uHistoryTimeMax */,
403 NULL);
404 RTLogRelSetDefaultInstance(pLogger);
405
406 if (strcmp(szCmd, "NEW") == 0)
407 {
408 if (argc != 4)
409 return SyntaxError("Invalid argument count!");
410
411 uint64_t cMBs;
412 rc = RTStrToUInt64Ex(argv[3], NULL, 10, &cMBs);
413 if (RT_FAILURE(rc))
414 return SyntaxError("Invalid number!");
415 if (cMBs < 2)
416 {
417 RTPrintf("error: Disk size %RU64MB must be at least 2MB!\n", cMBs);
418 return 1;
419 }
420
421 rc = NewImage(argv[2], cMBs);
422 }
423#if 0
424 else if (strcmp(szCmd, "DD") == 0)
425 {
426 if (argc != 4)
427 return SyntaxError("Invalid argument count!");
428 rc = ConvertDDImage(argv[2], argv[3]);
429 }
430 else if (strcmp(szCmd, "CONVERT") == 0)
431 {
432 if (argc != 3)
433 return SyntaxError("Invalid argument count!");
434 rc = ConvertOldImage(argv[2]);
435 }
436 else if (strcmp(szCmd, "DUMP") == 0)
437 {
438 if (argc != 3)
439 return SyntaxError("Invalid argument count!");
440 rc = DumpImage(argv[2]);
441 }
442 else if (strcmp(szCmd, "RESETGEO") == 0)
443 {
444 if (argc != 3)
445 return SyntaxError("Invalid argument count!");
446 rc = ResetImageGeometry(argv[2]);
447 }
448 else if (strcmp(szCmd, "COPY") == 0)
449 {
450 if (argc != 4)
451 return SyntaxError("Invalid argument count!");
452 rc = CopyImage(argv[3], argv[2]);
453 }
454 else if (strcmp(szCmd, "COPYDD") == 0)
455 {
456 if (argc != 4)
457 return SyntaxError("Invalid argument count!");
458 rc = CopyToDD(argv[3], argv[2]);
459 }
460 else if (strcmp(szCmd, "SHRINK") == 0)
461 {
462 if (argc != 3)
463 return SyntaxError("Invalid argument count!");
464 rc = ShrinkImage(argv[2]);
465 }
466#endif
467 else
468 return SyntaxError("Invalid command!");
469
470 RTLogFlush(NULL);
471 return !RT_SUCCESS(rc);
472}
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