Friday, January 16, 2009

usb drives with udev

Hey, finally I managed to actually get something out of udev, which I think is great but I don't really understand yet.
I have an 2.5'' hard drive in an external usb box. I carry this from my workplace home and back again and some stuff in it needs to point to the same absolute path, so it has to be mounted on the same mountpoint. Well, the disk has 2 partitions and I'm actually interested only in the partition /dev/sdc5. It has to be mounted in /media/usb-5, but kde's automounter mounts it in /media/disk. Of course I can ignore kde's automount feature and mount it manually after putting the corresponding entry in /etc/fstab, but I like this kde pop-up, click accept and it's done.
After reading this one, I figure out how to do it:
1. I get the relevant information with udevinfo:
fixdebian:/etc/udev/rules.d# udevinfo -a -p /sys/block/sdc/sdc5

Udevinfo 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 '/block/sdc/sdc5':
KERNEL=="sdc5"
SUBSYSTEM=="block"
DRIVER==""
ATTR{dev}=="8:37"
ATTR{start}=="26619831"
ATTR{size}=="51520329"
ATTR{stat}==" 537 537 0 0"

looking at parent device '/block/sdc':
KERNELS=="sdc"
SUBSYSTEMS=="block"
DRIVERS==""
ATTRS{dev}=="8:32"
ATTRS{range}=="16"
ATTRS{removable}=="0"
ATTRS{size}=="78140160"
ATTRS{stat}==" 59 776 1263 747 0 0 0 0 0 636 747"
ATTRS{capability}=="12"

looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1/1-3/1-3:1.0/host4/target4:0:0/4:0:0:0':
KERNELS=="4:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{device_blocked}=="0"
ATTRS{type}=="0"
ATTRS{scsi_level}=="0"
ATTRS{vendor}=="TOSHIBA "
ATTRS{model}=="MK4025GAS "
ATTRS{rev}=="0000"
ATTRS{state}=="running"
ATTRS{timeout}=="30"
ATTRS{iocounterbits}=="32"
ATTRS{iorequest_cnt}=="0x42"
ATTRS{iodone_cnt}=="0x42"
ATTRS{ioerr_cnt}=="0x0"
ATTRS{modalias}=="scsi:t-0x00"
ATTRS{evt_media_change}=="0"
ATTRS{queue_depth}=="1"
ATTRS{queue_type}=="none"
ATTRS{max_sectors}=="240"


(.... and a lot more output that I don't need now).
I pick both lines: ATTRS{vendor}=="TOSHIBA " and
ATTRS{model}=="MK4025GAS "

2. I create a file in /etc/udev/rules.d/ called 010_myusb-disk-part5.rules. The man page says that files included there are read in lexical order, so I guess it could be useful to be one of the first rules that apply to avoid any 'interference' from another file already included by the default udev installation. (Actually, at least in debian, the files included in /etc/udev/rules.d are soft links to files in the parent directory: you don't need to remove the whole file if you don't like it, just remove the link). The file is:
fixdebian:/etc/udev/rules.d# cat 010_myusb-disk-part5.rules
ACTION=="add", KERNEL=="sdc5", ENV{vendor}=="TOSHIBA ", ENV{model}=="MK4025GAS ", RUN+="/home/user/bin/mount-usb-5.sh"


3. The file /home/user/bin/mount-usb-5.sh is a simple executable script with the single line: mount /media/usb-5.
4. Run the udev test:

fixdebian:/etc/udev/rules.d# udevtest /sys/block/sdc/sdc5
parse_file: reading '/etc/udev/rules.d/010_myusb-disk-part5.rules' as rules file
parse_file: reading '/etc/udev/rules.d/020_permissions.rules' as rules file
parse_file: reading '/etc/udev/rules.d/025_libgphoto2.rules' as rules file

(...)
This program is for debugging only, it does not create any node,
or run any program specified by a RUN key. It may show incorrect results,
if rules match against subsystem specfic kernel event variables.

main: looking at device '/block/sdc/sdc5' from subsystem 'block'
udev_rules_get_name: no node name set, will use kernel name 'sdc5'
udev_db_get_device: found a symlink as db file
udev_device_event: device '/block/sdc/sdc5' already in database, validate currently present symlinks
udev_node_add: creating device node '/dev/sdc5', major = '8', minor = '37', mode = '0660', uid = '0', gid = '25'
main: run: 'socket:/org/freedesktop/hal/udev_event'

So this seems to work: at least the syntax of my new file isn't wrong. 5. Restart udev: in my debian box, I run /etc/init.d/udev restart 6. Now I plug in the usb drive, kde's mount pop-up window appears, I accect and, the drive is mounted in /media/usb-5, just as I wanted.

Friday, January 2, 2009

Environment variables a process runs with

Recently I had a problem with a certain process that could be launched it two different ways: from command line and from a graphical client application. When launched from the command line it didn't quite work, but it did when started via the graphical client application. I knew that it was an environment variable issue, but I didn't know how I could find out with which environment variables a certain process was running.
I guessed that I could find something it the /proc directory, so I got into and found that for each running process there's a file called 'environ', which can be found in /proc/PID/environ. Ok, so that's fine and it would be a great solution, provided my problem was in a linux box, but it was Solaris 5.9 machine, and in solaris the /proc file, though it exists, it's not so full of information as in linux. And there was no environ file.
Fortunately I found on the web (I don't have the url anymore, sorry) that you can do something like:

ps wwe
to get the what I was looking for, and this works on linux and solaris. For example, to get the environment of my running bash session:

testing@fixdebian:~$ ps wwe $$

PID TTY STAT TIME COMMAND
27857 pts/6 S 0:00 -su TERM=xterm PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games LANG=es_ES@euro MAIL=/var/mail/testing HOME=/home/testing SHELL=/bin/bash USER=testing LOGNAME=testing


which is far more elegant. And this solved my problem in a more general way.