Hello all! You may have noticed that updates this past week have been a bit sparse. Although I promised myself that I wouldn’t typically talk about personal manners in this blog, I think some sort of explanation is required here. In a nutshell, the hard disk for my computer was corrupted, and nearly all data on it was lost.
Going back to the beginning, I used to run Windows 98 on my computer, which I built myself back at the end of 2000 (the components were a Christmas gift from my parents, with one or two exceptions). Thus, Melkor, my wonderful, wonderful computer was born. Although I’ve tried various Linux distributions here and there (and generally liked them), I’ve never quite managed to get one that where everything just works right (this is mostly due to unusual circumstances involving internet access where I live, but that’s another story, save to say the broadband is not available here in any reasonable form).
Fast forward to the first week of April 2006. Melkor has been showing some odd problems with booting, but otherwise seems to running fine with some upgrades (a DVD drive, USB accessories) on the same original Win 98 installation. Among other things, scandisk is complaining about corrupt sectors, but this actually means nothing – it’s done it before, and it’s always been wrong before. While letting scandisk verify that everything “REALLY IS OK” (which it did), I noticed that it’s diagram of my hard drive resembled swiss cheese, and decided to run defrag.
So, after running defrag for a couple of hours, it stops, tells me that it’s encountered an error, and that I should run scandisk. Defrag has also done this before, and it’s also never been a problem. I rebooted my system and got that most feared of message – “Non-system disk or filesystem error” (very roughly, I couldn’t copy and paste it since, at that point, I no longer had an OS on that partion, although I didn’t know that yet).
After fiddling around with some boot settings in the BIOS, I decide that there’s no way I can get into Windows as things are, and boot up Xandros, which I had on another partion on the same hard drive. I copied some documents from the old Windows partion to my external USB hard drive that had been worked on or created in the last month or so, and then, after checking with Scandisk and DOSFSCK to make sure that the situation really was hopeless (it was), reformatted my drive with the Windows 98 CD.
Windows 98, coming right off the CD, is an ugly thing. It refuses to boot up in a resolution higher than 640 x 480 with 16 colors, even though the driver that Win 98 setup is clearly better than this. “Not a problem”, I thought, as I had made a complete backup of my hard drive just last month after have some odd transient problems of a (hopefully) unrelated nature. I’d just restore my entire hard drive from the back up after installing the driver to get my USB hard drive to work.
Except, of course, that I made the back up with Ahead’s Nero BackItUp, which, while exceedingly good at MAKING backups is a bit lacking in actually RESTORING them. Nero apparently needs all of its files in the right place, especially a “NBI” file that was nowhere to be found. Nero’s “NRestore.exe” also couldn’t detect any drives except the one that I was trying to restore to, making things even more difficult.
After a bit of poking around, I found out that the “NCO” files that Nero had generated could be opened with WinZip, and, after a bit of experimentation, with the freely available 7-Zip as well. So, the backup that I had wasn’t worthless after all! Except, of course, that even a smaller hard drive like my 1999 or so IBM contains dozens of gigabytes of data spread over hundreds of thousands of files; it’d take a lifetime to right-click on them all and extract them.
My initial solution was to use PHP to copy files in 5000 or so chunks into a special folder, select all of the files that had been copied, and tell 7-zip to get to work on them. This almost worked, in the sense that I managed to get my old version of Windows 98 running again for a minute or two before it crashed. Besides being extremely awkward, Nero stored the full file names in the name of the archive itself, and used a DOS “8.3″ filename inside the archive, so that a file named “ReallyLongFileName.txt” in the old system became “REALLY~1.TXT” in the restored backup. This may have been a feature I selected by mistake when I thought it would affect the name of the archive itself, but it’s still a misfeature for even being present – what type of backup software has optional data corruption?
So, my second solution was the following PHP script, which has some quirky behavior but more or less works:
<?php
/**
* Recursive version of glob
*
* @return array containing all pattern-matched files.
*
* @param string $sDir Directory to start with.
* @param string $sPattern Pattern to glob for.
* @param int $nFlags Flags sent to glob.
*/
function globr($sDir, $sPattern, $nFlags = NULL)
{
// Get the list of all matching files currently in the
// directory.
echo "Examining $sDirn";
$aFiles = glob("$sDir/$sPattern", $nFlags);
// Then get a list of all directories in this directory, and
// run ourselves on the resulting array. This is the
// recursion step, which will not execute if there are no
// directories.
foreach (glob("$sDir/*", GLOB_ONLYDIR) as $sSubDir)
{
$aSubFiles = globr($sSubDir, $sPattern, $nFlags);
$aFiles = array_merge($aFiles, $aSubFiles);
}
// The array we return contains the files we found, and the
// files all of our children found.
return $aFiles;
}
$glob="backupc";
chdir(dirname($glob));
// getcwd() is now actually "W:temp" or whatever
$dir = getcwd();
$allfiles = globr($dir, "*.nco");
foreach ($allfiles as $file) {
echo "Working on $filen";
$filename = basename($file);
$directory = dirname($file);
$newname = str_replace(".nco","",$filename);
//echo "exec "C:program files7zip7z e -so $file > $directory.$newname";
exec ("7z e -so "$file" > "$directory\$newname"");
//unlink($file);
}
?>
This is simultanously both the coolest and the dumbest script I have ever written (although, in truth, more lines than not are code snippits from other people that have been thrown together, and 7-Zip does all of the “heavy lifting”). I recursively goes through the backup, starts 7-zip’s command line mode with instructions to write the contents of the archive to stout, and redirects that output to to a file equal to the name of the old file minus the “NCO” part. Perfect, no?
Well, no, actually, it’s not. If the contents of the file are all that matters, the script actually does perform right – but Windows 98 determines what version of system files to use based on timestamps. Because all files generated by this script are technically new files with contents of the old files, as opposed to the old, extracted files themselves, the timestamps are messed up, and Windows chokes again when anything new is installed.
I suppose this problem could be solved with something akin to the touch command, but my system wasn’t working for the third time in a row, and four days had already gone by. I decided go ahead and get a upgrade copy of Windows XP. The system files were so badly mucked up by Win 98 trying to repair itself that Windows XP didn’t even realize that 98 was, in fact, installed, and asked to see my 98 installation disc. The script above is still good for applications where timestamps don’t matter – I’ve restored my Mozilla settings this way without too much fuss, and plain old data files are no problem at all. I’ve reinstalled my DVD player, and things should be back to normal around here on the FanCruft site.
I would like to thank Seagate and IBM, the brand names on my hard drives, both of which have done quite well these past few days, Igor Pavlov, creator of 7-Zip, whose name must have appeared on my screen literally a million times during this ordeal, and Sthomas, Deviant, DMan, and others who put useful bits of code (incorporated above) and comments on the PHP manual page for glob() – PHP has always had excellent documentation, boosted significantly by comments from the community, and I have never been happier to script in PHP.