QZ qz thoughts
a blog from Eli the Bearded


In the 1990s, I had an Apple Mac IIci with A/UX. Most of that is a story for another day. All I have left from that system are a few 3.5" (90 mm) floppy disks, a couple of CD-ROM with programs that run on multiple systems (eg, Infocom Games), and my magneto-optical stuff.

I had done my homework researching storage systems for backups. The best sources I had said that Zip drives were "bad", CD-R was "good", and magneto-optical (MO) was "archival". Zips were the cheapest drives of those, and CD-R the most expensive. Media was another matter, I recall CD-R as being cheapest. Media capacity was another thing. My main hard dirve was just 80MB, so a 100MB Zip drive or 128MB MO disk was a huge amount of space, and a CD-R disk was nearly impossible to completely use.

More than two decades on, the longevity advice seems to have been sound. There's a gotcha, however. MO has basically disappeared as a format. Speciallized industrial use apparently exists. Even the audio version, the minidisc, never gained a lot of traction (at least in the US; Japan is another story). CD-R and CD-RW has proved to be a bit fragile, but it is also very widely available, and eventually the media got very cheap, so making multiple copies and duplicating stuff every year is reasonable.

When I was getting rid of my Mac IIci, I kept the MO drive and disks. Then I bought a computer with a SCSI card to be able to read the files. I've still got that computer (although it works poorly), the SCSI card, my MO drive, and all my MO disks. About five years ago I spun up the computer and drive and copied everything to CD-R. About two years ago, I copied those CD-Rs to back-up hard drives. One was bad. I should really spin the whole thing up again and make new copies from the MO disks, but for today, here's some photos.

MO drive, disks, PCI SCSI card

The whole shebang. MO drive, some disks, PCI SCSI card

The 128 megabyte size MO was the smallest version of MO. In the 90mm form, 128 and 230 were available at the time I was buying, and larger capacities in 5.25" (130mm). Eventually disks up to 2 gigabytes were available in 90mm. As an aside, I was quite fond of that Idemitsu logo.

MO disk closeup open

MO disk closeup open. Sector partitions are clearly visible. I used tape to hold it open for this shot, normally it springs shut.

MO end view, next to floppy

The MO disks are about twice as thick as a 3.5" floppy.

disk side by side with floppy front

Same size, and very similar to 3.5" floppy from front

Pencilled in there is a summary of the partition table. This habit of mine made finding the partitions to read the files off from Linux much easier.

disk side by side with floppy back

And from the back; note thought the cover extends over the hub

disk side by side with floppy, MO opened

Back opened to show MO hub

The MO disks are bigger (in thickness), sturdier, and fancier than 3.5" floppies. Since the disks are sectored, the system doesn't need a notch in the hub to align things.

MO drive top with nameplate

MO drive top with nameplate, Epson OMD-5000, December 1992. Pretty sure I got this late 1993 or early 1994.

This was originally in an external enclosure with a 25-pin Mac-style SCSI connector. I pulled the drive out of the enclosure for ease of use post-Mac. The disks get warm during writes, hence concerns about air flow.

MO drive side view

Boring MO drive side view

MO drive side view

MO drive side view with barcode

MO drive front view

MO drive front, same size as a typical 3.5" floppy drive, but sweet 128 megabytes! The sticker on the eject button was optional.

I got, and probably still have, a special eject tool to poke in that hole instead of the standared bent paperclip. I used the tool with other drives, eg, those Macs that used a similar hole to eject CDs. The regular button eject activates an electro-mechanical eject, like on a VCR.

MO drive rear

MO drive rear with power and SCSI connectors plus jumpers. Gotta set that SCSI ID

Relatively sealed MO drive bottom

Drive bottom preserves secrets.

32bit 5v PCI SCSI card, copyright 1999

PCI (32bit 5v) 50-pin SCSI card, copyright 1999. I probably got this in 1999 or 2000.

Other side of PCI SCSI card

SCSI card, rear

