Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP4:Update
sg3_utils.1568
0003-sg_inq-deal-with-invalid-strings-in-inquir...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0003-sg_inq-deal-with-invalid-strings-in-inquiry-data.patch of Package sg3_utils.1568
From dc3a4510cd0a5728ba37b395b18b12a2c3929fdb Mon Sep 17 00:00:00 2001 From: Hannes Reinecke <hare@suse.de> Date: Thu, 15 Oct 2015 11:41:50 +0200 Subject: sg_inq: deal with invalid strings in inquiry data Although the standard claims that all inquiry strings and the VPD page 0x80 should be ASCII strings experience shows that this it not necessarily true; some broken devices attempt to return unicode string in VPD page 0x80. The patch updates encode_whitespaces() to skip any NULL bytes in strings, and terminate the string after two NULLs. Additionally a new function encode_unicode() has been added to allow for a proper display of the raw string. Signed-off-by: Hannes Reinecke <hare@suse.de> --- src/sg_inq.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 27 deletions(-) diff --git a/src/sg_inq.c b/src/sg_inq.c index fe302ae..21c8c5e 100644 --- a/src/sg_inq.c +++ b/src/sg_inq.c @@ -1042,7 +1042,9 @@ dStrRaw(const char* str, int len) * whitespaces to a single "_"; convert non-printable characters to "." * and if there are no valid (i.e. printable) characters return 0. * Process 'str' in place (i.e. it's input and output) and return the - * length of the output, excluding the trailing '\0'. + * length of the output, excluding the trailing '\0'. To cover any + * potential unicode string an intermediate zero is skipped; two + * consecutive zeroes indicate a string termination. */ static int encode_whitespaces(unsigned char *str, int inlen) @@ -1050,11 +1052,15 @@ encode_whitespaces(unsigned char *str, int inlen) int k, res; int j = 0; int valid = 0; - int outlen = inlen; + int outlen = inlen, zeroes = 0; /* Skip initial whitespaces */ while (isblank(str[j])) j++; + /* Skip possible unicode prefix characters */ + while (str[j] < 0x20) + j++; + k = j; /* Strip trailing whitespaces */ while ((outlen > k) && @@ -1068,11 +1074,21 @@ encode_whitespaces(unsigned char *str, int inlen) str[res++] = '_'; valid++; } - } else if (! isprint(str[k])) + zeroes = 0; + } else if (! isprint(str[k])) { + if (str[k] == 0x00) { + /* Stop on more than one consecutive zero */ + if (zeroes) + break; + zeroes++; + continue; + } str[res++] = '.'; - else { + zeroes = 0; + } else { str[res++] = str[k]; valid++; + zeroes = 0; } } if (! valid) @@ -1083,6 +1099,31 @@ encode_whitespaces(unsigned char *str, int inlen) } static int +encode_unicode(unsigned char *str, int inlen) +{ + int k = 0, res; + int zeroes = 0; + + for (res = 0; k < inlen; ++k) { + if (str[k] == 0x00) { + if (zeroes) { + str[res++] = '\0'; + break; + } + zeroes++; + } else { + zeroes = 0; + if (isprint(str[k])) + str[res++] = str[k]; + else + str[res++] = ' '; + } + } + + return res; +} + +static int encode_string(char *out, const unsigned char *in, int inlen) { int i, j = 0; @@ -1834,23 +1875,26 @@ export_dev_ids(unsigned char * buff, int len, int verbose) } switch (desig_type) { case 0: /* vendor specific */ - if (i_len > 128) + if (i_len == 0 || i_len > 128) break; - printf("SCSI_IDENT_%s_VENDOR=", assoc_str); if ((2 == c_set) || (3 == c_set)) { /* ASCII or UTF-8 */ k = encode_whitespaces(ip, i_len); /* udev-conformant character encoding */ - for (m = 0; m < k; ++m) { - if ((ip[m] >= '0' && ip[m] <= '9') || - (ip[m] >= 'A' && ip[m] <= 'Z') || - (ip[m] >= 'a' && ip[m] <= 'z') || - strchr("#+-.:=@_", ip[m]) != NULL) - printf("%c", ip[m]); - else - printf("\\x%02x", ip[m]); + if (k > 0) { + printf("SCSI_IDENT_%s_VENDOR=", assoc_str); + for (m = 0; m < k; ++m) { + if ((ip[m] >= '0' && ip[m] <= '9') || + (ip[m] >= 'A' && ip[m] <= 'Z') || + (ip[m] >= 'a' && ip[m] <= 'z') || + strchr("#+-.:=@_", ip[m]) != NULL) + printf("%c", ip[m]); + else + printf("\\x%02x", ip[m]); + } + printf("\n"); } - printf("\n"); } else { + printf("SCSI_IDENT_%s_VENDOR=", assoc_str); for (m = 0; m < i_len; ++m) printf("%02x", (unsigned int)ip[m]); printf("\n"); @@ -2982,9 +3026,11 @@ std_inq_response(const struct opts_t * op, int act_len) xtra_buff[i] = ' '; if (op->do_export) { len = encode_whitespaces((unsigned char *)xtra_buff, 8); - printf("SCSI_VENDOR=%s\n", xtra_buff); - encode_string(xtra_buff, &rp[8], 8); - printf("SCSI_VENDOR_ENC=%s\n", xtra_buff); + if (len > 0) { + printf("SCSI_VENDOR=%s\n", xtra_buff); + encode_string(xtra_buff, &rp[8], 8); + printf("SCSI_VENDOR_ENC=%s\n", xtra_buff); + } } else printf(" Vendor identification: %s\n", xtra_buff); if (act_len <= 16) { @@ -2995,9 +3041,11 @@ std_inq_response(const struct opts_t * op, int act_len) xtra_buff[16] = '\0'; if (op->do_export) { len = encode_whitespaces((unsigned char *)xtra_buff, 16); - printf("SCSI_MODEL=%s\n", xtra_buff); - encode_string(xtra_buff, &rp[16], 16); - printf("SCSI_MODEL_ENC=%s\n", xtra_buff); + if (len > 0) { + printf("SCSI_MODEL=%s\n", xtra_buff); + encode_string(xtra_buff, &rp[16], 16); + printf("SCSI_MODEL_ENC=%s\n", xtra_buff); + } } else printf(" Product identification: %s\n", xtra_buff); } @@ -3009,7 +3057,8 @@ std_inq_response(const struct opts_t * op, int act_len) xtra_buff[4] = '\0'; if (op->do_export) { len = encode_whitespaces((unsigned char *)xtra_buff, 4); - printf("SCSI_REVISION=%s\n", xtra_buff); + if (len > 0) + printf("SCSI_REVISION=%s\n", xtra_buff); } else printf(" Product revision level: %s\n", xtra_buff); } @@ -3019,7 +3068,8 @@ std_inq_response(const struct opts_t * op, int act_len) 20); if (op->do_export) { len = encode_whitespaces((unsigned char *)xtra_buff, 20); - printf("VENDOR_SPECIFIC=%s\n", xtra_buff); + if (len > 0) + printf("VENDOR_SPECIFIC=%s\n", xtra_buff); } else printf(" Vendor specific: %s\n", xtra_buff); } @@ -3033,7 +3083,8 @@ std_inq_response(const struct opts_t * op, int act_len) if (op->do_export) { len = encode_whitespaces((unsigned char *)xtra_buff, act_len - 96); - printf("VENDOR_SPECIFIC=%s\n", xtra_buff); + if (len > 0) + printf("VENDOR_SPECIFIC=%s\n", xtra_buff); } else printf(" Vendor specific: %s\n", xtra_buff); } @@ -3464,6 +3515,7 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len) (1 == op->do_hex) ? 0 : -1); else { char obuff[DEF_ALLOC_LEN]; + int k, m; memset(obuff, 0, sizeof(obuff)); len -= 4; @@ -3471,10 +3523,25 @@ vpd_decode(int sg_fd, const struct opts_t * op, int inhex_len) len = sizeof(obuff) - 1; memcpy(obuff, rp + 4, len); if (op->do_export) { - len = encode_whitespaces((unsigned char *)obuff, len); - printf("SCSI_IDENT_SERIAL=%s\n", obuff); + k = encode_whitespaces((unsigned char *)obuff, len); + if (k > 0) { + printf("SCSI_IDENT_SERIAL="); + /* udev-conformant character encoding */ + for (m = 0; m < k; ++m) { + if ((obuff[m] >= '0' && obuff[m] <= '9') || + (obuff[m] >= 'A' && obuff[m] <= 'Z') || + (obuff[m] >= 'a' && obuff[m] <= 'z') || + strchr("#+-.:=@_", obuff[m]) != NULL) + printf("%c", obuff[m]); + else + printf("\\x%02x", obuff[m]); + } + printf("\n"); + } } else { - printf(" Unit serial number: %s\n", obuff); + k = encode_unicode((unsigned char *)obuff, len); + if (k > 0) + printf(" Unit serial number: %s\n", obuff); } } break; -- 1.8.4.5
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor