Re: [PATCH v2 RESEND] usbip: make remote list honor parsable output
From: Jason Colapietro
Date: Tue Aug 11 2026 - 23:24:09 EST
On 8/11/26 16:48, Shuah Khan wrote:
> What happens without this patch? Can you elaborate with some examples?
-p is accepted in every list mode and `usbip help list` documents it as
"Parsable list format", but it only ever reached the local (-l) and gadget
(-d) paths. list_exported_devices() never took the flag, so -r ignores it
and always prints the human-readable report.
That is what the reporter hit in bugzilla 219502 -- same flag, same command,
two different formats depending on -l vs -r:
[root@usb1 adminlocal]# /usr/sbin/usbip list -p -l
busid=1-2#usbid=1a86:55d4#
busid=2-1#usbid=0627:0001#
busid=2-3#usbid=11b0:6298#
busid=2-4#usbid=12d1:1506#
[root@usb1 adminlocal]# /usr/sbin/usbip list -p -r localhost
Exportable USB devices
======================
- localhost
2-3: ATECH FLASH TECHNOLOGY : Kingston SNA-DC/U (11b0:6298)
: /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-3
: (Defined at Interface level) (00/00/00)
I reproduced that here: `usbip list -r <host>` and `usbip list -p -r <host>`
produce byte-identical output, so -p is a no-op on the one listing mode a
script is most likely to want it for. Automating attach against a remote host
means scraping the decorated report instead -- the column padding, the
" - <host>" banner, the blank line between devices, the per-interface lines.
After the patch, -r honours -p and emits the record shape local already uses:
$ usbip list -p -r 127.0.0.1
busid=1-1#usbid=0781:5583#
busid=1-2#usbid=046d:c52b#
so the obvious loop works against a remote host:
for b in $(usbip list -p -r "$host" | sed 's/^busid=//; s/#.*//'); do
usbip attach -r "$host" -b "$b"
done
On the same device set, `usbip list -p -l` and `usbip list -p -r <host>` are
now byte-identical -- one format for both sides.
Three things I checked:
- Without -p the remote output is unchanged; before and after diff clean.
- The connection stays in sync. Interface records are still read from the
socket in parsable mode, only the printf is suppressed. To confirm that
rather than assert it, I had the test server withhold the final 4-byte
usbip_usb_interface record for 3 seconds: the patched client with -p blocks
for the full 3 seconds, so it really is draining every record.
- With no exported devices, -p prints nothing on stdout ("no exportable
devices found on <host>" still goes to stderr), so stdout stays clean.
While checking that, I found the option order is a bug in its own right:
usbip_list() acts on -r, -l and -d the moment getopt_long() returns them, so
anything parsed afterwards is ignored. -p only works if it comes first --
"usbip list -r <host> -p" silently gives you the decorated report, and -l
and -d behave the same way. I have fixed that as a second patch in v3: the
mode is recorded during the option loop and run once parsing has finished,
so -p applies wherever it appears. When several mode selectors are given the
first one still wins, as before. Both orders and the long forms now produce
the same records, and the human output is untouched.
Testing disclosure: my checkout is on macOS, so I have not run a native
USB/IP stack end to end. The numbers above come from building the real
usbip_list.c, usbip_network.c, usbip_common.c and names.c against a stub
libudev -- the remote path never calls udev, and the stubs abort if reached
-- and pointing that binary at a small mock usbipd answering OP_REQ_DEVLIST
with a real OP_REP_DEVLIST payload. The -p -l side is a second build with a
fake udev backend presenting the same devices. So it is the real listing path
over a real socket, but not usbip-host/usbip-vudc on hardware. Happy to redo
the runs on a Linux box, or to have someone with a usbip setup confirm,
before this goes in.
I will send v3 as a two-patch series with a condensed before/after folded
into the first commit message, unless you would rather see the ordering fix
kept separate.
thanks,
Jason