The computer I have to use this card doesn't have space inside for the MO, so I used it with the cable coming out the back. I don't keep the card in the computer, because of the cable mess.

udev for the win

So I have an Arduino Uno now and some parts to begin working on my alarm clock project but I'm still new to Arduino and need to get comfortable with programming it. So first thing I do is fire up the standard Arduino GUI programming tool ("IDE" in the argot of those that like such tools).

You need to be added to the "dialout" group...

And I'm ready to Ackchyually it.

Being added to the dialout group is a pretty good fix. But it's not the only way to do that, so "need" is a strong word. The advantage of being in the dialout group is it works pretty generally and without any extra tooling. The disadvantage is group membership is inherited from login, and I don't want to log out and log in again. A logout is as good as a reboot, and usually it is the reboot that forces the logout. These days I try to limit it those to once a month or less, depending on important kernel updates. It's been less than two weeks now, way too soon for that much disruption.

So here follows an alternative route with udev rules.

First I need to identify the device to apply those rules. I'll start with watching what's going on in /var/log/syslog when I plug the device in:

Nov  7 19:49:59 slate-asus kernel: [947954.307562] usb 1-3: new full-speed USB device number 8 using xhci_hcd
Nov  7 19:49:59 slate-asus kernel: [947954.458285] usb 1-3: New USB device found, idVendor=2341, idProduct=0043
Nov  7 19:49:59 slate-asus kernel: [947954.458291] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=220
Nov  7 19:49:59 slate-asus kernel: [947954.458294] usb 1-3: Manufacturer: Arduino (www.arduino.cc)
Nov  7 19:49:59 slate-asus kernel: [947954.458296] usb 1-3: SerialNumber: 8593731353731234A012
Nov  7 19:49:59 slate-asus mtp-probe: checking bus 1, device 8: "/sys/devices/pci0000:00/0000:00:15.0/usb1/1-3"
Nov  7 19:49:59 slate-asus mtp-probe: bus: 1, device: 8 was not an MTP device
Nov  7 19:49:59 slate-asus kernel: [947954.532024] cdc_acm 1-3:1.0: ttyACM0: USB ACM device

