X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=extras%2Fscsi_id%2Fscsi_serial.c;h=7bfa9d18128c5b7223e5a0e36561b5970b613ddd;hp=9fb0f05e61ee657fbd70eac23089f9f7556f798b;hb=b4a2906bf1921cd6cbc25621a6db0bae906616c8;hpb=0bad3406c1e8eba6d5af2cbfd44d8a61231fa2bb diff --git a/extras/scsi_id/scsi_serial.c b/extras/scsi_id/scsi_serial.c index 9fb0f05e6..7bfa9d181 100644 --- a/extras/scsi_id/scsi_serial.c +++ b/extras/scsi_id/scsi_serial.c @@ -30,9 +30,9 @@ #include #include #include +#include /* need __user when built via klibc */ #include #include - #include "scsi_id.h" #include "scsi.h" @@ -70,12 +70,6 @@ static const struct scsi_id_search_values id_search_list[] = { static const char hex_str[]="0123456789abcdef"; -/* - * XXX maybe move all these to an sg_io.c file. - * - * From here ... - */ - /* * Values returned in the result/status, only the ones used by the code * are used here. @@ -95,6 +89,7 @@ static const char hex_str[]="0123456789abcdef"; #define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */ #define SG_ERR_CAT_TIMEOUT 3 #define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */ +#define SG_ERR_CAT_NOTSUPPORTED 5 /* Illegal / unsupported command */ #define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */ #define SG_ERR_CAT_OTHER 99 /* Some other error/warning */ @@ -136,6 +131,8 @@ static int sg_err_category_new(int scsi_status, int msg_status, int return SG_ERR_CAT_MEDIA_CHANGED; if (0x29 == asc) return SG_ERR_CAT_RESET; + } else if (sense_key == ILLEGAL_REQUEST) { + return SG_ERR_CAT_NOTSUPPORTED; } } return SG_ERR_CAT_SENSE; @@ -160,8 +157,7 @@ static int sg_err_category3(struct sg_io_hdr *hp) hp->sbp, hp->sb_len_wr); } -static int scsi_dump_sense(struct sysfs_class_device *scsi_dev, - struct sg_io_hdr *io) +static int scsi_dump_sense(struct sysfs_device *scsi_dev, struct sg_io_hdr *io) { unsigned char *sense_buffer; int s; @@ -257,7 +253,7 @@ static int scsi_dump_sense(struct sysfs_class_device *scsi_dev, scsi_dev->name, sense_buffer[0], sense_buffer[2]); log_message(LOG_WARNING, - "%s: non-extended sense class %d code 0x%0x ", + "%s: non-extended sense class %d code 0x%0x\n", scsi_dev->name, sense_class, code); } @@ -277,7 +273,7 @@ static int scsi_dump_sense(struct sysfs_class_device *scsi_dev, return -1; } -static int scsi_dump(struct sysfs_class_device *scsi_dev, struct sg_io_hdr *io) +static int scsi_dump(struct sysfs_device *scsi_dev, struct sg_io_hdr *io) { if (!io->status && !io->host_status && !io->msg_status && !io->driver_status) { @@ -298,48 +294,49 @@ static int scsi_dump(struct sysfs_class_device *scsi_dev, struct sg_io_hdr *io) return -1; } -static int scsi_inquiry(struct sysfs_class_device *scsi_dev, int fd, - unsigned char evpd, unsigned char page, unsigned - char *buf, unsigned int buflen) +static int scsi_inquiry(struct sysfs_device *scsi_dev, int fd, unsigned + char evpd, unsigned char page, unsigned char *buf, + unsigned int buflen) { unsigned char inq_cmd[INQUIRY_CMDLEN] = { INQUIRY_CMD, evpd, page, 0, buflen, 0 }; unsigned char sense[SENSE_BUFF_LEN]; struct sg_io_hdr io_hdr; int retval; - unsigned char *inq; - unsigned char *buffer; int retry = 3; /* rather random */ - if (buflen > 255) { + if (buflen > SCSI_INQ_BUFF_LEN) { log_message(LOG_WARNING, "buflen %d too long\n", buflen); return -1; } - inq = malloc(OFFSET + sizeof (inq_cmd) + 512); - memset(inq, 0, OFFSET + sizeof (inq_cmd) + 512); - buffer = inq + OFFSET; resend: + dprintf("%s evpd %d, page 0x%x\n", scsi_dev->name, evpd, page); + memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); io_hdr.interface_id = 'S'; io_hdr.cmd_len = sizeof(inq_cmd); io_hdr.mx_sb_len = sizeof(sense); io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; io_hdr.dxfer_len = buflen; - io_hdr.dxferp = buffer; + io_hdr.dxferp = buf; io_hdr.cmdp = inq_cmd; io_hdr.sbp = sense; io_hdr.timeout = DEF_TIMEOUT; if (ioctl(fd, SG_IO, &io_hdr) < 0) { - log_message(LOG_WARNING, "%s ioctl failed: %s\n", + log_message(LOG_WARNING, "%s: ioctl failed: %s\n", scsi_dev->name, strerror(errno)); - return -1; + retval = -1; + goto error; } retval = sg_err_category3(&io_hdr); switch (retval) { + case SG_ERR_CAT_NOTSUPPORTED: + buf[1] = 0; + /* Fallthrough */ case SG_ERR_CAT_CLEAN: case SG_ERR_CAT_RECOVERED: retval = 0; @@ -349,14 +346,8 @@ resend: retval = scsi_dump(scsi_dev, &io_hdr); } - /* - * XXX where is the length checked? That is, was our request - * buffer long enough? - */ - if (!retval) { retval = buflen; - memcpy(buf, buffer, retval); } else if (retval > 0) { if (--retry > 0) { dprintf("%s: Retrying ...\n", scsi_dev->name); @@ -365,21 +356,21 @@ resend: retval = -1; } - free(inq); +error: + if (retval < 0) + log_message(LOG_WARNING, + "%s: Unable to get INQUIRY vpd %d page 0x%x.\n", + scsi_dev->name, evpd, page); + return retval; } -/* - * XXX maybe move all these to an sg_io.c file. - * - * Ending here. - */ - -static int do_scsi_page0_inquiry(struct sysfs_class_device *scsi_dev, int fd, +/* Get list of supported EVPD pages */ +static int do_scsi_page0_inquiry(struct sysfs_device *scsi_dev, int fd, char *buffer, int len) { int retval; - char vendor[MAX_ATTR_LEN]; + struct sysfs_attribute *vendor; memset(buffer, 0, len); retval = scsi_inquiry(scsi_dev, fd, 1, 0x0, buffer, len); @@ -392,7 +383,7 @@ static int do_scsi_page0_inquiry(struct sysfs_class_device *scsi_dev, int fd, return 1; } if (buffer[3] > len) { - log_message(LOG_WARNING, "%s: page 0 buffer too long %d", + log_message(LOG_WARNING, "%s: page 0 buffer too long %d\n", scsi_dev->name, buffer[3]); return 1; } @@ -409,15 +400,16 @@ static int do_scsi_page0_inquiry(struct sysfs_class_device *scsi_dev, int fd, * If the vendor id appears in the page assume the page is * invalid. */ - if (sysfs_get_attr(scsi_dev->path, "vendor", vendor, - MAX_ATTR_LEN)) { + vendor = sysfs_get_device_attr(scsi_dev, "vendor"); + if (!vendor) { log_message(LOG_WARNING, "%s: cannot get model attribute\n", scsi_dev->name); return 1; } - if (!strncmp(&buffer[VENDOR_LENGTH], vendor, VENDOR_LENGTH)) { - log_message(LOG_WARNING, "%s invalid page0 data\n", + if (!strncmp(&buffer[VENDOR_LENGTH], vendor->value, + VENDOR_LENGTH)) { + log_message(LOG_WARNING, "%s: invalid page0 data\n", scsi_dev->name); return 1; } @@ -429,18 +421,18 @@ static int do_scsi_page0_inquiry(struct sysfs_class_device *scsi_dev, int fd, * The caller checks that serial is long enough to include the vendor + * model. */ -static int prepend_vendor_model(struct sysfs_class_device *scsi_dev, - char *serial) +static int prepend_vendor_model(struct sysfs_device *scsi_dev, char *serial) { - char attr[MAX_ATTR_LEN]; + struct sysfs_attribute *attr; int ind; - if (sysfs_get_attr(scsi_dev->path, "vendor", attr, MAX_ATTR_LEN)) { + attr = sysfs_get_device_attr(scsi_dev, "vendor"); + if (!attr) { log_message(LOG_WARNING, "%s: cannot get vendor attribute\n", scsi_dev->name); return 1; } - strncpy(serial, attr, VENDOR_LENGTH); + strncpy(serial, attr->value, VENDOR_LENGTH); ind = strlen(serial) - 1; /* * Remove sysfs added newlines. @@ -448,12 +440,13 @@ static int prepend_vendor_model(struct sysfs_class_device *scsi_dev, if (serial[ind] == '\n') serial[ind] = '\0'; - if (sysfs_get_attr(scsi_dev->path, "model", attr, MAX_ATTR_LEN)) { + attr = sysfs_get_device_attr(scsi_dev, "model"); + if (!attr) { log_message(LOG_WARNING, "%s: cannot get model attribute\n", scsi_dev->name); return 1; } - strncat(serial, attr, MODEL_LENGTH); + strncat(serial, attr->value, MODEL_LENGTH); ind = strlen(serial) - 1; if (serial[ind] == '\n') serial[ind] = '\0'; @@ -477,10 +470,9 @@ static int prepend_vendor_model(struct sysfs_class_device *scsi_dev, * check_fill_0x83_id - check the page 0x83 id, if OK allocate and fill * serial number. **/ -static int check_fill_0x83_id(struct sysfs_class_device *scsi_dev, - char *page_83, - const struct scsi_id_search_values *id_search, - char *serial, int max_len) +static int check_fill_0x83_id(struct sysfs_device *scsi_dev, char + *page_83, const struct scsi_id_search_values + *id_search, char *serial, int max_len) { int i, j, len; @@ -565,15 +557,17 @@ static int check_fill_0x83_id(struct sysfs_class_device *scsi_dev, return 0; } -static int do_scsi_page83_inquiry(struct sysfs_class_device *scsi_dev, int fd, +/* Get device identification VPD page */ +static int do_scsi_page83_inquiry(struct sysfs_device *scsi_dev, int fd, char *serial, int len) { int retval; - int id_ind, j; - unsigned char page_83[256]; + unsigned int id_ind, j; + unsigned char page_83[SCSI_INQ_BUFF_LEN]; - memset(page_83, 0, 256); - retval = scsi_inquiry(scsi_dev, fd, 1, 0x83, page_83, 255); + memset(page_83, 0, SCSI_INQ_BUFF_LEN); + retval = scsi_inquiry(scsi_dev, fd, 1, 0x83, page_83, + SCSI_INQ_BUFF_LEN); if (retval < 0) return 1; @@ -599,8 +593,7 @@ static int do_scsi_page83_inquiry(struct sysfs_class_device *scsi_dev, int fd, * Examine each descriptor returned. There is normally only * one or a small number of descriptors. */ - for (j = 4; j <= page_83[3] + 3; - j += page_83[j + 3] + 4) { + for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) { retval = check_fill_0x83_id(scsi_dev, &page_83[j], &id_search_list[id_ind], serial, len); @@ -622,17 +615,18 @@ static int do_scsi_page83_inquiry(struct sysfs_class_device *scsi_dev, int fd, return 1; } -static int do_scsi_page80_inquiry(struct sysfs_class_device *scsi_dev, int fd, +/* Get unit serial number VPD page */ +static int do_scsi_page80_inquiry(struct sysfs_device *scsi_dev, int fd, char *serial, int max_len) { int retval; int ser_ind; int i; int len; - unsigned char buf[256]; + unsigned char buf[SCSI_INQ_BUFF_LEN]; - memset(buf, 0, 256); - retval = scsi_inquiry(scsi_dev, fd, 1, 0x80, buf, 255); + memset(buf, 0, SCSI_INQ_BUFF_LEN); + retval = scsi_inquiry(scsi_dev, fd, 1, 0x80, buf, SCSI_INQ_BUFF_LEN); if (retval < 0) return retval; @@ -662,21 +656,19 @@ static int do_scsi_page80_inquiry(struct sysfs_class_device *scsi_dev, int fd, return 0; } -int scsi_get_serial (struct sysfs_class_device *scsi_dev, const char *devname, +int scsi_get_serial (struct sysfs_device *scsi_dev, const char *devname, int page_code, char *serial, int len) { - unsigned char page0[256]; + unsigned char page0[SCSI_INQ_BUFF_LEN]; int fd; int ind; int retval; - if (len > 255) { - } memset(serial, 0, len); dprintf("opening %s\n", devname); - fd = open(devname, O_RDONLY); + fd = open(devname, O_RDONLY | O_NONBLOCK); if (fd < 0) { - log_message(LOG_WARNING, "%s cannot open %s: %s\n", + log_message(LOG_WARNING, "%s: cannot open %s: %s\n", scsi_dev->name, devname, strerror(errno)); return 1; } @@ -698,7 +690,7 @@ int scsi_get_serial (struct sysfs_class_device *scsi_dev, const char *devname, goto completed; } } else if (page_code != 0x00) { - log_message(LOG_WARNING, "%s unsupported page code 0x%d\n", + log_message(LOG_WARNING, "%s: unsupported page code 0x%d\n", scsi_dev->name, page_code); return 1; } @@ -707,7 +699,7 @@ int scsi_get_serial (struct sysfs_class_device *scsi_dev, const char *devname, * Get page 0, the page of the pages. By default, try from best to * worst of supported pages: 0x83 then 0x80. */ - if (do_scsi_page0_inquiry(scsi_dev, fd, page0, 255)) { + if (do_scsi_page0_inquiry(scsi_dev, fd, page0, SCSI_INQ_BUFF_LEN)) { /* * Don't try anything else. Black list if a specific page * should be used for this vendor+model, or maybe have an @@ -743,6 +735,7 @@ int scsi_get_serial (struct sysfs_class_device *scsi_dev, const char *devname, retval = 1; completed: if (close(fd) < 0) - log_message(LOG_WARNING, "close failed: %s", strerror(errno)); + log_message(LOG_WARNING, "%s: close failed: %s\n", + scsi_dev->name, strerror(errno)); return retval; }