It's All About the Benjamins

Fixing image attachment metadata in wordpress1110.5 01:22:11

So I’ve been going through a long process of converting image galleries from a proprietary system (facebook via my own behind-the-scenes project, photodump), and I finally got everything converted — posts, image attachments, metadata, comments etc — at least as much as I could fake. But there’s some parts of the WordPress mysqldb that is practically impossible to generate without using wordpress’ own features, namely wp_postmeta. There is supposed to be an entry for each image and its thumbnail. It looks something like this

Well, fine, there are two great image thumbnail generator plugins, AJAX thumbnail rebuild, and regenerate thumbnails by Finalgear.com’s Viper007Bond. If there’s no metadata in the first place, regenerate thumbnails just throws an error, though — it’s for regenerating thumbnails, not creating this metadata. Ajax thumnail rebuild at least tries, though, but it gives you this broken db entry:

Well what to do? I looked up the errors regenerate thumnails was throwing since they were a bit more verbose. I found this great post showing exactly how to edit the code! But it did nothing. Nothing! So I went through diagnosing each variable and spitting it out by hijacking the baked-in error messages. So after diagnosis, I figured out it wasn’t ever actually getting the filename of the image, so here’s the code that does it. In regenerate-thumbnails.php replace $fullsizepath = get_attached_file( $image->ID );
with

$meta = wp_get_attachment_metadata($image->ID, true);
$file = $meta['file'];
$uploads = wp_upload_dir();
$fullsizepath = "/users/blahblah/wordpress_install/blogs.dir/(blognumber)/files". basename(wp_get_attachment_url($image->ID));

That totally fake path is the fully-qualified local filesystem path of where your images have been uploaded. Okay! Now regerate thumbnails is generating thumbnails! And writing the correct metadata into the sqldb.

Cloning a failing OS X boot drive1009.9 02:47:06

Supposedly, OS X’s Disk Utility is supposed to extend the “It Just Works” philosophy to some of the most sensitive and un-idiot-proofed parts of computer administration: partitioning, formatting, and copying disk drives and other storage media.

Well, I’m sure it’s great at it if you don’t have a bunch of bad blocks on your failing, two-year-old, 160 GB hard drive you got as a replacement from the Apple Store in Rome because your original drive imploded. Yeah because about halfway into cloning your primary to a new hard drive, Disk Utility will return some generic failure about not being able to complete the operation.

So what’s one to do? Well, if you want to make a byte-for-byte copy, you’ll have to crack out the command line and use dd, a UNIX tool so ancient its arguments take equals signs. Of course, to do that, you’ll have to unmount your boot drive, and in order to unmount your boot drive, you’ll have to boot up an OS X installer DVD. In my case, that means building a little crutch out of books and bottles to hold my Macbook upside down, since I have one of those lovely Superdrives which will only find a DVD’s track 0 when it is inverted.

root# dd if=/dev/rdisk0 of=/dev/rdisk2 bs=512 conv=noerror,sync

This of course assumes that you are copying from the boot drive, recognized as disk0 (rdisk0 means to access the disk as a raw block device, which we want because of the bad sectors), the drive you are cloning to is disk2, and the that dd won’t give up when it hits a bad block (noerror), instead it will just write a bunch of NULL for that block (sync). As far as I could tell from the Internet, HFS+ still uses a 512-byte block, which means you’ll get a miserable transfer rate across USB. Be prepared to wait 70 hours to copy a 160 GB drive. Theoretically you could set the blocksize much larger for faster transfers (normally this is what you would want to do) but because there are bad blocks, its my understanding that you’d get NULLs written instead of the good data surrounding the bad data.

So, come back a few days later, reboot the computer, fire up disk utility again and go to the new hard drive. The partition tab will let you non-destructively resize your cloned drive from 160 GB up to 320 GB to fill the whole drive, right?

Wrong. At least, it didn’t for me. Maybe it does for other people, but I just had to get the short end of the stick. Disk Utilily will pop up another fabulously descriptive error message: “Partition Failed with the Error: Media Kit reports partition (map) too small”

What? Well, remember mac hard drives are formatted as GUID (aka GPT) drives, so basically the problem here is that even though the clone is on a bigger hard drive, it still has the GPT from the original, smaller drive. OS X freaks out and won’t resize the partition. So, what to do, but nuke the GPT and write a new one. This won’t effect your data at all, but if you screw it up, you may not be able to access it ever again, boo hoo. So with that warning, here’s what you need to do.

Because we’ll need to do this with the disks unmounted, its best to keep using the OS X install CD. Go into terminal and see what the current GPT looks like. If you get an error at any time during this like gpt show: unable to open device '/dev/disk1': No such file or directory, you will need to unmount the disk. Sometimes it auto mounts after you write a command and you have to unmount it again. Whatever.

So here’s the GPT. It’s actually the GPT from my USB Time Machine HDD, but what you see will be similar. In your case, you’ll probably be doing this on /dev/disk2 or wherever you new, cloned drive is located.

root# gpt show /dev/disk2
start size index contents
0 1 PMBR
1 1 Pri GPT header
2 32 Pri GPT table
34 6
40 409600 1 GPT part - C12A7328-F81F-11D2-BA4B-00A0C93EC93B
409640 976101344 2 GPT part - 48465300-0000-11AA-AA11-00306543ECAC
976510984 262151