That's all I really need there, but there's other ways to get that information. If you are not used to reading that log, here's the general format of what it is showing:

  • Nov 7 19:49:59 date and time in system default timezone (US Pacific for me).
  • slate-asus computer name. I uniquely name all my computers, and this one doesn't have an obvious model name on it, so color - maker.
  • kernel: / mtp-probe: the name of the component creating the message. Messages from the kernel include the uptime in seconds, eg [947954.532024], which is one week, three days, twenty-three hours, nineteen minutes and a bit over fourteen seconds. Way too soon to reboot.
  • checking bus 1, device 8: "/sys/devices/pci0000:00/0000:00:15.0/usb1/1-3 This message from the media transport protocol probe has one way to identify the device.
  • cdc_acm 1-3:1.0: ttyACM0: USB ACM device This contains the other way. cdc: communications device class; acm: abstract control model. Essentially this is a modem-like serial device on USB (the "universial serial bus"). And modem-like is why the group is dialout.
  • Another way to find the device name is look in the /dev/ directory and find the new file that was created when plugging the device in (here, /dev/ttyACM0) and have the udev system tell us what it is with the udevadm info -a -n /dev/ttyACM0 command (verbose output partially removed):

    # udevadm info -a -n /dev/ttyACM0
    Udevadm info starts with the device specified by the devpath and then
    walks up the chain of parent devices. It prints for every device
    found, all possible attributes in the udev rules key format.
    A rule to match, can be composed by the attributes of the device
    and the attributes from one single parent device.
      looking at device '/devices/pci0000:00/0000:00:15.0/usb1/1-3/1-3:1.0/tty/ttyACM0':
      looking at parent device '/devices/pci0000:00/0000:00:15.0/usb1/1-3/1-3:1.0':
      looking at parent device '/devices/pci0000:00/0000:00:15.0/usb1/1-3':
      looking at parent device '/devices/pci0000:00/0000:00:15.0/usb1':
      looking at parent device '/devices/pci0000:00/0000:00:15.0':
      looking at parent device '/devices/pci0000:00':

    We'd get the same relevant information from the other identifier using the udevadm info -a /sys/devices/pci0000:00/0000:00:15.0 command. Every single thing in that list of device info can be used as a key for trigging a udev script. The ATTRS{subsystem_device} or ATTRS{subsystem_vendor} is a good choice for being relatively specific to plugging in an Uno and getting a device.

    So now we know what to use as a trigger, let's use that to run a script. In /etc/udev/rules.d/ live *.rules files for what to do for devices. On my system the highest numbered existing rule is 70-snap.snapd.rules, so I'll pick a two digit number higher than that and create my new rules file.

    $ cat /etc/udev/rules.d/80-arduino.rules
    ATTRS{subsystem_device}=="0x201f", ACTION=="add", RUN+="/usr/local/bin/plugin uno"

    Each line is a rule. This one says when the subsystem_device attribute is 0x201f and the action happening is an add, then add to the list of things to be run /usr/local/bin/plugin uno. The argument isn't really needed for udev, because there are enough environment variables to use for context, but could be handy for hand running it. I (or you) could match on more than one attribute by just adding them to the list: ATTRS{subsystem_vendor}=="0x1043", ATTRS{subsystem_device}=="0x201f", ...

    With the rule in place, we need to reload the udev configuration in order to have the rule take effect. This is much easier than a reboot.

    # udevadm control --reload

    A note on prompts: in my copies of terminal output, a prompt of $ means that it is a command to be run as a regular user, and a prompt of # means it requires superuser privileges. I usually use a superuser shell, but sudo in front of the command is the common way these days.

    Now we have a rule to run something when the device is plugged in, we should figure out what to run. A stub script is very helpful here:

    $ cat /usr/local/bin/plugin
    exec >> "$log" 2>&1     # "exec" changes stdout, etc, while running

    Plug the Uno in, and then look at the plugin-udev.log file.

    $ cat /var/log/plugin-udev.log

    There's a lot in there, so I could use ID_MODEL_FROM_DATABASE or ID_MODEL_FROM_DATABASE instead of uno as an argument, but I'm going to stick with that method to flag what to do. But I will have DEVNAME tell me what to act on. Next version of the plugin script:

    # device to try for "uno" if $DEVNAME is not set
    if [ ! -w "$log" ] ; then
      echo "$0: Intended to be run as root from udev scripts."
    exec 3>&1               # create 3 as copy of stdout
    exec >> "$log" 2>&1     # make orig stdout/stderr logfile
    now=$(date +%Y/%m/%dT%H:%M:%S)
    case "$1" in
      uno) device=${DEVNAME:-$uno_dev} 
           if [ -c "$device" ] ; then
             echo "$now - chowning $device now"
             chown username "$device"
             echo "$now - can't find $device"
      ?*) echo "$now - unrecognized plugin event: $1"
          echo        "unrecognized plugin event: $1" >&3
      *)  echo "$now - need a udev event, eg 'uno'"
          echo        "need a udev event, eg 'uno'" >&3

    I juggle stdout/stderr a bit here. First I open file descriptor 3 as a copy of stdout, then I change stdout and stderr to go to the logfile. This means anything normally sent to stdout or stderr will go in the log, and I can capture output and errors there, but because if I want to print to the original stdout (probably a terminal), I need to do it explicitly through file descriptor 3. Any program I run, will use the logfile for output but I can also print to the terminal. I use that for the unexpected usage cases. If someone with privileges runs /usr/local/bin/plugin that gets logged in the logfile and gets a message on the terminal. (Someone without privileges probably gets stopped when I check if the logfile is writable with [ -w "$log" ].)

    So, let's try it out. Plug in the USB cable from the Arduino and:

    $ ls -l /dev/ttyA*     
    crw-rw---- 1 username dialout 166, 0 Nov  8 13:39 /dev/ttyACM0
    $ groups
    username adm cdrom sudo dip plugdev lpadmin sambashare docker rvm
    $ tail -1 /var/log/plugin-udev.log
    2020/11/07T21:51:46 - chowning /dev/ttyACM0 now

    Presto, the device "belongs" to me, I can write to it without being in group dialout.

    People often use udev rules for dealing with permissions related to thumbdrives, and there are a bunch of tutorials on doing that sort of thing, but udev is more useful and I wanted to show that.

