Computers: June 2008 Archives
Brand new 500 MB Time Capsule. Latest firmware, latest AirPort software, latest Mac OS X version.
One of my computers, a Titanium PowerBook, connects just fine and backups and it all seems happy and joyous.
My other one, the MacBook Pro ... not so much. No matter what I try, I get "The backup volume could not be mounted." Here's the system log:
Jun 18 00:49:47 bourque kernel[0]: AFP_VFS afpfs_mount: /Volumes/Shore, pid 206 Jun 18 00:49:47 bourque /System/Library/CoreServices/backupd[327]: Backup requested due to disk attach Jun 18 00:49:47 bourque /System/Library/CoreServices/backupd[327]: Starting standard backup Jun 18 00:49:47 bourque /System/Library/CoreServices/backupd[327]: Network mountpoint /Volumes/Shore not owned by backupd... remounting Jun 18 00:49:47 bourque /System/Library/CoreServices/backupd[327]: [SnapshotUtilities remountVolumeRef] url could not be resolved via BonJour Jun 18 00:49:47 bourque /System/Library/CoreServices/backupd[327]: Failed to remount network volume. Jun 18 00:49:52 bourque /System/Library/CoreServices/backupd[327]: Backup failed with error: 19
It's some sort of authentication problem. I could not figure out what it is, tried everything. Tried messing with the Keychain, tried deleting all prefs. Nothing works. I saw a bunch of other people online with the same problem; some had fixed it, some had (apparently) not.
Eventually I figured out that if I mounted the volume as root -- which is what backupd runs as -- then it works just fine.
$ mkdir /Volumes/Shore $ sudo mount_afp afp://pudge:mypassword@Shore.local/Shore /Volumes/Shore
Then I can run Time Machine and all is happy. Until the next time.
So I wrote this script that gets called from root's crontab. It basically does the same thing (though not quite as "neatly") as Time Machine itself should. Until Apple fixes this insanely stupid bug -- you'd think the thing would work out of the box! -- it should keep me going, although to actually enter Time Machine, I need to manually mount the sparsebundle that's sitting on the Time Capsule, but I can do that without root.
#!/usr/bin/perl use warnings; use strict; my $backupd = '/System/Library/CoreServices/backupd.bundle/' . 'Contents/Resources/backupd-helper'; # put password in this file, chmod 0600 my $passf = '/Users/pudge/.backupd-helper-helper'; my $user = 'pudge'; my $share = 'Shore.local'; my $vol = 'Shore'; chomp(my $pass = do { open my $fh, '<', $passf; <$fh> }); my $dir = "/Volumes/$vol"; my $url = "afp://$user:$pass\@$share/$vol"; rmdir $dir; # let fail silently, we only want to remove if dir is empty, # and if it doesn't exist, that's OK too mkdir $dir or die "Can't mkdir $dir: $!"; # NOW complain loudly if it fails system '/sbin/mount_afp', $url, $dir; system $backupd; # usually not necessary, but will fail silently system '/sbin/umount', $dir; __END__
So our design guy tells us that it would be much better if, instead of throwing in double <br> tags for paragraphs, we changed it to <p> tags. Oh, and make sure it works in XHTML in case we want to use that someday, which means we need starting and ending tags.
So, this is sortof a pain, doing it right. I am trying to think of all the potential problems, and there's a bunch. So I put in a paragraph tag for the double-linebreak tag, but where do I put the ending tag? What algorithms do I use to find the right place? Pain.
And then I remembered that all comments get passed through a function I wrote several years ago called balanceTags(). You can basically throw any HTML you want at it, and it will return valid HTML. It will balance unbalanced tags (including paragraph tags), it will make sure blockquote tags include block tags inside them, and so on. If the "xhtml" flag was on, it will even make lone tags like linebreaks and images (and some paragraphs) into proper XHTML tags. So switching to XHTML is as simple as flipping the switch.
Therefore, all I had to do is find out where to put the open paragraph tags, and balanceTags() takes care of the rest. Hooray! So in this case it means putting a paragraph tag at the beginning of each comment (which is something I've wanted to do for awhile anyway), and then another one at each double-linebreak, and we're golden.
I was worrying about doing it right for nothing, since I'd already done it right years ago!
The slashd program in slash runs "tasks" which are separate files. It performs a require(). The problem is that sometimes symbols in each task can conflict with another.
We have many tasks so rather than edit each one, we decided to handle the encapsulation in slashd itself. It creates a package name, and has code to import symbols from main into the package, and then sets the line number correctly.
(my $tmppackage = $file) =~ s/\.pl$//; $tmppackage =~ s/\W/_/g; $tmppackage =~ s/^([^a-zA-Z])/a_$1/g; $tmppackage = "Slash::Task::$tmppackage"; # replace tmppackage in string where appropriate (my $addtxt = <<'EOT') =~ s/\${?tmppackage}?/$tmppackage/g; package $tmppackage; { no strict 'refs'; my @scalar = qw(me task_exit_flag); my @hash = qw(task); my @code = (qw( slashdLog slashdErrnote slashdLogDie tagboxLog verbosity db_time init_cron ), grep { *{"main::$_"}{CODE} } @Slash::EXPORT, @Slash::Display::EXPORT, @Slash::Utility::EXPORT, @File::Spec::Functions::EXPORT, @LWP::UserAgent::EXPORT, @URI::Escape::EXPORT, @File::Basename::EXPORT, @File::Path::EXPORT, @Time::Local::EXPORT, @Time::HiRes::EXPORT ); *{"${tmppackage}::$_"} = *{"main::$_"}{HASH} for @hash; *{"${tmppackage}::$_"} = *{"main::$_"}{SCALAR} for @scalar; *{"${tmppackage}::$_"} = *{"main::$_"}{CODE} for @code; } #line 1 EOT my($tmpfh, $tmpfile) = tempfile(); my $tmptxt = do { open my $fh, '<', $fullname; local $/; <$fh> }; print $tmpfh $addtxt, $tmptxt; $tmpfh->flush; # can't close fh until we require the file, # else the file might disappear my $ok = 0; eval { local $me = $file; $ok = require $tmpfile };