diff options
Diffstat (limited to 'freebsd/sys/cam/cam.c')
-rw-r--r-- | freebsd/sys/cam/cam.c | 125 |
1 files changed, 106 insertions, 19 deletions
diff --git a/freebsd/sys/cam/cam.c b/freebsd/sys/cam/cam.c index 18628cd0..71523db2 100644 --- a/freebsd/sys/cam/cam.c +++ b/freebsd/sys/cam/cam.c @@ -107,9 +107,6 @@ const struct cam_status_entry cam_status_table[] = { { CAM_SCSI_BUSY, "SCSI Bus Busy" }, }; -const int num_cam_status_entries = - sizeof(cam_status_table)/sizeof(*cam_status_table); - #ifdef _KERNEL SYSCTL_NODE(_kern, OID_AUTO, cam, CTLFLAG_RD, 0, "CAM Subsystem"); @@ -118,7 +115,6 @@ SYSCTL_NODE(_kern, OID_AUTO, cam, CTLFLAG_RD, 0, "CAM Subsystem"); #endif int cam_sort_io_queues = CAM_DEFAULT_SORT_IO_QUEUES; -TUNABLE_INT("kern.cam.sort_io_queues", &cam_sort_io_queues); SYSCTL_INT(_kern_cam, OID_AUTO, sort_io_queues, CTLFLAG_RWTUN, &cam_sort_io_queues, 0, "Sort IO queues to try and optimise disk access patterns"); #endif @@ -160,35 +156,125 @@ cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen) *dst = '\0'; } +void +cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen, + uint32_t flags) +{ + + /* 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) { + if (*src < 0x20 || *src >= 0x80) { + /* SCSI-II Specifies that these should never occur. */ + /* non-printable character */ + switch (flags & CAM_STRVIS_FLAG_NONASCII_MASK) { + case CAM_STRVIS_FLAG_NONASCII_ESC: + sbuf_printf(sb, "\\%c%c%c", + ((*src & 0300) >> 6) + '0', + ((*src & 0070) >> 3) + '0', + ((*src & 0007) >> 0) + '0'); + break; + case CAM_STRVIS_FLAG_NONASCII_RAW: + /* + * If we run into a NUL, just transform it + * into a space. + */ + if (*src != 0x00) + sbuf_putc(sb, *src); + else + sbuf_putc(sb, ' '); + break; + case CAM_STRVIS_FLAG_NONASCII_SPC: + sbuf_putc(sb, ' '); + break; + case CAM_STRVIS_FLAG_NONASCII_TRIM: + default: + break; + } + } else { + /* normal character */ + sbuf_putc(sb, *src); + } + src++; + srclen--; + } +} + + /* * Compare string with pattern, returning 0 on match. * Short pattern matches trailing blanks in name, - * wildcard '*' in pattern matches rest of name, - * wildcard '?' matches a single non-space character. + * Shell globbing rules apply: * matches 0 or more characters, + * ? matchces one character, [...] denotes a set to match one char, + * [^...] denotes a complimented set to match one character. + * Spaces in str used to match anything in the pattern string + * but was removed because it's a bug. No current patterns require + * it, as far as I know, but it's impossible to know what drives + * returned. + * + * Each '*' generates recursion, so keep the number of * in check. */ int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len) { - while (*pattern != '\0'&& str_len > 0) { - + while (*pattern != '\0' && str_len > 0) { if (*pattern == '*') { - return (0); - } - if ((*pattern != *str) - && (*pattern != '?' || *str == ' ')) { + pattern++; + if (*pattern == '\0') + return (0); + do { + if (cam_strmatch(str, pattern, str_len) == 0) + return (0); + str++; + str_len--; + } while (str_len > 0); return (1); + } else if (*pattern == '[') { + int negate_range, ok; + uint8_t pc, sc; + + ok = 0; + sc = *str++; + str_len--; + if ((negate_range = (*pattern == '^')) != 0) + pattern++; + while (((pc = *pattern) != ']') && *pattern != '\0') { + pattern++; + if (*pattern == '-') { + if (pattern[1] == '\0') /* Bad pattern */ + return (1); + if (sc >= pc && sc <= pattern[1]) + ok = 1; + pattern += 2; + } else if (pc == sc) + ok = 1; + } + if (ok == negate_range) + return (1); + } else if (*pattern == '?') { + /* NB: || *str == ' ' of the old code is a bug and was removed */ + /* if you add it back, keep this the last if before the naked else */ + pattern++; + str++; + str_len--; + } else { + if (*str != *pattern) + return (1); + pattern++; + str++; + str_len--; } - pattern++; - str++; - str_len--; } while (str_len > 0 && *str == ' ') { str++; str_len--; } - if (str_len > 0 && *str == 0) - str_len = 0; return (str_len); } @@ -209,7 +295,7 @@ cam_fetch_status_entry(cam_status status) { status &= CAM_STATUS_MASK; return (bsearch(&status, &cam_status_table, - num_cam_status_entries, + nitems(cam_status_table), sizeof(*cam_status_table), camstatusentrycomp)); } @@ -366,7 +452,8 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str, } if (proto_flags & CAM_EAF_PRINT_RESULT) { sbuf_cat(&sb, path_str); - ata_res_sbuf(&ccb->ataio, &sb); + sbuf_printf(&sb, "RES: "); + ata_res_sbuf(&ccb->ataio.res, &sb); sbuf_printf(&sb, "\n"); } |