My real point is to emphasise that there's no reason why VBox couldn't separated out its VDI and VMDK manipulation utilities, to make them easier to use as a FLOSS baseline.
It's a little utility which creates a copy (not a clone -- the UUIDs are the same) of a dynamic VDI, but shuffles the 1Mbyte allocation pages into ascending sequence, thereby defragmenting the VDI. OK, its in Perl, but why write 1,000 lines of C++ when you can do it in <150 lines of Perl. And I reckon that more readers will be familiar with Perl. I nearly did it in Python, but I thought that would be cruel. It still drives my HDD flat out. Anyway here it is. Please treat it as Alpha code. It works fine for me, but I won't warrant it.
DO NOT USE —— I'VE FOUND A CASE WHERE THIS CORRUPTS THE VDI
(I will post an update when I've debugged it)
Code: Select all
#
# A liile demo to show that it is quite easy to manipulate VDIs
# ~ 140 lines of Perl to do a defrag
# TerryE 15 Jul 2008
# This is an original work by me and placed unwarranted into the public domain.
#
use strict;
sub printUUID($);
sub printMap($@);
sub dumpVDIheader($);
my( $vdiName, $headerSize, $nextBlock ) =( shift(@ARGV), 512, 0 );
my( $header, $allocMap, @currentMap, @marshalOrder, @allocatedBlock, $newAllocMap );
open INVDI, '<:raw:bytes', $vdiName or die "cannot open VDI\n";
die "cannot read header\n"
unless read( INVDI, $header, $headerSize ) == $headerSize;
my( $blockSize, $blocksInHDD, $blocksAllocated ) = dumpVDIheader $header;
my $mapSize = $blocksInHDD * 4;
die "cannot read allocation map\n"
unless read( INVDI, $allocMap, $mapSize ) == $mapSize;
@currentMap = map { unpack "l<", substr( $allocMap, 4*$_, 4 ) ; }
( 0..($blocksInHDD-1) ) ;
@marshalOrder = grep { $_ > -1 } @currentMap;
@allocatedBlock = map { $_ == -1 ? -1 : $nextBlock++ } @currentMap;
$newAllocMap = join '', map( { pack( "l<", $_ ); } @allocatedBlock ) ;
die "problem with setting up Allocation Map\n"
if length( $newAllocMap ) != $mapSize;
printMap "Allocation map", @currentMap;
printMap "Marshalling Block sequence map", @marshalOrder;
printMap "New Allocation map", @allocatedBlock;
my $vdiTmp = $vdiName . "${$}tmp";
open OUTVDI, '>:raw:bytes', $vdiTmp or die "cannot open VDI\n";
seek OUTVDI, 0, 0;
die "cannot write header\n"
unless syswrite( OUTVDI, $header, $headerSize ) == $headerSize;
die "cannot write index mao\n"
unless syswrite( OUTVDI, $newAllocMap, $mapSize ) == $mapSize;
my $block = ' ' x $blockSize;
my $cnt = 0;
foreach my $i(@marshalOrder) {
my($chunk, $offset) =( '', 0 );
print( ($cnt++ % 10 ) == 9 ? "+":"." );
die "seek error on input file\n"
unless seek INVDI, $headerSize + $mapSize + $i*$blockSize , 0;
while( $offset < $blockSize ) {
my $n = read( INVDI, $chunk, $blockSize - $offset );
substr( $block, $offset, $n) = $chunk;
$offset += $n;
die "cannot read block\n" if $n == 0;
}
die "die invalid block length \n" unless $offset == $blockSize;
$offset = 0;
while( $offset < $blockSize ) {
my $n = syswrite( OUTVDI, substr( $block, $offset), $blockSize - $offset );
$offset += $n;
die "cannot write block\n" if $n == 0;
}
die "cannot write block\n" unless $offset == $blockSize;
}
close INVDI; close OUTVDI;
exit;
#===========================================================================
sub dumpVDIheader($) {
my( $fileInfo, $imageSignture, $version, $headerSize, $imageType,
$imageFlags, $imageDescription,$offsetBlocks, $offsetData,
$nCylinders, $nHeads, $nSectors, $sectorSize, $unused,
$diskSizeLSL, $diskSizeMSL, $blockSize, $blockExtraData, $blocksInHDD,
$blocksAllocated
) = unpack "a[64]VVVVVa[256]VVVVVVVVVVVVVVV", $header;
my $thisUUID = substr $header, 0x188, 16;
my $lastUUID = substr $header, 0x198, 16;
my $linkUUID = substr $header, 0x1a8, 16;
my $parentUUID = substr $header, 0x1b8, 16;
die "Unable to process this VDI format\n"
unless $imageSignture == 0xBEDA107F && $version == 0x00010001;
my $diskSize = $diskSizeMSL * 256 * 256 * 256 * 256 + $diskSizeLSL;
$fileInfo =~ s/[\0x00\n]*//g;
$imageDescription =~ s/[\0x00\n]*//g;
print "fileInfo = $fileInfo\n";
print "imageSignture = $imageSignture\n";
print "version = $version\n";
print "headerSize = $headerSize\n";
print "imageType = $imageType\n";
print "imageFlags = $imageFlags\n";
print "imageDescription = $imageDescription\n";
print "offsetBlocks = $offsetBlocks\n";
print "offsetData = $offsetData\n";
print "nCylinders = $nCylinders\n";
print "nHeads = $nHeads\n";
print "nSectors = $nSectors\n";
print "sectorSize = $sectorSize\n";
print "diskSize = $diskSize\n";
print "blockSize = $blockSize\n";
print "blockExtraData = $blockExtraData\n";
print "blocksInHDD = $blocksInHDD\n";
print "blocksAllocated = $blocksAllocated\n";
print "This UUID = ", printUUID($thisUUID), "\n";
print "Last UUID = ", printUUID($lastUUID), "\n";
print "Link UUID = ", printUUID($linkUUID), "\n";
print "Parent UUID = ", printUUID($parentUUID), "\n";
return( $blockSize, $blocksInHDD, $blocksAllocated );
}
sub printUUID($) {
return sprintf "%08x-%04x-%04x-%04x-%08x%04x", unpack("VvvnNn", shift);
}
sub printMap($@) {
my $mapTitle = shift;
my @map = @_;
print "\n$mapTitle = \n |", map {sprintf "%4d", $_}(0..19) ;
print "\n----+",("-" x 80);
foreach my $i( 0..$#map ) {
printf "\n%4d|", $i if($i % 20) == 0;
printf "%4d", $map[$i];
}
print "\n\n";
}
Code: Select all
fileInfo = <<< Sun VM VirtualBo Disk Image >>>
imageSignture = 3201962111
version = 65537
headerSize = 400
imageType = 1
imageFlags = 0
imageDescription =
offsetBlocks = 512
offsetData = 8192
nCylinders = 0
nHeads = 0
nSectors = 0
sectorSize = 512
diskSize = 2013265920
blockSize = 1048576
blockExtraData = 0
blocksInHDD = 1920
blocksAllocated = 523
This UUID = 2762085a-b6a8-4469-a157-e2b243a58fcb
Last UUID = e3b15c0c-73c5-40ed-aef7-06d620690c96
Link UUID = 00000000-0000-0000-0000-000000000000
Parent UUID = 00000000-0000-0000-0000-000000000000
Allocation map =
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
----+--------------------------------------------------------------------------------
0| 0 -1 1 54 77 98 2 159 182 217 3 259 272 285 4 372 397 398 5 399
20| 412 -1 6 -1 -1 -1 7 -1 -1 -1 8 -1 -1 -1 519 -1 -1 -1 -1 -1
40| -1 -1 -1 -1 -1 -1 -1 -1 204 205 206 207 208 209 210 211 212 213 214 215
60| 216 218 220 221 222 223 224 225 226 227 234 235 236 237 238 240 241 242 243 244
80| 245 246 247 289 288 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
100| 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
120| 354 355 356 364 357 358 359 360 9 392 361 362 363 365 366 367 368 369 370 371
140| 373 374 375 376 377 378 379 380 386 385 384 381 382 383 387 388 389 390 391 393
160| 394 -1 -1 -1 -1 -1 -1 -1 400 -1 -1 -1 -1 -1 -1 -1 28 40 39 43
180| 44 45 46 47 248 249 250 251 252 253 254 255 256 257 258 260 262 263 264 265
200| 266 267 268 269 270 271 273 274 275 279 278 277 276 280 281 282 283 284 286 287
220| 290 291 292 293 294 295 -1 -1 -1 -1 -1 -1 522 -1 -1 -1 -1 -1 -1 -1
240| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 10 -1 -1 -1
260| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
280| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
300| -1 -1 -1 -1 23 24 25 26 296 297 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
320| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
340| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
360| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
380| -1 -1 -1 -1 11 -1 408 -1 -1 -1 -1 -1 409 -1 -1 -1 -1 -1 -1 -1
400| 410 -1 -1 -1 -1 -1 -1 -1 411 -1 -1 -1 -1 -1 -1 -1 407 -1 -1 -1
420| -1 -1 -1 -1 406 -1 -1 -1 -1 -1 -1 -1 27 38 29 30 31 32 33 34
440| 35 36 37 41 96 97 95 94 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
460| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 401 -1 -1 -1 -1 -1 -1 -1
480| 402 -1 -1 -1 -1 -1 -1 -1 403 -1 -1 -1 -1 -1 -1 -1 404 -1 -1 -1
500| -1 -1 -1 -1 405 -1 -1 -1 -1 -1 -1 -1 12 -1 -1 -1 -1 -1 -1 -1
520| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
540| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
560| 261 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
580| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
600| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
620| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
640| 13 -1 18 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
660| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
680| -1 -1 -1 -1 -1 -1 -1 -1 42 48 49 50 51 52 53 55 56 57 58 59
700| 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 78 79 80
720| 81 82 83 84 85 86 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
740| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
760| -1 -1 -1 -1 -1 -1 -1 -1 14 19 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
780| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
800| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 308 -1 -1 -1
820| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
840| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
860| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
880| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 15 -1 20 -1
900| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
920| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
940| -1 -1 -1 -1 87 88 89 90 91 92 93 99 100 101 102 103 104 105 106 107
960| 108 109 110 115 111 112 113 114 22 116 117 118 119 120 121 122 123 124 125 126
980| 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
1000| 147 148 171 170 299 300 301 298 302 303 304 305 306 307 309 310 311 312 313 314
1020| 315 316 317 318 16 21 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
1040| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
1060| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 149 150 151 152 153 154 155 156
1080| 157 158 160 161 162 163 164 165 166 167 168 169 172 173 174 175 176 177 178 179
1100| 180 181 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
1120| 201 202 203 219 228 229 230 231 232 233 239 -1 -1 -1 -1 -1 -1 -1 -1 -1
1140| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 17 -1 520 -1 -1 -1 -1 -1
1160| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
1180| -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
1200| 395 396 -1 -1 -1 -1 413 419 418 417 416 415 420 421 414 462 -1 -1 -1 -1
1220| -1 -1 422 -1 -1 -1 -1 -1 -1 -1 423 -1 -1 -1 -1 -1 -1 -1 424 -1
1240| -1 -1 -1 -1 -1 -1 425 -1 -1 -1 -1 -1 -1 -1 426 -1 -1 -1 -1 -1
1260| -1 -1 427 -1 -1 -1 -1 -1 -1 -1 428 -1 -1 -1 -1 -1 -1 -1 429 -1
1280| -1 -1 -1 -1 -1 -1 430 -1 -1 -1 -1 -1 -1 -1 431 -1 -1 -1 -1 -1
1300| -1 -1 432 -1 -1 -1 -1 -1 -1 -1 433 -1 -1 -1 -1 -1 -1 -1 434 -1
1320| -1 -1 -1 -1 -1 -1 435 -1 -1 -1 -1 -1 -1 -1 436 -1 -1 -1 -1 -1
1340| -1 -1 437 -1 -1 -1 -1 -1 -1 -1 438 -1 -1 -1 -1 -1 -1 -1 439 -1
1360| -1 -1 -1 -1 -1 -1 440 -1 -1 -1 -1 -1 -1 -1 441 -1 -1 -1 -1 -1
1380| -1 -1 442 -1 -1 -1 -1 -1 -1 -1 443 -1 -1 -1 -1 -1 -1 -1 444 -1
1400| -1 -1 -1 -1 -1 -1 445 -1 -1 -1 -1 -1 -1 -1 446 -1 -1 -1 -1 -1
1420| -1 -1 447 -1 -1 -1 -1 -1 -1 -1 448 -1 -1 -1 -1 -1 -1 -1 449 -1
1440| -1 -1 -1 -1 -1 -1 450 -1 -1 -1 -1 -1 -1 -1 451 -1 -1 -1 -1 -1
1460| -1 -1 452 -1 -1 -1 -1 -1 -1 -1 453 -1 -1 -1 -1 -1 -1 -1 454 -1
1480| -1 -1 -1 -1 -1 -1 455 -1 -1 -1 -1 -1 -1 -1 456 -1 -1 -1 -1 -1
1500| -1 -1 457 -1 -1 -1 -1 -1 -1 -1 458 -1 -1 -1 -1 -1 -1 -1 459 -1
1520| -1 -1 -1 -1 -1 -1 460 -1 -1 -1 -1 -1 -1 -1 461 -1 -1 -1 -1 -1
1540| -1 -1 463 -1 -1 -1 -1 -1 -1 -1 464 -1 -1 -1 -1 -1 -1 -1 465 -1
1560| -1 -1 -1 -1 -1 -1 466 -1 -1 -1 -1 -1 -1 -1 467 -1 -1 -1 -1 -1
1580| -1 -1 468 -1 -1 -1 -1 -1 -1 -1 469 -1 -1 -1 -1 -1 -1 -1 470 -1
1600| -1 -1 -1 -1 -1 -1 471 -1 -1 -1 -1 -1 -1 -1 472 -1 -1 -1 -1 -1
1620| -1 -1 473 -1 -1 -1 -1 -1 -1 -1 474 -1 -1 -1 475 476 477 478 479 485
1640| 486 487 488 489 -1 -1 -1 -1 -1 -1 490 -1 -1 -1 -1 -1 -1 -1 491 -1
1660| -1 -1 -1 -1 -1 -1 492 -1 -1 -1 -1 -1 -1 -1 493 -1 -1 -1 -1 -1
1680| -1 -1 494 -1 -1 -1 -1 -1 -1 -1 495 -1 -1 -1 -1 -1 -1 -1 496 -1
1700| -1 -1 -1 -1 -1 -1 497 -1 -1 -1 -1 -1 -1 -1 498 -1 -1 -1 -1 -1
1720| -1 -1 499 -1 -1 -1 -1 -1 -1 -1 500 -1 -1 -1 -1 -1 -1 -1 501 -1
1740| -1 -1 -1 -1 -1 -1 502 -1 -1 -1 521 -1 -1 -1 480 -1 -1 -1 -1 -1
1760| -1 -1 481 -1 -1 -1 -1 -1 -1 -1 482 -1 -1 -1 -1 -1 -1 -1 483 -1
1780| -1 -1 -1 -1 -1 -1 484 -1 -1 -1 -1 -1 -1 -1 503 -1 -1 -1 -1 -1
1800| -1 -1 504 -1 -1 -1 -1 -1 -1 -1 505 -1 -1 -1 -1 -1 -1 -1 506 -1
1820| -1 -1 -1 -1 -1 -1 507 -1 -1 -1 -1 -1 -1 -1 508 -1 -1 -1 -1 -1
1840| -1 -1 509 -1 -1 -1 -1 -1 -1 -1 510 -1 -1 -1 -1 -1 -1 -1 511 -1
1860| -1 -1 -1 -1 -1 -1 512 -1 -1 -1 -1 -1 -1 -1 513 -1 -1 -1 -1 -1
1880| -1 -1 514 -1 -1 -1 -1 -1 -1 -1 515 -1 -1 -1 -1 -1 -1 -1 516 -1
1900| -1 -1 -1 -1 -1 -1 517 -1 -1 -1 -1 -1 -1 -1 518 -1 -1 -1 -1 -1
Marshalling Block sequence map =
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
----+--------------------------------------------------------------------------------
0| 0 1 54 77 98 2 159 182 217 3 259 272 285 4 372 397 398 5 399 412
20| 6 7 8 519 204 205 206 207 208 209 210 211 212 213 214 215 216 218 220 221
40| 222 223 224 225 226 227 234 235 236 237 238 240 241 242 243 244 245 246 247 289
60| 288 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
80| 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 364
100| 357 358 359 360 9 392 361 362 363 365 366 367 368 369 370 371 373 374 375 376
120| 377 378 379 380 386 385 384 381 382 383 387 388 389 390 391 393 394 400 28 40
140| 39 43 44 45 46 47 248 249 250 251 252 253 254 255 256 257 258 260 262 263
160| 264 265 266 267 268 269 270 271 273 274 275 279 278 277 276 280 281 282 283 284
180| 286 287 290 291 292 293 294 295 522 10 23 24 25 26 296 297 11 408 409 410
200| 411 407 406 27 38 29 30 31 32 33 34 35 36 37 41 96 97 95 94 401
220| 402 403 404 405 12 261 13 18 42 48 49 50 51 52 53 55 56 57 58 59
240| 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 78 79 80
260| 81 82 83 84 85 86 14 19 308 15 20 87 88 89 90 91 92 93 99 100
280| 101 102 103 104 105 106 107 108 109 110 115 111 112 113 114 22 116 117 118 119
300| 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
320| 140 141 142 143 144 145 146 147 148 171 170 299 300 301 298 302 303 304 305 306
340| 307 309 310 311 312 313 314 315 316 317 318 16 21 149 150 151 152 153 154 155
360| 156 157 158 160 161 162 163 164 165 166 167 168 169 172 173 174 175 176 177 178
380| 179 180 181 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
400| 200 201 202 203 219 228 229 230 231 232 233 239 17 520 395 396 413 419 418 417
420| 416 415 420 421 414 462 422 423 424 425 426 427 428 429 430 431 432 433 434 435
440| 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
460| 456 457 458 459 460 461 463 464 465 466 467 468 469 470 471 472 473 474 475 476
480| 477 478 479 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
500| 502 521 480 481 482 483 484 503 504 505 506 507 508 509 510 511 512 513 514 515
520| 516 517 518