From: Jeff Mahoney Subject: udev: add option to generate old 'buggy' serials References: bnc#886852 Prior to udev 184, scsi_id would truncate the last character of the model string when generating the ID_SERIAL value. If a system was installed prior to that fix being available in udev, there may be configuration information that refers to the truncated link. This patch adds a --truncated-serial option and a udev rule will created the old truncated links. Signed-off-by: Jeff Mahoney --- rules/60-persistent-storage.rules | 4 ++++ src/udev/scsi_id/scsi_id.c | 15 ++++++++++++++- src/udev/scsi_id/scsi_id.h | 1 + src/udev/scsi_id/scsi_serial.c | 19 +++++++++++++------ 4 files changed, 32 insertions(+), 7 deletions(-) Index: systemd-221/rules/60-persistent-storage.rules =================================================================== --- systemd-221.orig/rules/60-persistent-storage.rules +++ systemd-221/rules/60-persistent-storage.rules @@ -40,6 +40,10 @@ KERNEL=="sd*|cciss*", ENV{DEVTYPE}=="par KERNEL=="sd*[!0-9]", ENV{ID_BUS}=="ata", PROGRAM="scsi_id --whitelisted --replace-whitespace -p0x80 -d $devnode", RESULT=="?*", ENV{ID_SCSI_COMPAT}="$result", SYMLINK+="disk/by-id/scsi-$env{ID_SCSI_COMPAT}" KERNEL=="sd*[0-9]", ENV{ID_SCSI_COMPAT}=="?*", SYMLINK+="disk/by-id/scsi-$env{ID_SCSI_COMPAT}-part%n" +# scsi compat links for ATA devices (for compatibility with udev < 184) +KERNEL=="sd*[!0-9]", ENV{ID_BUS}=="ata", PROGRAM="scsi_id --truncated-serial --whitelisted --replace-whitespace -p0x80 -d$tempnode", RESULT=="?*", ENV{ID_SCSI_COMPAT_TRUNCATED}="$result", SYMLINK+="disk/by-id/scsi-$env{ID_SCSI_COMPAT_TRUNCATED}" +KERNEL=="sd*[0-9]", ENV{ID_SCSI_COMPAT_TRUNCATED}=="?*", SYMLINK+="disk/by-id/scsi-$env{ID_SCSI_COMPAT_TRUNCATED}-part%n" + # FireWire KERNEL=="sd*[!0-9]|sr*", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}" KERNEL=="sd*[0-9]", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}-part%n" Index: systemd-221/src/udev/scsi_id/scsi_id.c =================================================================== --- systemd-221.orig/src/udev/scsi_id/scsi_id.c +++ systemd-221/src/udev/scsi_id/scsi_id.c @@ -43,6 +43,7 @@ static const struct option options[] = { { "replace-whitespace", no_argument, NULL, 'u' }, { "sg-version", required_argument, NULL, 's' }, { "verbose", no_argument, NULL, 'v' }, + { "truncated-serial", no_argument, NULL, '9' }, { "version", no_argument, NULL, 'V' }, /* don't advertise -V */ { "export", no_argument, NULL, 'x' }, { "help", no_argument, NULL, 'h' }, @@ -54,6 +55,7 @@ static bool dev_specified = false; static char config_file[MAX_PATH_LEN] = "/etc/scsi_id.config"; static enum page_code default_page_code = PAGE_UNSPECIFIED; static int sg_version = 4; +static bool compat_truncated = false; static bool reformat_serial = false; static bool export = false; static char vendor_str[64]; @@ -316,6 +318,7 @@ static void help(void) { " -g --whitelisted Treat device as whitelisted\n" " -u --replace-whitespace Replace all whitespace by underscores\n" " -v --verbose Verbose logging\n" + " --truncated-serial truncated serial for compatibility with systems configured with by-id links created by udev < 184\n" " -x --export Print values as environment keys\n" , program_invocation_short_name); @@ -387,6 +390,10 @@ static int set_options(struct udev *udev log_open(); break; + case '9': + compat_truncated = true; + break; + case 'V': printf("%s\n", VERSION); exit(0); @@ -528,6 +535,9 @@ static int scsi_id(struct udev *udev, ch util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)); util_replace_chars(serial_str, NULL); printf("ID_SERIAL=%s\n", serial_str); + util_replace_whitespace(dev_scsi.serial_compat, serial_str, sizeof(serial_str)); + util_replace_chars(serial_str, NULL); + printf("ID_SERIAL_COMPAT=%s\n", serial_str); util_replace_whitespace(dev_scsi.serial_short, serial_str, sizeof(serial_str)); util_replace_chars(serial_str, NULL); printf("ID_SERIAL_SHORT=%s\n", serial_str); @@ -558,7 +568,10 @@ static int scsi_id(struct udev *udev, ch if (reformat_serial) { char serial_str[MAX_SERIAL_LEN]; - util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)); + if (compat_truncated) + util_replace_whitespace(dev_scsi.serial_compat, serial_str, sizeof(serial_str)); + else + util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)); util_replace_chars(serial_str, NULL); printf("%s\n", serial_str); goto out; Index: systemd-221/src/udev/scsi_id/scsi_id.h =================================================================== --- systemd-221.orig/src/udev/scsi_id/scsi_id.h +++ systemd-221/src/udev/scsi_id/scsi_id.h @@ -45,6 +45,7 @@ struct scsi_id_device { char kernel[64]; char serial[MAX_SERIAL_LEN]; char serial_short[MAX_SERIAL_LEN]; + char serial_compat[MAX_SERIAL_LEN]; int use_sg; /* Always from page 0x80 e.g. 'B3G1P8500RWT' - may not be unique */ Index: systemd-221/src/udev/scsi_id/scsi_serial.c =================================================================== --- systemd-221.orig/src/udev/scsi_id/scsi_serial.c +++ systemd-221/src/udev/scsi_id/scsi_serial.c @@ -97,7 +97,8 @@ static const char hex_str[]="0123456789a static int do_scsi_page80_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, - char *serial, char *serial_short, int max_len); + char *serial, char *serial_short, + char *serial_compat, int max_len); static int sg_err_category_new(struct udev *udev, int scsi_status, int msg_status, int @@ -620,7 +621,7 @@ static int do_scsi_page83_inquiry(struct unsigned char page_83[SCSI_INQ_BUFF_LEN]; /* also pick up the page 80 serial number */ - do_scsi_page80_inquiry(udev, dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN); + do_scsi_page80_inquiry(udev, dev_scsi, fd, NULL, unit_serial_number, NULL, MAX_SERIAL_LEN); memzero(page_83, SCSI_INQ_BUFF_LEN); retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_83, page_83, @@ -765,7 +766,8 @@ static int do_scsi_page83_prespc3_inquir /* Get unit serial number VPD page */ static int do_scsi_page80_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, int fd, - char *serial, char *serial_short, int max_len) + char *serial, char *serial_short, + char *serial_compat, int max_len) { int retval; int ser_ind; @@ -799,9 +801,14 @@ static int do_scsi_page80_inquiry(struct ser_ind = prepend_vendor_model(udev, dev_scsi, &serial[1]); if (ser_ind < 0) return 1; + if (serial_compat) + strcpy(serial_compat, serial); ser_ind++; /* for the leading 'S' */ - for (i = 4; i < len + 4; i++, ser_ind++) + for (i = 4; i < len + 4; i++, ser_ind++) { serial[ser_ind] = buf[i]; + if (serial_compat) + serial_compat[ser_ind - 1] = buf[i]; + } } if (serial_short != NULL) { memcpy(serial_short, &buf[4], len); @@ -877,7 +884,7 @@ int scsi_get_serial(struct udev *udev, return 1; if (page_code == PAGE_80) { - if (do_scsi_page80_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) { + if (do_scsi_page80_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, dev_scsi->serial_compat, len)) { retval = 1; goto completed; } else { @@ -951,7 +958,7 @@ int scsi_get_serial(struct udev *udev, for (ind = 4; ind <= page0[3] + 3; ind++) if (page0[ind] == PAGE_80) if (!do_scsi_page80_inquiry(udev, dev_scsi, fd, - dev_scsi->serial, dev_scsi->serial_short, len)) { + dev_scsi->serial, dev_scsi->serial_short, dev_scsi->serial_compat, len)) { /* * Success */