November Third, Twenty-twenty

Night view of a lit up window with a mannequin

I saw this many times over the past month, mostly at night where it stands out from the brightly lit window.

Day view of same window with a mannequin

During the day it is easier to miss.

Closer view of the window, showing mannequin has VOTE TRUMP sign

The "VOTE TRUMP" sign is not typical of this neighborhood.

Closer still, showing mannequin with VOTE TRUMP sign is the Devil

A mannequin dressed as the devil during the run up to Halloween, well that is typical.

I Voted! sticker and San Francisco ballot voter stubs

When I voted in 2016, there were about 120 votes cast at my local polling place. (San Francisco has a lot of polling locations, so between that and people voting by mail 120 is not a bad turnout.) There were something like three votes for Trump at that location in 2016. Today I was voter #35 there, and I expect the Trump vote will be less this time.

Earliest Viable Poop

There are two dogs in this household, with very different personalities. Dog walks highlight one of the biggest contrasts.

One dog boldly in the sidewalk, one trying to get back home.

In this end-of-dog-walk shot, I've leashed the dogs to a pillar while I put the garbage bins away. Willie stands in the center of the sidewalk, staring into the distance. Hazel is trying to get back into the house.

Willie is super skilled at mental maps. He probably cannot get himself lost (although he has been known to run off). When we traveled, in pre-covid times, Willie could always be counted on to know when we were back "home" even if it was at night, somewhere he's been inside of only once for a few minutes, and approaching from a different direction than he had visited it before.

Hazel, two years after adoption, now seems to almost never go up the neighbors stairs. Hazel likes a walk from time to time. She is always happy to go on the morning walk (okay, not happy on rainy days), although she sometimes needs some help to start moving towards the door. But come evening, she'll pointedly run away from the leashes.

Willie is usually — rainy days are an exception — happy to walk for as long as I'd like to walk, and I'm quite willing to walk a long time. Our evening walks are often around half a mile, and sometimes longer than a mile. Morning walks, such as in the above photo are just around the block.

Which brings me to "Earliest Viable Poop".

In corporate nomenclature, the "minimum viable product" is the least advanced version of something a company thinks they can get money for. Companies like Apple don't generally release the minimum, but you can be sure a lot of apps in the Apple App Store are minimum viable. The idea behind such is "release early and use the revenue to pay for the development of more features."

Hazel clearly prefers to poop outside, but if the outside is unavailable or too unpleasant, she'll just use that bathmat next to the toilet. (That's what that room is for, right?) That's the Earliest Viable Poop for Hazel, the poop before the walk even starts. If she was releasing smart phone apps, they'd do one thing, and just barely do it all.

Willie, he will make it clear when he wants to go out and when he needs to to out. And once out, if only at the "wants" stage, he uses his mental map to make a good guess about the walk length. Even if it's not a route he's walked before, he is good at sensing if it is now the return trip. When he guesses that it is past half-way (or on a route he knows well, more than three-quarters) then he starts to really pay attention to the good spots. Even in rain, where he has what we call "efficient" walks, the earliest viable poop is a half block away (which is also about the distance of the last viable poop on a regular return trip). He takes his time to find the right spot, and has standards about the whole business. His threshold for minimum product would not be solely based on the minimum a low discerning customer would accept, but the minimum someone with real choice would consider.

I like to think about these things on long meditative walks with Willie. I know there is a place for the barely complete solution, but remember it's on par with pooping on the bathroom floor. Technology and scat have more in common than people think. A bunch of stuff goes in, gets digested, and then a release is made to the world, sometimes with a lot of care about how it lands, sometimes not.