* [PATCH v2 RESEND] usbip: make remote list honor parsable output
@ 2026-08-11 3:42 Jason Colapietro
2026-08-11 22:48 ` Shuah Khan
0 siblings, 1 reply; 4+ messages in thread
From: Jason Colapietro @ 2026-08-11 3:42 UTC (permalink / raw)
To: Valentina Manea, Shuah Khan
Cc: Hongren Zheng, Greg KH, linux-usb, linux-kernel, stable
The -p option only affects local devices and gadgets. Remote lists still
print their human-readable headings and details, so scripts cannot parse
them using the documented option.
Pass the parsable flag through the remote listing path. Emit the same busid
and usbid record used for local devices while continuing to consume every
interface record from the server.
Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219502
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5
Signed-off-by: Jason Colapietro <jasoncola1@gmail.com>
---
Changes in v2:
- Make the email From header match Signed-off-by.
- Add Cc: stable@vger.kernel.org.
tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index 3d810bcca02..b9d60b87e47 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -41,7 +41,7 @@ void usbip_list_usage(void)
printf("usage: %s", usbip_list_usage_string);
}
-static int get_exported_devices(char *host, int sockfd)
+static int get_exported_devices(char *host, int sockfd, bool parsable)
{
char product_name[100];
char class_name[100];
@@ -80,9 +80,11 @@ static int get_exported_devices(char *host, int sockfd)
return 0;
}
- printf("Exportable USB devices\n");
- printf("======================\n");
- printf(" - %s\n", host);
+ if (!parsable) {
+ printf("Exportable USB devices\n");
+ printf("======================\n");
+ printf(" - %s\n", host);
+ }
for (i = 0; i < reply.ndev; i++) {
memset(&udev, 0, sizeof(udev));
@@ -98,9 +100,14 @@ static int get_exported_devices(char *host, int sockfd)
usbip_names_get_class(class_name, sizeof(class_name),
udev.bDeviceClass, udev.bDeviceSubClass,
udev.bDeviceProtocol);
- printf("%11s: %s\n", udev.busid, product_name);
- printf("%11s: %s\n", "", udev.path);
- printf("%11s: %s\n", "", class_name);
+ if (parsable) {
+ printf("busid=%s#usbid=%04x:%04x#\n", udev.busid,
+ udev.idVendor, udev.idProduct);
+ } else {
+ printf("%11s: %s\n", udev.busid, product_name);
+ printf("%11s: %s\n", "", udev.path);
+ printf("%11s: %s\n", "", class_name);
+ }
for (j = 0; j < udev.bNumInterfaces; j++) {
rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
@@ -116,16 +123,18 @@ static int get_exported_devices(char *host, int sockfd)
uintf.bInterfaceClass,
uintf.bInterfaceSubClass,
uintf.bInterfaceProtocol);
- printf("%11s: %2d - %s\n", "", j, class_name);
+ if (!parsable)
+ printf("%11s: %2d - %s\n", "", j, class_name);
}
- printf("\n");
+ if (!parsable)
+ printf("\n");
}
return 0;
}
-static int list_exported_devices(char *host)
+static int list_exported_devices(char *host, bool parsable)
{
int rc;
int sockfd;
@@ -138,7 +147,7 @@ static int list_exported_devices(char *host)
}
dbg("connected to %s:%s", host, usbip_port_string);
- rc = get_exported_devices(host, sockfd);
+ rc = get_exported_devices(host, sockfd, parsable);
if (rc < 0) {
err("failed to get device list from %s", host);
return -1;
@@ -351,7 +360,7 @@ int usbip_list(int argc, char *argv[])
parsable = true;
break;
case 'r':
- ret = list_exported_devices(optarg);
+ ret = list_exported_devices(optarg, parsable);
goto out;
case 'l':
ret = list_devices(parsable);
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 RESEND] usbip: make remote list honor parsable output
2026-08-11 3:42 [PATCH v2 RESEND] usbip: make remote list honor parsable output Jason Colapietro
@ 2026-08-11 22:48 ` Shuah Khan
2026-08-12 3:30 ` Jason Colapietro
0 siblings, 1 reply; 4+ messages in thread
From: Shuah Khan @ 2026-08-11 22:48 UTC (permalink / raw)
To: Jason Colapietro, Valentina Manea, Shuah Khan
Cc: Hongren Zheng, Greg KH, linux-usb, linux-kernel, stable,
Shuah Khan
On 8/10/26 21:42, Jason Colapietro wrote:
> The -p option only affects local devices and gadgets. Remote lists still
> print their human-readable headings and details, so scripts cannot parse
> them using the documented option.
>
> Pass the parsable flag through the remote listing path. Emit the same busid
> and usbid record used for local devices while continuing to consume every
> interface record from the server.
What happens without this patch? Can you elaborate with some examples?
>
> Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0")
> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219502
> Cc: stable@vger.kernel.org
> Assisted-by: Codex:gpt-5
> Signed-off-by: Jason Colapietro <jasoncola1@gmail.com>
> ---
> Changes in v2:
> - Make the email From header match Signed-off-by.
> - Add Cc: stable@vger.kernel.org.
>
> tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
> 1 file changed, 21 insertions(+), 12 deletions(-)
>
> diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
> index 3d810bcca02..b9d60b87e47 100644
> --- a/tools/usb/usbip/src/usbip_list.c
> +++ b/tools/usb/usbip/src/usbip_list.c
> @@ -41,7 +41,7 @@ void usbip_list_usage(void)
> printf("usage: %s", usbip_list_usage_string);
> }
>
> -static int get_exported_devices(char *host, int sockfd)
> +static int get_exported_devices(char *host, int sockfd, bool parsable)
> {
> char product_name[100];
> char class_name[100];
> @@ -80,9 +80,11 @@ static int get_exported_devices(char *host, int sockfd)
> return 0;
> }
>
> - printf("Exportable USB devices\n");
> - printf("======================\n");
> - printf(" - %s\n", host);
> + if (!parsable) {
> + printf("Exportable USB devices\n");
> + printf("======================\n");
> + printf(" - %s\n", host);
> + }
>
> for (i = 0; i < reply.ndev; i++) {
> memset(&udev, 0, sizeof(udev));
> @@ -98,9 +100,14 @@ static int get_exported_devices(char *host, int sockfd)
> usbip_names_get_class(class_name, sizeof(class_name),
> udev.bDeviceClass, udev.bDeviceSubClass,
> udev.bDeviceProtocol);
> - printf("%11s: %s\n", udev.busid, product_name);
> - printf("%11s: %s\n", "", udev.path);
> - printf("%11s: %s\n", "", class_name);
> + if (parsable) {
> + printf("busid=%s#usbid=%04x:%04x#\n", udev.busid,
> + udev.idVendor, udev.idProduct);
> + } else {
> + printf("%11s: %s\n", udev.busid, product_name);
> + printf("%11s: %s\n", "", udev.path);
> + printf("%11s: %s\n", "", class_name);
> + }
>
> for (j = 0; j < udev.bNumInterfaces; j++) {
> rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
> @@ -116,16 +123,18 @@ static int get_exported_devices(char *host, int sockfd)
> uintf.bInterfaceClass,
> uintf.bInterfaceSubClass,
> uintf.bInterfaceProtocol);
> - printf("%11s: %2d - %s\n", "", j, class_name);
> + if (!parsable)
> + printf("%11s: %2d - %s\n", "", j, class_name);
> }
>
> - printf("\n");
> + if (!parsable)
> + printf("\n");
> }
>
> return 0;
> }
>
> -static int list_exported_devices(char *host)
> +static int list_exported_devices(char *host, bool parsable)
> {
> int rc;
> int sockfd;
> @@ -138,7 +147,7 @@ static int list_exported_devices(char *host)
> }
> dbg("connected to %s:%s", host, usbip_port_string);
>
> - rc = get_exported_devices(host, sockfd);
> + rc = get_exported_devices(host, sockfd, parsable);
> if (rc < 0) {
> err("failed to get device list from %s", host);
> return -1;
> @@ -351,7 +360,7 @@ int usbip_list(int argc, char *argv[])
> parsable = true;
> break;
> case 'r':
> - ret = list_exported_devices(optarg);
> + ret = list_exported_devices(optarg, parsable);
> goto out;
> case 'l':
> ret = list_devices(parsable);
thanks,
-- Shuah
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2 RESEND] usbip: make remote list honor parsable output
@ 2026-08-12 3:23 Jason Colapietro
0 siblings, 0 replies; 4+ messages in thread
From: Jason Colapietro @ 2026-08-12 3:23 UTC (permalink / raw)
To: skhan, Shuah Khan, Valentina Manea
Cc: Hongren Zheng, Greg KH, linux-usb, linux-kernel, stable
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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2 RESEND] usbip: make remote list honor parsable output
2026-08-11 22:48 ` Shuah Khan
@ 2026-08-12 3:30 ` Jason Colapietro
0 siblings, 0 replies; 4+ messages in thread
From: Jason Colapietro @ 2026-08-12 3:30 UTC (permalink / raw)
To: Shuah Khan
Cc: Valentina Manea, Shuah Khan, Hongren Zheng, Greg KH, linux-usb,
linux-kernel, stable
Jason Colapietro <jasoncola1@gmail.com>
11:26 PM (1 minute ago)
to Shuah, Valentina, skhan, Hongren, Greg, linux-usb, linux-kernel, stable
The -p option only affects local devices and gadgets. Remote lists still
print their human-readable headings and details, so scripts cannot parse
them using the documented option.
Pass the parsable flag through the remote listing path. Emit the same busid
and usbid record used for local devices while continuing to consume every
interface record from the server.
Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0")
Closes: https://www.google.com/url?q=https://bugzilla.kernel.org/show_bug.cgi?id%3D219502&source=gmail&ust=1786591574713000&sa=E
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5
Signed-off-by: Jason Colapietro <jasoncola1@gmail.com>
---
Changes in v3:
- No functional change; resent as 1/2 of a series.
- 2/2 makes -p work regardless of where it appears on the command line.
tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index 3d810bcca02..b9d60b87e47 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -41,7 +41,7 @@ void usbip_list_usage(void)
printf("usage: %s", usbip_list_usage_string);
}
-static int get_exported_devices(char *host, int sockfd)
+static int get_exported_devices(char *host, int sockfd, bool parsable)
{
char product_name[100];
char class_name[100];
@@ -80,9 +80,11 @@ static int get_exported_devices(char *host, int sockfd)
return 0;
}
- printf("Exportable USB devices\n");
- printf("======================\n");
- printf(" - %s\n", host);
+ if (!parsable) {
+ printf("Exportable USB devices\n");
+ printf("======================\n");
+ printf(" - %s\n", host);
+ }
for (i = 0; i < reply.ndev; i++) {
memset(&udev, 0, sizeof(udev));
@@ -98,9 +100,14 @@ static int get_exported_devices(char *host, int sockfd)
usbip_names_get_class(class_name, sizeof(class_name),
udev.bDeviceClass, udev.bDeviceSubClass,
udev.bDeviceProtocol);
- printf("%11s: %s\n", udev.busid, product_name);
- printf("%11s: %s\n", "", udev.path);
- printf("%11s: %s\n", "", class_name);
+ if (parsable) {
+ printf("busid=%s#usbid=%04x:%04x#\n", udev.busid,
+ udev.idVendor, udev.idProduct);
+ } else {
+ printf("%11s: %s\n", udev.busid, product_name);
+ printf("%11s: %s\n", "", udev.path);
+ printf("%11s: %s\n", "", class_name);
+ }
for (j = 0; j < udev.bNumInterfaces; j++) {
rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
@@ -116,16 +123,18 @@ static int get_exported_devices(char *host, int sockfd)
uintf.bInterfaceClass,
uintf.bInterfaceSubClass,
uintf.bInterfaceProtocol);
- printf("%11s: %2d - %s\n", "", j, class_name);
+ if (!parsable)
+ printf("%11s: %2d - %s\n", "", j, class_name);
}
- printf("\n");
+ if (!parsable)
+ printf("\n");
}
return 0;
}
-static int list_exported_devices(char *host)
+static int list_exported_devices(char *host, bool parsable)
{
int rc;
int sockfd;
@@ -138,7 +147,7 @@ static int list_exported_devices(char *host)
}
dbg("connected to %s:%s", host, usbip_port_string);
- rc = get_exported_devices(host, sockfd);
+ rc = get_exported_devices(host, sockfd, parsable);
if (rc < 0) {
err("failed to get device list from %s", host);
return -1;
@@ -351,7 +360,7 @@ int usbip_list(int argc, char *argv[])
parsable = true;
break;
case 'r':
- ret = list_exported_devices(optarg);
+ ret = list_exported_devices(optarg, parsable);
goto out;
case 'l':
ret = list_devices(parsable);
--
2.50.1 (Apple Git-155)
-Jason
On Tue, Aug 11, 2026 at 6:48 PM Shuah Khan <skhan@linuxfoundation.org> wrote:
>
> On 8/10/26 21:42, Jason Colapietro wrote:
> > The -p option only affects local devices and gadgets. Remote lists still
> > print their human-readable headings and details, so scripts cannot parse
> > them using the documented option.
> >
> > Pass the parsable flag through the remote listing path. Emit the same busid
> > and usbid record used for local devices while continuing to consume every
> > interface record from the server.
>
> What happens without this patch? Can you elaborate with some examples?
>
> >
> > Fixes: e9837bbb3e69 ("staging: usbip: userspace tools v1.0.0")
> > Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219502
> > Cc: stable@vger.kernel.org
> > Assisted-by: Codex:gpt-5
> > Signed-off-by: Jason Colapietro <jasoncola1@gmail.com>
> > ---
> > Changes in v2:
> > - Make the email From header match Signed-off-by.
> > - Add Cc: stable@vger.kernel.org.
> >
> > tools/usb/usbip/src/usbip_list.c | 33 ++++++++++++++++++++------------
> > 1 file changed, 21 insertions(+), 12 deletions(-)
> >
> > diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
> > index 3d810bcca02..b9d60b87e47 100644
> > --- a/tools/usb/usbip/src/usbip_list.c
> > +++ b/tools/usb/usbip/src/usbip_list.c
> > @@ -41,7 +41,7 @@ void usbip_list_usage(void)
> > printf("usage: %s", usbip_list_usage_string);
> > }
> >
> > -static int get_exported_devices(char *host, int sockfd)
> > +static int get_exported_devices(char *host, int sockfd, bool parsable)
> > {
> > char product_name[100];
> > char class_name[100];
> > @@ -80,9 +80,11 @@ static int get_exported_devices(char *host, int sockfd)
> > return 0;
> > }
> >
> > - printf("Exportable USB devices\n");
> > - printf("======================\n");
> > - printf(" - %s\n", host);
> > + if (!parsable) {
> > + printf("Exportable USB devices\n");
> > + printf("======================\n");
> > + printf(" - %s\n", host);
> > + }
> >
> > for (i = 0; i < reply.ndev; i++) {
> > memset(&udev, 0, sizeof(udev));
> > @@ -98,9 +100,14 @@ static int get_exported_devices(char *host, int sockfd)
> > usbip_names_get_class(class_name, sizeof(class_name),
> > udev.bDeviceClass, udev.bDeviceSubClass,
> > udev.bDeviceProtocol);
> > - printf("%11s: %s\n", udev.busid, product_name);
> > - printf("%11s: %s\n", "", udev.path);
> > - printf("%11s: %s\n", "", class_name);
> > + if (parsable) {
> > + printf("busid=%s#usbid=%04x:%04x#\n", udev.busid,
> > + udev.idVendor, udev.idProduct);
> > + } else {
> > + printf("%11s: %s\n", udev.busid, product_name);
> > + printf("%11s: %s\n", "", udev.path);
> > + printf("%11s: %s\n", "", class_name);
> > + }
> >
> > for (j = 0; j < udev.bNumInterfaces; j++) {
> > rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
> > @@ -116,16 +123,18 @@ static int get_exported_devices(char *host, int sockfd)
> > uintf.bInterfaceClass,
> > uintf.bInterfaceSubClass,
> > uintf.bInterfaceProtocol);
> > - printf("%11s: %2d - %s\n", "", j, class_name);
> > + if (!parsable)
> > + printf("%11s: %2d - %s\n", "", j, class_name);
> > }
> >
> > - printf("\n");
> > + if (!parsable)
> > + printf("\n");
> > }
> >
> > return 0;
> > }
> >
> > -static int list_exported_devices(char *host)
> > +static int list_exported_devices(char *host, bool parsable)
> > {
> > int rc;
> > int sockfd;
> > @@ -138,7 +147,7 @@ static int list_exported_devices(char *host)
> > }
> > dbg("connected to %s:%s", host, usbip_port_string);
> >
> > - rc = get_exported_devices(host, sockfd);
> > + rc = get_exported_devices(host, sockfd, parsable);
> > if (rc < 0) {
> > err("failed to get device list from %s", host);
> > return -1;
> > @@ -351,7 +360,7 @@ int usbip_list(int argc, char *argv[])
> > parsable = true;
> > break;
> > case 'r':
> > - ret = list_exported_devices(optarg);
> > + ret = list_exported_devices(optarg, parsable);
> > goto out;
> > case 'l':
> > ret = list_devices(parsable);
>
> thanks,
> -- Shuah
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-12 3:30 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11 3:42 [PATCH v2 RESEND] usbip: make remote list honor parsable output Jason Colapietro
2026-08-11 22:48 ` Shuah Khan
2026-08-12 3:30 ` Jason Colapietro
-- strict thread matches above, loose matches on Subject: below --
2026-08-12 3:23 Jason Colapietro
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox