git: 850eb149e7ab - main - mfiutil(4)/mrsasutil(4): "show drives" truncates information

From: Michael Osipov <michaelo_at_FreeBSD.org>
Date: Sat, 11 Apr 2026 18:28:44 UTC
The branch main has been updated by michaelo:

URL: https://cgit.FreeBSD.org/src/commit/?id=850eb149e7ab0733fcf9469a607dca223ff467ad

commit 850eb149e7ab0733fcf9469a607dca223ff467ad
Author:     Michael Osipov <michaelo@FreeBSD.org>
AuthorDate: 2026-04-09 09:19:36 +0000
Commit:     Michael Osipov <michaelo@FreeBSD.org>
CommitDate: 2026-04-11 18:28:03 +0000

    mfiutil(4)/mrsasutil(4): "show drives" truncates information
    
    Improve mfi_pd_inq_string() by
    * Reusing buffer sizes from cam/cam.h according to SCSI specification + NULL byte
    * Don't truncate vendor-specific information by escaping into a too small buffer
    * Use cam_strvis() from libcam instead of old, outdated local copy
    * Recaculate size of inq_string based on the reused buffer sizes and
      format statements
    
    PR:             294354
    Reviewed by:    imp
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D56328
---
 usr.sbin/mfiutil/Makefile    |  2 +-
 usr.sbin/mfiutil/mfi_drive.c | 59 +++++++++-----------------------------------
 2 files changed, 13 insertions(+), 48 deletions(-)

diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile
index 49c0e688e8e2..d7ccb1f2d9c1 100644
--- a/usr.sbin/mfiutil/Makefile
+++ b/usr.sbin/mfiutil/Makefile
@@ -9,7 +9,7 @@ MLINKS=	mfiutil.8 mrsasutil.8
 
 CFLAGS.gcc+= -fno-builtin-strftime
 
-LIBADD=	sbuf util
+LIBADD=	cam sbuf util
 
 # Here be dragons
 .ifdef DEBUG
diff --git a/usr.sbin/mfiutil/mfi_drive.c b/usr.sbin/mfiutil/mfi_drive.c
index c7c5aeb02f14..88d24623ae27 100644
--- a/usr.sbin/mfiutil/mfi_drive.c
+++ b/usr.sbin/mfiutil/mfi_drive.c
@@ -42,6 +42,7 @@
 #include <string.h>
 #include <strings.h>
 #include <unistd.h>
+#include <cam/cam.h>
 #include <cam/scsi/scsi_all.h>
 #include "mfiutil.h"
 
@@ -279,50 +280,14 @@ mfi_pd_get_info(int fd, uint16_t device_id, struct mfi_pd_info *info,
 	    sizeof(struct mfi_pd_info), mbox, 2, statusp));
 }
 
-static void
-cam_strvis(char *dst, const char *src, int srclen, int dstlen)
-{
-
-	/* Trim leading/trailing spaces, nulls. */
-	while (srclen > 0 && src[0] == ' ')
-		src++, srclen--;
-	while (srclen > 0
-	    && (src[srclen-1] == ' ' || src[srclen-1] == '\0'))
-		srclen--;
-
-	while (srclen > 0 && dstlen > 1) {
-		char *cur_pos = dst;
-
-		if (*src < 0x20) {
-			/* SCSI-II Specifies that these should never occur. */
-			/* non-printable character */
-			if (dstlen > 4) {
-				*cur_pos++ = '\\';
-				*cur_pos++ = ((*src & 0300) >> 6) + '0';
-				*cur_pos++ = ((*src & 0070) >> 3) + '0';
-				*cur_pos++ = ((*src & 0007) >> 0) + '0';
-			} else {
-				*cur_pos++ = '?';
-			}
-		} else {
-			/* normal character */
-			*cur_pos++ = *src;
-		}
-		src++;
-		srclen--;
-		dstlen -= cur_pos - dst;
-		dst = cur_pos;
-	}
-	*dst = '\0';
-}
-
 /* Borrowed heavily from scsi_all.c:scsi_print_inquiry(). */
 const char *
 mfi_pd_inq_string(struct mfi_pd_info *info)
 {
 	struct scsi_inquiry_data iqd, *inq_data = &iqd;
-	char vendor[16], product[48], revision[16], rstr[12], serial[SID_VENDOR_SPECIFIC_0_SIZE];
-	static char inq_string[64];
+	char vendor[SID_VENDOR_SIZE+1], product[SID_PRODUCT_SIZE+1],
+		 revision[SID_REVISION_SIZE+1], rstr[9], serial[SID_VENDOR_SPECIFIC_0_SIZE+1];
+	static char inq_string[80];
 
 	memcpy(inq_data, info->inquiry_data,
 	    (sizeof (iqd) <  sizeof (info->inquiry_data))?
@@ -334,14 +299,14 @@ mfi_pd_inq_string(struct mfi_pd_info *info)
 	if (SID_QUAL(inq_data) != SID_QUAL_LU_CONNECTED)
 		return (NULL);
 
-	cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
-	    sizeof(vendor));
-	cam_strvis(product, inq_data->product, sizeof(inq_data->product),
-	    sizeof(product));
-	cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
-	    sizeof(revision));
-	cam_strvis(serial, (char *)inq_data->vendor_specific0, sizeof(inq_data->vendor_specific0),
-	    sizeof(serial));
+	cam_strvis_flag(vendor, inq_data->vendor, sizeof(inq_data->vendor),
+	    sizeof(vendor), CAM_STRVIS_FLAG_NONASCII_TRIM);
+	cam_strvis_flag(product, inq_data->product, sizeof(inq_data->product),
+	    sizeof(product), CAM_STRVIS_FLAG_NONASCII_TRIM);
+	cam_strvis_flag(revision, inq_data->revision, sizeof(inq_data->revision),
+	    sizeof(revision), CAM_STRVIS_FLAG_NONASCII_TRIM);
+	cam_strvis_flag(serial, (char *)inq_data->vendor_specific0, sizeof(inq_data->vendor_specific0),
+	    sizeof(serial), CAM_STRVIS_FLAG_NONASCII_SPC);
 
 	/* Hack for SATA disks, no idea how to tell speed. */
 	if (strcmp(vendor, "ATA") == 0) {