linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch] udev: new dasd_id tool
@ 2006-11-27 13:15 Volker Sameske
  2006-11-27 15:52 ` Kay Sievers
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Volker Sameske @ 2006-11-27 13:15 UTC (permalink / raw)
  To: linux-hotplug


The currently used uid (volume label) for s390 DASD devices is not really 
unique. For that reason a unique uid sysfs-attribute for DASD devices has
been introduced. This new dasd_id tool replaces the current one and 
evaluates this new sysfs attribute. In case it is not available, dasd_id 
returns the old volume label instead.
 
Signed-of-by: Volker Sameske <sameske@de.ibm.com>
---

etc/udev/debian/persistent.rules             |    2 
etc/udev/redhat/50-udev.rules                |    2 
etc/udev/rules.d/60-persistent-storage.rules |    4 
etc/udev/slackware/udev.rules                |    2 
etc/udev/suse/60-persistent-storage.rules    |    2 
extras/dasd_id/dasd_id.8                     |   68 +-
extras/dasd_id/dasd_id.c                     |  731 +++++++++++++++++++++------
7 files changed, 636 insertions(+), 175 deletions(-)

diff -Nurp udev-103-orig/etc/udev/debian/persistent.rules udev-103-work/etc/udev/debian/persistent.rules
--- udev-103-orig/etc/udev/debian/persistent.rules	2006-11-27 09:05:30.000000000 +0100
+++ udev-103-work/etc/udev/debian/persistent.rules	2006-11-27 13:10:17.000000000 +0100
@@ -30,7 +30,7 @@ KERNEL="sd*[!0-9]|sr*|st*",		ENV{ID_SER
 	IMPORT{program}="scsi_id -g -x -a -s $devpath -d $tempnode"
 
 KERNEL="dasd*[!0-9]", \
-	IMPORT{program}="dasd_id --export $tempnode"
+	IMPORT{program}="dasd_id -u -e -d $tempnode"
 
 KERNEL="*[!0-9]", \
 	IMPORT{program}="edd_id --export $tempnode"
diff -Nurp udev-103-orig/etc/udev/redhat/50-udev.rules udev-103-work/etc/udev/redhat/50-udev.rules
--- udev-103-orig/etc/udev/redhat/50-udev.rules	2006-11-27 09:05:30.000000000 +0100
+++ udev-103-work/etc/udev/redhat/50-udev.rules	2006-11-27 13:11:06.000000000 +0100
@@ -277,7 +277,7 @@ KERNEL="sd*[!0-9]|sr*", SYSFS{ieee1394_
 KERNEL="sd*[!0-9]|sr*", ENV{ID_SERIAL}="", IMPORT{program}="/lib/udev/usb_id -x"
 KERNEL="sd*[!0-9]|sr*", ENV{ID_SERIAL}="", IMPORT{program}="/lib/udev/scsi_id -g -x -s %p -d $tempnode"
 KERNEL="sd*[!0-9]|sr*", ENV{ID_SERIAL}="", IMPORT{program}="/lib/udev/scsi_id -g -x -a -s %p -d $tempnode"
-KERNEL="dasd*[!0-9]", IMPORT{program}="/lib/udev/dasd_id --export $tempnode"
+KERNEL="dasd*[!0-9]", IMPORT{program}="/lib/udev/dasd_id -u -e -d $tempnode"
 KERNEL="sd*[!0-9]|sr*|dasd*[!0-9]", ENV{ID_SERIAL}="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
 
 # for partitions import parent information
diff -Nurp udev-103-orig/etc/udev/rules.d/60-persistent-storage.rules udev-103-work/etc/udev/rules.d/60-persistent-storage.rules
--- udev-103-orig/etc/udev/rules.d/60-persistent-storage.rules	2006-11-27 09:05:30.000000000 +0100
+++ udev-103-work/etc/udev/rules.d/60-persistent-storage.rules	2006-11-27 13:08:08.000000000 +0100
@@ -23,7 +23,9 @@ KERNEL="sd*[!0-9]|sr*|st*", ATTRS{ieee1
 KERNEL="sd*[!0-9]|sr*|st*", ENV{ID_SERIAL}="", IMPORT{program}="usb_id -x"
 KERNEL="sd*[!0-9]|sr*|st*", ENV{ID_SERIAL}="", IMPORT{program}="scsi_id -g -x -s %p -d $tempnode"
 KERNEL="sd*[!0-9]|sr*|st*", ENV{ID_SERIAL}="", IMPORT{program}="scsi_id -g -x -a -s %p -d $tempnode"
-KERNEL="dasd*[!0-9]", IMPORT{program}="dasd_id --export $tempnode"
+KERNEL="dasd*[!0-9]", IMPORT{program}="dasd_id -u -e -d $tempnode"
+KERNEL="dasd*[!0-9]", ENV{ID_SERIAL}="?*", SYMLINK+="dasd/$env{ID_SERIAL}/device"
+KERNEL="dasd*[0-9]", ENV{ID_SERIAL}="?*", SYMLINK+="dasd/$env{ID_SERIAL}/part%n"
 KERNEL="sd*[!0-9]|sr*|dasd*[!0-9]", ENV{ID_SERIAL}="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
 KERNEL="sd*[0-9]|dasd*[0-9]", ENV{ID_SERIAL}="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n"
 KERNEL="st*", ENV{ID_SERIAL}="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
diff -Nurp udev-103-orig/etc/udev/slackware/udev.rules udev-103-work/etc/udev/slackware/udev.rules
--- udev-103-orig/etc/udev/slackware/udev.rules	2006-11-27 09:05:30.000000000 +0100
+++ udev-103-work/etc/udev/slackware/udev.rules	2006-11-27 13:12:15.000000000 +0100
@@ -60,7 +60,7 @@ KERNEL="sd*[!0-9]|sr*", SYSFS{ieee1394_
 KERNEL="sd*[!0-9]|sr*", ENV{ID_SERIAL}="", IMPORT{program}="/lib/udev/usb_id -x"
 KERNEL="sd*[!0-9]|sr*", ENV{ID_SERIAL}="", IMPORT{program}="/lib/udev/scsi_id -g -x -s %p -d $tempnode"
 KERNEL="sd*[!0-9]|sr*", ENV{ID_SERIAL}="", IMPORT{program}="/lib/udev/scsi_id -g -x -a -s %p -d $tempnode"
-KERNEL="dasd*[!0-9]", IMPORT{program}="/lib/udev/dasd_id --export $tempnode"
+KERNEL="dasd*[!0-9]", IMPORT{program}="/lib/udev/dasd_id -u -e -d $tempnode"
 KERNEL="sd*[!0-9]|sr*|dasd*[!0-9]", ENV{ID_SERIAL}="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
 
 # for partitions import parent information
diff -Nurp udev-103-orig/etc/udev/suse/60-persistent-storage.rules udev-103-work/etc/udev/suse/60-persistent-storage.rules
--- udev-103-orig/etc/udev/suse/60-persistent-storage.rules	2006-11-27 09:05:30.000000000 +0100
+++ udev-103-work/etc/udev/suse/60-persistent-storage.rules	2006-11-27 13:12:43.000000000 +0100
@@ -23,7 +23,7 @@ KERNEL="sd*[!0-9]|sr*|st*", ATTRS{ieee1
 KERNEL="sd*[!0-9]|sr*|st*", ENV{ID_SERIAL}="", IMPORT{program}="usb_id -x"
 KERNEL="sd*[!0-9]|sr*|st*", ENV{ID_SERIAL}="", IMPORT{program}="scsi_id -g -x -s %p -d $tempnode"
 KERNEL="sd*[!0-9]|sr*|st*", ENV{ID_SERIAL}="", IMPORT{program}="scsi_id -g -x -a -s %p -d $tempnode"
-KERNEL="dasd*[!0-9]", IMPORT{program}="dasd_id --export $tempnode"
+KERNEL="dasd*[!0-9]", IMPORT{program}="dasd_id -u -e -d $tempnode"
 KERNEL="sd*[!0-9]|sr*|dasd*[!0-9]", ENV{ID_SERIAL}="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
 KERNEL="sd*[0-9]|dasd*[0-9]", ENV{ID_SERIAL}="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n"
 KERNEL="sd*[!0-9]|sr*|dasd*[!0-9]", ENV{ID_SERIAL}="?*", ENV{ID_VENDOR}="ATA", SYMLINK+="disk/by-id/ata-$env{ID_MODEL}_$env{ID_SERIAL_SHORT}"
diff -Nurp udev-103-orig/extras/dasd_id/dasd_id.8 udev-103-work/extras/dasd_id/dasd_id.8
--- udev-103-orig/extras/dasd_id/dasd_id.8	2006-11-27 09:05:30.000000000 +0100
+++ udev-103-work/extras/dasd_id/dasd_id.8	2006-11-27 10:59:13.000000000 +0100
@@ -1,28 +1,62 @@
-.TH DASD_ID 8 "November 2005" "" "Linux Administrator's Manual"
+.TH DASD_ID 8 "November 2006" "" "Linux Administrator's Manual"
 .SH NAME
-dasd_id \- udev callout to read label from s390 block device
+.B "dasd_id "
+\- udev callout to read unique id from s390 DASD device
 .SH SYNOPSIS
-.BI dasd_id
-[\fI--export\fP] \fIblockdevice\fP
-.SH "DESCRIPTION"
-.B dasd_id
-is normally called from a udev rule, to provide udev with a unique string and
-additional information (type, serial) for an S390 drive. Udev can use this
+.BI "dasd_id [-u] [-e] {-l " <busid>
+.BI "| -b " <blockdev>
+.BI " | -d " <devnode>
+.BI "}"
+.sp
+.BI "dasd_id [-h] [-?] [-v]"
+
+.SH DESCRIPTION
+.B dasd_id 
+displays specific information about a specified DASD device.
+It is normally called from a udev rule, to provide udev with a unique id string and
+additional information (type, serial) for an S390 DASD drive. Udev can use this
 information to create symlinks in /dev/disk/by-id and /dev/disk/by-label
 to the real device node.
-.SH USAGE
-.B dasd_id
-opens the blockdevice node specified at the commandline and prints the
-information chosen by the options.
+
 .SH OPTIONS
-The following commandline switches are supported to specify what dasd_id
-should print:
+
+.TP
+.BI "-u|--uid"
+Print DASD unique ID.
+.TP
+.BI "-b|--busid " <busid>
+Use the bus ID as input parameter, e.g. 0.0.e910.
+.TP
+.BI "-l|--block " <blockdev>
+Use the block device name as input parameter, e.g. dasdb.
+.TP
+.BI "-d|--devnode " <devnode>
+Use a device node as input parameter, e.g. /dev/dasdb.
 .TP
-.BI --export
-print all values (instead of only the serial)
+.BI "-e|--export"
+Print all values (ID_BUS, ID_TYPE, ID_SERIAL).
+.TP
+.BI "-h|-?|--help"
+Print usage text.
+.TP
+.BI "-v|--version"
+Print version number.
+
+.SH EXAMPLES
+dasd_id -u -b 0.0.e910
+
+dasd_id -u -l dasdb
+
+dasd_id -u -d /dev/dasdb
+
+All three examples should return the same unique ID for 
+the same DASD device, e.g. IBM.75000000092461.e900.10.
+
+In case this uid is not available, dasd_id will return
+the volume label instead, e.g. 0XE910.
 .RE
 .SH SEE ALSO
 .BR udev (7)
 .SH AUTHORS
-Developed by Arnd Bergmann <arnd@arndb.de> and Kay Sievers <kay.sievers@vrfy.org>.
+Volker Sameske <sameske@de.ibm.com>
 
diff -Nurp udev-103-orig/extras/dasd_id/dasd_id.c udev-103-work/extras/dasd_id/dasd_id.c
--- udev-103-orig/extras/dasd_id/dasd_id.c	2006-11-27 09:05:30.000000000 +0100
+++ udev-103-work/extras/dasd_id/dasd_id.c	2006-11-27 12:49:40.000000000 +0100
@@ -1,92 +1,164 @@
 /*
- * dasdlabel - read label from s390 block device
+ * This file contains the dasdinfo tool which can be used
+ * to get a unique DASD ID
  *
- * Copyright (C) 2004 Arnd Bergmann <arnd@arndb.de>
+ * Copyright IBM Corp. 2006
+ *
+ * Author(s): Volker Sameske (sameske@de.ibm.com)
  *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the
- *	Free Software Foundation version 2 of the License.
  */
 
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE 1
-#endif
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
 #include <stdlib.h>
 #include <stdio.h>
+#include <getopt.h>
 #include <string.h>
-#include <unistd.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <errno.h>
+#include <dirent.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/ioctl.h>
+#include <sys/sysmacros.h>
 
-#include "../../udev.h"
-
-#ifdef USE_LOG
-void log_message(int priority, const char *format, ...)
-{
-	va_list args;
-	static int udev_log = -1;
-
-	if (udev_log = -1) {
-		const char *value;
+#define RELEASE_STRING "1.0.0"
+#define READCHUNK 80
+#define BLKSSZGET    _IO(0x12,104)
+#define DASD_IOCTL_LETTER 'D'
+#define BIODASDINFO  _IOR(DASD_IOCTL_LETTER,1,struct dasd_information)
+#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER,3,struct dasd_information2)
+#define TEMP_DEV_MAX_RETRIES    1000
+
+static const char tool_name[] = "zSeries DASD information program";
+static const char copyright_notice[] = "Copyright IBM Corp. 2006";
+
+struct volume_label {
+	char volkey[4];
+	char vollbl[4];
+	char volid[6];
+} __attribute__ ((packed));
+
+struct dasd_information2 {
+	unsigned int devno;
+	unsigned int real_devno;
+	unsigned int schid;
+	unsigned int cu_type  : 16;
+	unsigned int cu_model :  8;
+	unsigned int dev_type : 16;
+	unsigned int dev_model : 8;
+	unsigned int open_count;
+	unsigned int req_queue_len;
+	unsigned int chanq_len;
+	char type[4];
+	unsigned int status;
+	unsigned int label_block;
+	unsigned int FBA_layout;
+	unsigned int characteristics_size;
+	unsigned int confdata_size;
+	char characteristics[64];
+	char configuration_data[256];
+	unsigned int format;
+	unsigned int features;
+	unsigned int reserved0;
+	unsigned int reserved1;
+	unsigned int reserved2;
+	unsigned int reserved3;
+	unsigned int reserved4;
+	unsigned int reserved5;
+	unsigned int reserved6;
+	unsigned int reserved7;
+};
 
-		value = getenv("UDEV_LOG");
-		if (value)
-			udev_log = log_priority(value);
-		else
-			udev_log = LOG_ERR;
-	}
+struct dasd_information {
+	unsigned int devno;
+	unsigned int real_devno;
+	unsigned int schid;
+	unsigned int cu_type  : 16;
+	unsigned int cu_model :  8;
+	unsigned int dev_type : 16;
+	unsigned int dev_model : 8;
+	unsigned int open_count;
+	unsigned int req_queue_len;
+	unsigned int chanq_len;
+	char type[4];
+	unsigned int status;
+	unsigned int label_block;
+	unsigned int FBA_layout;
+	unsigned int characteristics_size;
+	unsigned int confdata_size;
+	char characteristics[64];
+	char configuration_data[256];
+};
 
-	if (priority > udev_log)
-		return;
+struct dasd_data
+{
+	struct dasd_information2 dasd_info;
+	int dasd_info_version;
+	int blksize;
+};
 
-	va_start(args, format);
-	vsyslog(priority, format, args);
-	va_end(args);
+static void dinfo_print_version (void)
+{
+	printf ("%s version %s.\n", tool_name, RELEASE_STRING);
+	printf ("%s.\n", copyright_notice);
 }
-#endif
 
-/*
- * Only compile this on S/390. Doesn't make any sense
- * for other architectures.
- */
+static void dinfo_print_usage(char *cmd)
+{
+	printf(""
+	       "Display specific information about a specified DASD device.\n"
+	       "\n"
+	       "Usage: %s [-u] [-e] {-l <busid> | -b <blockdev> | -d <devnode>}\n"
+	       "       %s [-h] [-?] [-v]\n"
+	       "\n"
+	       "where:\n"
+	       "    -u|--uid\n"
+	       "             print DASD unique ID\n"
+	       "    -b|--busid <busid>\n"
+	       "             bus ID, e.g. 0.0.e910\n"
+	       "    -l|--block <blockdev>\n"
+	       "             block device name, e.g. dasdb\n"
+	       "    -d|--devnode <devnode>\n"
+	       "             device node, e.g. /dev/dasda\n"
+	       "    -e|--export\n"
+	       "             print all values (ID_BUS, ID_TYPE, ID_SERIAL)\n"
+	       "    -h|-?|--help\n"
+	       "             prints this usage text\n"
+	       "    -v|--version\n"
+	       "             prints the version number\n"
+	       "\n"
+	       "Example: %s -u -l dasda\n"
+	       "\n",cmd,cmd,cmd);
+}
 
-static unsigned char EBCtoASC[256] +static char EBCtoASC[256]  {
 /* 0x00  NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
 	0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
 /* 0x08  -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
 	0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-/* 0x10  DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
-                                -ENP  ->LF             */
+/* 0x10  DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC */
 	0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
-/* 0x18  CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
-                                                  -IUS */
+/* 0x18  CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB */
 	0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-/* 0x20  -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
-                                -INP                   */
+/* 0x20  -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC */
 	0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
-/* 0x28  -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
-                     -SW                               */
+/* 0x28  -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL */
 	0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
 /* 0x30 ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
 	0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
 /* 0x38 -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
 	0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
-/* 0x40   SP   RSP           ä              ----       */
+/* 0x40   SP   RSP           ?              ----       */
 	0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
 /* 0x48                      .     <     (     +     | */
 	0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
 /* 0x50    &                                      ---- */
 	0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
-/* 0x58          ß     !     $     *     )     ;       */
+/* 0x58          ?     !     $     *     )     ;       */
 	0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
-/* 0x60    -     /  ----     Ä  ----  ----  ----       */
+/* 0x60    -     /  ----     ?  ----  ----  ----       */
 	0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
 /* 0x68             ----     ,     %     _     >     ? */
 	0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
@@ -98,7 +170,7 @@ static unsigned char EBCtoASC[256]  	0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
 /* 0x88    h     i              ----  ----  ----       */
 	0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
-/* 0x90    °     j     k     l     m     n     o     p */
+/* 0x90    ?     j     k     l     m     n     o     p */
 	0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
 /* 0x98    q     r                    ----        ---- */
 	0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
@@ -106,157 +178,510 @@ static unsigned char EBCtoASC[256]  	0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
 /* 0xA8    y     z              ----  ----  ----  ---- */
 	0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
-/* 0xB0    ^                    ----     §  ----       */
+/* 0xB0    ^                    ----     ?  ----       */
 	0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
 /* 0xB8       ----     [     ]  ----  ----  ----  ---- */
 	0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
 /* 0xC0    {     A     B     C     D     E     F     G */
 	0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-/* 0xC8    H     I  ----           ö              ---- */
+/* 0xC8    H     I  ----           ?              ---- */
 	0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
 /* 0xD0    }     J     K     L     M     N     O     P */
 	0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
-/* 0xD8    Q     R  ----           ü                   */
+/* 0xD8    Q     R  ----           ?                   */
 	0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
 /* 0xE0    \           S     T     U     V     W     X */
 	0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-/* 0xE8    Y     Z        ----     Ö  ----  ----  ---- */
+/* 0xE8    Y     Z        ----     ?  ----  ----  ---- */
 	0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
 /* 0xF0    0     1     2     3     4     5     6     7 */
 	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-/* 0xF8    8     9  ----  ----     Ü  ----  ----  ---- */
+/* 0xF8    8     9  ----  ----     ?  ----  ----  ---- */
 	0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
 };
 
-static void vtoc_ebcdic_dec (const unsigned char *source, unsigned char *target, int l) 
+
+static char * dinfo_ebcdic_dec (char *source, char *target, int l)
 {
 	int i;
 
-	for (i = 0; i < l; i++) 
-		target[i]=(char)EBCtoASC[(unsigned char)(source[i])];
+	for (i = 0; i < l; i++)
+		target[i]ëCtoASC[(unsigned char)(source[i])];
+
+	return target;
 }
 
-/*
- * struct dasd_information_t
- * represents any data about the data, which is visible to userspace
- */
-typedef struct dasd_information_t {
-	unsigned int devno;		/* S/390 devno */
-	unsigned int real_devno;	/* for aliases */
-	unsigned int schid;		/* S/390 subchannel identifier */
-	unsigned int cu_type  : 16;	/* from SenseID */
-	unsigned int cu_model :  8;	/* from SenseID */
-	unsigned int dev_type : 16;	/* from SenseID */
-	unsigned int dev_model : 8;	/* from SenseID */
-	unsigned int open_count;
-	unsigned int req_queue_len;
-	unsigned int chanq_len;		/* length of chanq */
-	char type[4];			/* from discipline.name, 'none' for unknown */
-	unsigned int status;		/* current device level */
-	unsigned int label_block;	/* where to find the VOLSER */
-	unsigned int FBA_layout;	/* fixed block size (like AIXVOL) */
-	unsigned int characteristics_size;
-	unsigned int confdata_size;
-	char characteristics[64];	/* from read_device_characteristics */
-	char configuration_data[256];	/* from read_configuration_data */
-} dasd_information_t;
+static int dinfo_read_dasd_uid (char *uidfile, char *readbuf, int readbuflen)
+{
+	FILE *dasduid;
+	int offset = 0;
 
-#define DASD_IOCTL_LETTER	 'D'
-#define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,dasd_information_t)
-#define BLKSSZGET _IO(0x12,104)
+        if ((dasduid = fopen(uidfile,"r")) = NULL) {
+		printf("Could not open uid-file %s.\n", uidfile);
+		return -1;
+	}
 
-unsigned char serial[8];
+	while (fgets(readbuf + offset, READCHUNK, dasduid)  &&
+	       readbuf[strlen(readbuf)-1] != '\n' ) {
+		offset += READCHUNK-1;
+		if ( offset+READCHUNK-1 >= readbuflen ) {
+			readbuf = realloc(readbuf,
+					  readbuflen + READCHUNK-1);
+			readbuflen += READCHUNK-1;
+		}
+	}
+	fclose(dasduid);
+	return 0;
+}
 
-static int dasd_id(int fd)
+static int dinfo_read_dasd_vlabel (char *device, struct volume_label *vlabel,
+			    char *readbuf)
 {
-	int blocksize;
-	dasd_information_t info;
-	unsigned char *data;
-	unsigned char *label_raw;
+	struct dasd_data data;
+	struct volume_label tmp;
+	unsigned int vlsize = sizeof(struct volume_label);
+	unsigned long vlabel_start;
+	char vollbl[5];
+	int f;
+
+	if ((f = open(device, O_RDONLY)) < 0) {
+		printf("Could not open device node.\n");
+		goto error;
+	}
 
-	if (ioctl(fd, BIODASDINFO, &info) != 0) {
-		dbg("not a dasd");
-		return -1;
+	if (ioctl(f, BLKSSZGET, &data.blksize) != 0) {
+		printf("Unable to figure out block size.\n");
+		goto error;
 	}
 
-		if (ioctl(fd, BLKSSZGET, &blocksize) != 0) {
-			err("failed to get blocksize");
-			return -1;
+	if (ioctl(f, BIODASDINFO2, &data.dasd_info) = 0)
+		data.dasd_info_version = 2;
+	else {
+		if (ioctl(f, BIODASDINFO, &data.dasd_info) != 0) {
+			printf("Unable to figure out DASD informations.\n");
+			goto error;
 		}
+	}
 
-		if (lseek(fd,info.label_block * blocksize, SEEK_SET) = -1) {
-			err("seek failed on dasd");
-			return -1;
-		}
+	vlabel_start = data.dasd_info.label_block * data.blksize;
+	if (lseek(f, vlabel_start, SEEK_SET) < 0)
+		goto error;
+
+	bzero(vlabel, vlsize);
+
+	if (read(f, vlabel, vlsize) != vlsize) {
+		printf("Could not read volume label.\n");
+		goto error;
+	}
+
+	if (data.dasd_info.FBA_layout) {
+		bzero(&tmp, vlsize);
+		memcpy(&tmp, vlabel, vlsize);
+		memcpy(vlabel->vollbl, &tmp, vlsize-4);
+	}
+
+	close(f);
+
+	bzero(readbuf, 7);
+	bzero(vollbl, 5);
+	strncpy(vollbl, vlabel->vollbl, 4);
+	dinfo_ebcdic_dec(vollbl, vollbl, 4);
+
+	if ((strncmp(vollbl, "VOL1", 4) = 0) || (strncmp(vollbl, "LNX1", 4) = 0)) {
+		strncpy(readbuf, vlabel->volid, 6);
+		dinfo_ebcdic_dec(readbuf, readbuf, 6);
+	} else
+		strncpy(readbuf, "      ", 6);
+
+
+	return 0;
+error:
+	close(f);
+	return -1;
+}
+
+static void* dinfo_malloc(size_t size)
+{
+        void* result;
+
+        result = malloc(size);
+        if (result = NULL) {
+                printf("Could not allocate %lld bytes of memory",
+                             (unsigned long long) size);
+        }
+        return result;
+}
+
+static char* dinfo_make_path(char* dirname, char* filename)
+{
+        char* result;
+        size_t len;
+
+        len = strlen(dirname) + strlen(filename) + 2;
+        result = (char *) dinfo_malloc(len);
+        if (result = NULL)
+                return NULL;
+        sprintf(result, "%s/%s", dirname, filename);
+        return result;
+}
+
+static int dinfo_create_devnode(dev_t dev, char** devno)
+{
+        char* result;
+        char* pathname[] = { "/dev", getenv("TMPDIR"), "/tmp",
+                             getenv("HOME"), "." , "/"};
+        char filename[] = "dasdinfo0000";
+        mode_t mode;
+        unsigned int path;
+        int retry;
+        int rc;
+        int fd;
+
+	mode = S_IFBLK | S_IRWXU;
+
+        /* Try several locations for the temporary device node. */
+        for (path=0; path < sizeof(pathname) / sizeof(pathname[0]); path++) {
+                if (pathname[path] = NULL)
+                        continue;
+                for (retry=0; retry < TEMP_DEV_MAX_RETRIES; retry++) {
+                        sprintf(filename, "dasdinfo%04d", retry);
+                        result = dinfo_make_path(pathname[path], filename);
+                        if (result = NULL)
+                                return -1;
+                        rc = mknod(result, mode, dev);
+                        if (rc = 0) {
+                                /* Need this test to cover
+				 * 'nodev'-mounted
+                                 * filesystems. */
+                                fd = open(result, O_RDWR);
+                                if (fd != -1) {
+                                        close(fd);
+                                        *devno = result;
+                                        return 0;
+                                }
+				remove(result);
+                                retry = TEMP_DEV_MAX_RETRIES;
+                        } else if (errno != EEXIST)
+                                retry = TEMP_DEV_MAX_RETRIES;
+                        free(result);
+                }
+        }
+        printf("Error: Unable to create temporary device node");
+        return -1;
+}
+
+static void dinfo_free_devnode(char* device)
+{
+        if (remove(device)) {
+                printf("Warning: Could not remove "
+			"temporary file %s", device);
+        }
+}
 
-		data = malloc(blocksize);
-		if (data = NULL)
-			return -1;
-
-		if (read(fd, data, blocksize) = -1) {
-			err("read disklabel failed");
-			free(data);
-			return -1;
+static int dinfo_extract_dev(dev_t *dev, char *str, int readbuflen)
+{
+	char tmp[readbuflen];
+	char *p = NULL;
+	int ma, mi;
+
+	bzero(tmp, readbuflen);
+	strncpy(tmp, str, readbuflen);
+	if (( p = strchr(tmp, ':')) = NULL) {
+		printf("Error: unable to extract major/minor\n");
+		return -1;
+	}
+
+	*p = '\0';
+	ma = atoi(tmp);
+	mi = atoi(p + sizeof(char));
+
+	*dev = makedev(ma, mi);
+
+	return 0;
+}
+
+static int dinfo_get_dev_from_blockdev(char *blockdev, dev_t *dev)
+{
+	FILE *dasddev;
+	int offset = 0;
+	char *devfile = NULL;
+        char *readbuf = NULL;
+        int readbuflen = READCHUNK;
+
+        if ((devfile = dinfo_malloc(readbuflen)) = NULL)
+                return -1;
+
+	sprintf(devfile,"/sys/block/%s/dev", blockdev);
+
+	if ((readbuf = dinfo_malloc(readbuflen)) = NULL) {
+		printf("Error: Not enough memory to allocate readbuffer\n");
+                return -1;
+	}
+
+	if ((dasddev = fopen(devfile,"r")) = NULL) {
+		printf("Could not open %s.\n", devfile);
+		return -1;
+	}
+
+	while (fgets(readbuf + offset, READCHUNK, dasddev)  &&
+	       readbuf[strlen(readbuf)-1] != '\n' ) {
+		offset += READCHUNK-1;
+		if ( offset+READCHUNK-1 >= readbuflen ) {
+			readbuf = realloc(readbuf,
+					  readbuflen + READCHUNK-1);
+			readbuflen += READCHUNK-1;
 		}
+	}
+	fclose(dasddev);
 
-		if ((!info.FBA_layout) && (!strcmp(info.type, "ECKD")))
-			label_raw = &data[8];
-		else
-			label_raw = &data[4];
-		serial[6] = '\0';
+	if (dinfo_extract_dev(dev, readbuf, readbuflen) != 0)
+		return -1;
 
-		vtoc_ebcdic_dec(label_raw, serial, 6);
-		free(data);
+	return 0;
+}
 
-		return 0;
+static char *dinfo_get_blockdev_from_busid(char *busid, char **blkdev)
+{
+	char tmp[READCHUNK];
+	DIR *directory = NULL;
+	struct dirent *dir_entry = NULL;
+
+	sprintf(tmp,"/sys/bus/ccw/devices/%s/", busid);
+	directory = opendir(tmp);
+
+	while ((dir_entry = readdir(directory)) != NULL) {
+		if (strncmp(dir_entry->d_name, "block:", 6) = 0) {
+			if ((*blkdev = dinfo_malloc(_D_ALLOC_NAMLEN(dir_entry))) = NULL)
+				return NULL;
+			strcpy(*blkdev, strchr(dir_entry->d_name, ':') + sizeof(char));
+			break;
+		}
 	}
 
-int main(int argc, char *argv[])
+	closedir(directory);
+
+	return *blkdev;
+}
+
+static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
 {
-	const char *node = NULL;
-	int i;
-	int export = 0;
-	int fd;
-	int rc = 0;
+	struct stat stat_buffer;
+	char stat_dev[READCHUNK];
+	char sys_dev_path[READCHUNK];
+	char *readbuf;
+	DIR *directory = NULL;
+	struct dirent *dir_entry = NULL;
+	FILE *block_dev;
+	int readbuflen = READCHUNK;
+	int offset;
+
+	if (stat(devnode, &stat_buffer) != 0) {
+		printf("Error: could not stat %s\n", devnode);
+		return -1;
+	}
+
+	sprintf(stat_dev, "%d:%d", major(stat_buffer.st_rdev),
+		minor(stat_buffer.st_rdev));
+
+	if ((directory = opendir("/sys/block/")) = NULL) {
+		printf("Error: could not open directory /sys/block\n");
+		return -1;
+	}
+
+	if ((readbuf = dinfo_malloc(readbuflen)) = NULL) {
+		printf("Error: Not enough memory to allocate readbuffer\n");
+                return -1;
+	}
+
+	while ((dir_entry = readdir(directory)) != NULL) {
+		sprintf(sys_dev_path, "/sys/block/%s/dev", dir_entry->d_name);
 
-	logging_init("dasd_id");
+		if ((block_dev = fopen(sys_dev_path,"r")) = NULL)
+			continue;
 
-	for (i = 1; i < argc; i++) {
-		char *arg = argv[i];
+		offset = 0;
+		while (fgets(readbuf + offset, READCHUNK, block_dev)  &&
+		       readbuf[strlen(readbuf)-1] != '\n' ) {
+			offset += READCHUNK-1;
+			if ( offset+READCHUNK-1 >= readbuflen ) {
+				readbuf = realloc(readbuf,
+						  readbuflen + READCHUNK-1);
+				readbuflen += READCHUNK-1;
+			}
+		}
+		fclose(block_dev);
 
-		if (strcmp(arg, "--export") = 0) {
+		if (strncmp(stat_dev, readbuf, strlen(stat_dev)) = 0) {
+			sprintf(*uidfile,"/sys/block/%s/device/uid", dir_entry->d_name);
+			break;
+		}
+	}
+
+	closedir(directory);
+	return 0;
+}
+
+int main(int argc, char * argv[])
+{
+	struct utsname uname_buf;
+	int version, release;
+	char *uidfile = NULL;
+	char *device = NULL;
+	char *readbuf = NULL;
+	int readbuflen = READCHUNK;
+	dev_t dev;
+	int export = 0;
+	int c;
+	int print_uid = 0;
+	char *blockdev = NULL;
+	char *busid = NULL;
+	char *devnode = NULL;
+	struct volume_label vlabel;
+
+	while (1) {
+		int option_index = 0;
+		static struct option long_options[] = {
+			{"uid",     0, 0, 'u'},
+			{"busid",   1, 0, 'b'},
+			{"block",   1, 0, 'l'},
+			{"devnode", 1, 0, 'd'},
+			{"export",  0, 0, 'e'},
+			{"help",    0, 0, 'h'},
+			{"version", 0, 0, 'v'},
+			{0, 0, 0, 0}
+		};
+
+		c = getopt_long (argc, argv, "vh?eub:l:d:",
+				 long_options, &option_index);
+		if (c = -1)
+			break;
+
+		switch (c) {
+		case 'u':
+			print_uid = 1;
+			break;
+		case 'b':
+			busid=strdup(optarg);
+			break;
+		case 'l':
+			blockdev=strdup(optarg);
+			break;
+		case 'd':
+			devnode=strdup(optarg);
+			break;
+		case 'e':
 			export = 1;
-		} else
-			node = arg;
+			break;
+		case 'h':
+		case '?':
+			dinfo_print_usage(argv[0]);
+			exit(0);
+		case 'v':
+			dinfo_print_version();
+			exit(0);
+		default:
+			dinfo_print_usage(argv[0]);
+			exit(0);
+		}
 	}
-	if (!node) {
-		err("no node specified");
-		rc = 1;
-		goto exit;
+
+	uname(&uname_buf);
+	sscanf(uname_buf.release, "%d.%d", &version,&release);
+	if (strcmp(uname_buf.sysname,"Linux") ||
+	    version < 2 || release < 6) {
+		printf("%s %d.%d is not supported\n", uname_buf.sysname,
+			version,release);
+		return -1;
 	}
 
-	fd = open(node, O_RDONLY);
-	if (fd < 0) {
-		err("unable to open '%s'", node);
-		rc = 1;
-		goto exit;
+	if (!busid && !blockdev && !devnode) {
+		printf("Error: please specify a device using either -b, -l or -d\n");
+		return -1;
 	}
 
-	if (dasd_id(fd) < 0) {
-		err("dasd_id failed: %s", strerror(errno));
-		rc = 1;
+	if ((busid && blockdev) || (busid && devnode) || (blockdev && devnode)) {
+		printf("Error: please specify device only once,  either -b, -l or -d\n");
+		return -1;
 	}
 
+	if (!print_uid) {
+		printf("Error: no action specified (e.g. -u)\n");
+		return -1;
+	}
+
+	if (((readbuf = dinfo_malloc(readbuflen)) = NULL) ||
+	    ((uidfile = dinfo_malloc(readbuflen)) = NULL) ||
+	    ((device = dinfo_malloc(readbuflen)) = NULL))
+		return -1;
+
 	if (export) {
-		printf("ID_TYPE=disk\n");
-		printf("ID_SERIAL=%s\n",serial);
 		printf("ID_BUSÌw\n");
-	} else
-		printf("%s\n", serial);
+		printf("ID_TYPE=disk\n");
+	}
 
-	close(fd);
-exit:
-	logging_close();
-	return rc;
-}
+	/* try to read the uid attribute */
+	if (busid) {
+		sprintf(uidfile,"/sys/bus/ccw/devices/%s/uid", busid);
+	} else if (blockdev) {
+		sprintf(uidfile,"/sys/block/%s/device/uid", blockdev);
+	} else if (devnode) {
+		if (dinfo_get_uid_from_devnode(&uidfile, devnode) != 0)
+			goto error;
+	}
+	if (dinfo_read_dasd_uid(uidfile, readbuf, readbuflen) = 0) {
+		if (export) {
+			printf("ID_SERIAL=%s",readbuf);
+		} else
+			printf("%s",readbuf);
+
+		goto out;
+	}
+
+	/* there is no uid, try to read the volume serial */
+	if (busid) {
+		char *blockdev_name = NULL;
+
+		if (dinfo_get_blockdev_from_busid(busid, &blockdev_name) = NULL)
+			goto error;
+
+		if (dinfo_get_dev_from_blockdev(blockdev_name, &dev) != 0)
+			goto error;
+
+		if(dinfo_create_devnode(dev, &device) != 0)
+			goto error;
+
+		free(blockdev_name);
+
+	} else if (blockdev) {
+		if (dinfo_get_dev_from_blockdev(blockdev, &dev) != 0)
+			goto error;
+
+		if(dinfo_create_devnode(dev, &device) != 0)
+			goto error;
+
+	} else if (devnode) {
+		strcpy(device, devnode);
+	}
+
+	if (dinfo_read_dasd_vlabel(device, &vlabel, readbuf) = 0) {
+		if (export) {
+			printf("ID_SERIAL=%6.6s\n",readbuf);
+		} else
+			printf("%6.6s\n", readbuf);
 
+		if (busid || blockdev)
+			dinfo_free_devnode(device);
+
+		goto out;
+	}
+
+error:
+	printf("Error: could not read unique DASD ID\n");
+
+out:
+	free(uidfile);
+	free(device);
+	free(readbuf);
+
+	return 0;
+}



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CIDÞVDEV
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2006-11-29 12:03 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-27 13:15 [Patch] udev: new dasd_id tool Volker Sameske
2006-11-27 15:52 ` Kay Sievers
2006-11-27 17:05 ` Volker Sameske
2006-11-27 17:41 ` Kay Sievers
2006-11-27 17:53 ` Patrick Mansfield
2006-11-28  8:54 ` Kay Sievers
2006-11-28 15:29 ` Volker Sameske
2006-11-28 15:53 ` Kay Sievers
2006-11-28 16:22 ` Volker Sameske
2006-11-28 16:33 ` Kay Sievers
2006-11-29  6:55 ` Volker Sameske
2006-11-29  9:11 ` Kay Sievers
2006-11-29 12:03 ` Volker Sameske

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).