OpenBSD's hotplugd rocks! — GNUcode.me

OpenBSD's hotplugd rocks!

by Joshua Branson — April 13, 2023

My last post talked about how I broke my OpenBSD laptop by telling OpenBSD that my usbstick was essential to the boot process, and then, when I booted the laptop, I did not have that usb stick mounted. That caused some problems. I since learned that the preferred way of automounting a usb stick under OpenBSD is with hotplugd.

hotplugd is OpenBSD’s automounting functionality, and it’s actually super simple and easy. Just put your scripts at /etc/hotplugd/attach and /etc/hotplugd/detach. And the man page gives you an example shell script, but since I am not a big fan of sh (its syntax is confusing), I decided to write my attach script in GNU Guile. Writing that script made me want to write more scripts in scheme shell, but I the last time I tried to install the scheme shell on OpenBSD, it failed to compile.

Anyway, it is really easy to write your own script. hotplugd will call your script like so:

attach <number> <label>

where <number> is one of the numbers in the table below and <label> is a short descriptive string of the device.

|---+------------------------------------|
| 0 | generic, no special info           |
|---+------------------------------------|
| 1 | CPU (carries resource utilization) |
|---+------------------------------------|
| 2 | disk drive                         |
|---+------------------------------------|
| 3 | network interface                  |
|---+------------------------------------|
| 4 | tape device                        |
|---+------------------------------------|
| 5 | serial line interface              |
|---+------------------------------------|

I am only really interested in 2 and 3. Here is how I debbuged my attach script, and you can easily do the same.

First find out what sd device your usb stick is. Before you put in your usb stick type in:

sysctl hw.disknames

hw.disknames=sd0:ec557d42f5cbfa41,sd1:5583d235b610c8a2

Now put in your usb stick and run the same command.

sysctl hw.disknames

hw.disknames=sd0:ec557d42f5cbfa41,sd1:5583d235b610c8a2,sd2:

So now I know that my usb stick is sd2. Let’s do a disklabel command on it:

# disklabel sd2

# /dev/rsd2c:
type: SCSI
disk: SCSI disk
label: USB Flash Drive
duid: 0000000000000000
flags:
bytes/sector: 512
sectors/track: 63
tracks/cylinder: 255
sectors/cylinder: 16065
cylinders: 1887
total sectors: 30326784
boundstart: 0
boundend: 30326784

16 partitions:
#                size           offset  fstype [fsize bsize   cpg]
  c:            14.5G                0  unused
  i:            14.5G             2048   MSDOS

Notice from the output that this label is “USB Flash Drive”. That is the label that hotplugd will send to your attach script.

If you want a usb stick that is read-able/writeable accross all operating systems, currently you will want to use the vfat filesystem. That is what the output above shows. The fstype of MSDOS is a vfat filesystem. This usb stick is what I will use when I want to copy data between different OS-es (I do want an encrypted OpenBSD-specific usb stick to store my gpg keys, but I have not yet set that up). According to some of the smart people on the #openbsd irc channel, if you have such a usb stick, then the i filesystem partition is the one that you want to mount to read the data. And we see that above as well (c is code for the whole drive. /dev/rsd2c is how you access the whole and raw disk).

Ok, so now that you know what arguments that hotplugd will send your script, go ahead and write your basic script. It probably won’t be perfect, which is ok. To test it, type in su in your terminal to get to root account, and then test your script in the exact same way that OpenBSD will use your script (# means that you are currently the root user):

# ./attach 2 "USB Flash Drive"

You will probably get some weird errors, and that’s ok. After you have run your attach script, and it seemed to have no errors, verify that it properly mounted with:

mount

/dev/sd1a on / type ffs (local, softdep)
/dev/sd1k on /home type ffs (local, nodev, nosuid, softdep)
/dev/sd1d on /tmp type ffs (local, nodev, nosuid, softdep)
/dev/sd1f on /usr type ffs (local, nodev, softdep)
/dev/sd1g on /usr/X11R6 type ffs (local, nodev, softdep)
/dev/sd1h on /usr/local type ffs (local, nodev, wxallowed, softdep)
/dev/sd1j on /usr/obj type ffs (local, nodev, nosuid, softdep)
/dev/sd1i on /usr/src type ffs (local, nodev, nosuid, softdep)
/dev/sd1e on /var type ffs (local, nodev, nosuid, softdep)
/dev/sd2i on /mnt/usb type msdos (local, nodev, noexec)

And it look like I properly mounted my usb stick (the last line says it was).

One thing that users might find confusing is that OpenBSD passes in 2, but Guile accepted the 2 as a string.

My simple attach script works for me. It will only auto mount vfat filesystems, and I am pretty sure that weird things will happen if I plug in two usb sticks at once, but it works.