The numbers that you get for your own disk are critically important, although the first five lines will likely be identical to the above. What this shows is the MBR at sector zero (if you have one, you may not), then the start of the GPT itself, then a six-sector blank spot, and then, at sector 40, your EFI partition. Then, after that, at sector 409640, your HFS+ partition. If you have multiple partitions on your boot drive, you’ll have to figure out how to do this yourself from the instructions I give below about relabeling your EFI and HFS+ partitions.

This seems all scary and stuff, but if you’ve ever had to use BSD’s disklabel utility, it’s not all that different. First, we need to nuke the wrongly-sized GPT.

root# gpt destroy /dev/disk2

Okay, you’ve just made your drive completely unreadable to OS X!

Now, to make a new GPT.

root# gpt create /dev/disk2

Now it has a new GPT! OS X will try to mount the drive at this point, even though it won’t have found any usable partitions. Unmount it.

Let’s add partition label for the secret EFI partition. Remember, it started at sector 40 and was 409600 sectors in size (that’s 200 megabytes in case you were wondering). We’ll also have to add that big hexadecimal string which came after “GPT Part”: it identifies this partition as type EFI. Just to make sure it gets marked as partition index #1, we’ll put in that flag, too

root# gpt add -i 1 -b 40 -s 409600 -t C12A7328-F81F-11D2-BA4B-00A0C93EC93B

Apparently, you can also write “-t efi” instead of that big long string, but I didn’t want to chance anything, so I just copied and pasted it from the original output from gpt show.

Now, let’s make an index label for the HFS+ partition. We won’t have to specify the partition type, because gpt will default to HFS+. (If you want to know the string for other kinds of partitions, look here). Remember you need to look at the output of your own gpt show to determine these numbers. Also, this is the second partition on the drive, so remember to specify -i 2. Here is what it would be if I were redoing my Time Machine HDD’s GPT:

root# gpt add -i 2 -b 409640 -s 976101344

Okay, with that done, fire up Disk Utility. NOW it’ll non-destructively resize your partition just fine.

“BUT DUDE I TYPED ONE OF THOSE GPT COMMANDS WRONG AND SHUT THE TERMINAL DOWN AND I DON’T HAVE THE NUMBERS ANYMORE I DON’T KNOW WHAT TO DO!”

Dont panic! Remember, this is a cloned drive, right? You can do gpt show on the original drive and get the same information. Just make sure you don’t nuke the gpt on that drive too, because then you’ll really be up poop creek without a plunger.

Addendum: I’d really like to thank Scott Roberts for posting about redoing GPT tables on larger drives. Although his how-to is for a non-boot drive, and I had to figure out the EFI partition by trial and error (and manpages), I was completely lost on how to bounce back from that Media Kit error until I found his writeup.

Post Script: Of course, all of this — the 3 days of waiting, the hand hacking, the furious googling to figure out cryptic error messages — raises the question “Why not just pay money for SuperDuper or Carbon Copy Cloner to do this for you?” Well, because the tools are already there for free, and now you knwo how to use them beforehand and, uh, knowing is half the battle.

Snow Leopard and Project Capuchin1008.2 03:30:01

Some of the newer Sony Ericsson feature phones can run special hybrid J2ME-Flash Lite programs though some voodoo known as Project Capuchin. Great!

Well, the compiler that Sony released for OS X doesn’t work on snow leopard. This is because it was compiled for a 32 bit JVM, and 10.6 defaults to a 64 bit JVM and barfs when you try to run SWF2JAR, or the “Create Capuchin Application” from inside Flash CS3/CS4/CS5/whatever. It’s an easy fix, though. For swf2jar, control-click the application and show package contents. In the contents > macos folder is the MacOS runtime (like in any application), in the case of swf2jar, it’s just a bash script. Open textedit or whatever you prefer, and drag the swf2jar with the black-box icon to the textedit icon, and you should see that the bash script looks like this:


#!/bin/sh
BASEDIR=`dirname $0`
exec java \
-XstartOnFirstThread \
-Xdock:name="Swf2Jar" \
-Xdock:icon=$BASEDIR/../Resources/SWF2JAR.icns \
-classpath $BASEDIR/../Resources/Java/SWF2JAR.jar:$BASEDIR \
-jar $BASEDIR/../Resources/Java/SWF2JAR.jar \
-fileHelpLocation:$BASEDIR/../Resources/ug_swf2jar_r1a.pdf

Now what we need to do to get this to run is to pass a flag to java to make it run in 32 bit mode. This flag is -d32. You’ll have to put a trailing backslash on it so that bash doesn’t hoark up on the newline. So, it should now look like this:

#!/bin/sh
BASEDIR=`dirname $0`
exec java \
-d32 \
-XstartOnFirstThread \
-Xdock:name="Swf2Jar" \
-Xdock:icon=$BASEDIR/../Resources/SWF2JAR.icns \
-classpath $BASEDIR/../Resources/Java/SWF2JAR.jar:$BASEDIR \
-jar $BASEDIR/../Resources/Java/SWF2JAR.jar \
-fileHelpLocation:$BASEDIR/../Resources/ug_swf2jar_r1a.pdf

Save and you’re done. To fix it inside CS5, go to the Library folder inside your home directory, and then Application Support > Adobe > Flash CS5 > en_US > Configuration > Commands > swf2jar folder and then modify the swf2jar file in the same way as outlined above. Hey presto!

Hello world!1008.2 03:11:56

Welcome to iaatb. This is your first post. Edit or delete it, then start blogging!

Copyright 2002-2012 B.H. Lamb.
Copyright 2002-2012 B.H. Lamb.