Initial s390-tools-2.0.0 import

This commit is based on the s390-tools-1.39.0 version.

Changes on top of s390-tools-1.39.0:

 - Add MIT license to all source files
 - Add LICENSE file
 - Transform REAMDE to README.md (markdown)
 - Add AUTHORS.md file
 - Add CONTRIBUTING.md file
 - Move changelog from README to CHANGELOG.md file

Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
This commit is contained in:
Michael Holzheu
2017-08-07 16:13:17 +02:00
commit b627b8d8e1
647 changed files with 168974 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
include ../common.mak
libs = $(rootdir)/libu2s/libu2s.a \
$(rootdir)/libutil/libutil.a
all: dasdinfo
dasdinfo: dasdinfo.o $(libs)
install: all
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) \
$(DESTDIR)$(MANDIR)/man8
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 dasdinfo $(DESTDIR)$(BINDIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 dasdinfo.8 \
$(DESTDIR)$(MANDIR)/man8
clean:
rm -f *.o *~ dasdinfo core
.PHONY: all install clean
+97
View File
@@ -0,0 +1,97 @@
.\" Copyright 2017 IBM Corp.
.\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
.TH DASDINFO 8 "Febr 2007" "s390-tools" "Linux Administrator's Manual"
.SH NAME
.B "dasdinfo "
\- tool to read unique id from s390 DASD device
.SH SYNOPSIS
.BI "dasdinfo [-a] [-l] [-u] [-x] [-e] {-i " <busid>
.BI "| -b " <blockdev>
.BI " | -d " <devnode>
.BI "}"
.sp
.BI "dasdinfo [-h] [-v]"
.SH DESCRIPTION
.B dasdinfo
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 OPTIONS
.TP
.BI "-a|--all"
Same as -u -x -l
.TP
.BI "-x|--extended-uid"
Print DASD uid
This option prints the full uid of the DASD. When z/VM provides two
virtual devices that are actually located on the same real device, the
first four tokens of the uid will be identical for both devices. z/VM
may provide an additional token that allows to distinguish between
different minidisks. You need both support in the Linux kernel and
z/VM to receive such an additional token.
For z/VM: VM support for the hypervisor injected Special Node Element
Qualifier (SNEQ) (or hypervisor injected self-description data) is
available by applying the PTFs for VM APAR VM64273 on z/VM 5.2.0 and higher.
.TP
.BI "-u|--uid"
Print DASD uid without z/VM minidisk token
z/VM may provide an additional token that allows to distinguish
between different minidisks (see --extended-uid option). To remain
compatibile with systems that were installed on older Linux or z/VM
levels, the -u option will print the uid excluding any z/VM-provided
minidisk token.
For example, if the extended uid is
IBM.75000000092461.e900.10.00000000000037400000000000000000 then the
uid is IBM.75000000092461.e900.10. If the extended uid contains no
minidisk token, e.g. in an LPAR environment, then both uids are the
same.
.TP
.BI "-l|--label"
Print DASD volume label (volser).
.TP
.BI "-i|--busid " <busid>
Use the bus ID as input parameter, e.g. 0.0.e910.
.TP
.BI "-b|--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 "-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
dasdinfo -u -i 0.0.e910
dasdinfo -u -b dasdb
dasdinfo -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, dasdinfo will return
the volume label instead, e.g. 0XE910.
.SH SEE ALSO
.BR udev (7)
.SH AUTHORS
Volker Sameske <sameske@de.ibm.com>
+837
View File
@@ -0,0 +1,837 @@
/*
* dasdinfo - Display unique DASD ID, either UID or volser
*
* Copyright IBM Corp. 2007, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <ftw.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include "lib/util_base.h"
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/zt_common.h"
#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 struct util_prg prg = {
.desc = "Display DASD volume serial number and ID information",
.args = "-i BUSID | -b BLOCKDEV | -d DEVNODE",
.copyright_vec = {
{
.owner = "IBM Corp.",
.pub_first = 2007,
},
UTIL_PRG_COPYRIGHT_END
}
};
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("DEVICE"),
{
.option = { "block", required_argument, NULL, 'b' },
.argument = "BLOCKDEV",
.desc = "Block device name, e.g. dasdb",
},
{
.option = { "devnode", required_argument, NULL, 'd' },
.argument = "DEVNODE",
.desc = "Device node, e.g. /dev/dasda",
},
{
.option = { "busid", required_argument, NULL, 'i' },
.argument = "BUSID",
.desc = "Bus ID, e.g. 0.0.e910",
},
UTIL_OPT_SECTION("OPTIONS"),
{
.option = { "label", no_argument, NULL, 'l' },
.desc = "Print DASD volume label (volser)",
},
{
.option = { "uid", no_argument, NULL, 'u' },
.desc = "Print DASD uid (without z/VM minidisk token)",
},
{
.option = { "extended-uid", no_argument, NULL, 'x' },
.desc = "Print DASD uid (including z/VM minidisk token)",
},
{
.option = { "all", no_argument, NULL, 'a' },
.desc = "Same as -u -x -l",
},
{
.option = { "export", no_argument, NULL, 'e' },
.desc = "Export ID_BUS, ID_TYPE, ID_SERIAL for use in udev",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
/* needed because ftw can not pass arbitrary arguments */
static char *searchbusid;
static char *busiddir;
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;
};
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];
};
struct dasd_data
{
struct dasd_information2 dasd_info;
int dasd_info_version;
int blksize;
};
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 */
0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
/* 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 */
0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
/* 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 ? ---- */
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 ? ! $ * ) ; */
0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
/* 0x60 - / ---- ? ---- ---- ---- */
0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
/* 0x68 ---- , % _ > ? */
0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
/* 0x70 --- ---- ---- ---- ---- ---- ---- */
0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* 0x78 * ` : # @ ' = " */
0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
/* 0x80 * a b c d e f g */
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 */
0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
/* 0x98 q r ---- ---- */
0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
/* 0xA0 ~ s t u v w x */
0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
/* 0xA8 y z ---- ---- ---- ---- */
0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
/* 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 ---- ? ---- */
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 ---- ? */
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 ---- ? ---- ---- ---- */
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 ---- ---- ? ---- ---- ---- */
0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
};
static char *dinfo_ebcdic_dec (char *source, char *target, int l)
{
int i;
for (i = 0; i < l; i++)
target[i]=EBCtoASC[(unsigned char)(source[i])];
return target;
}
static int dinfo_read_dasd_uid (char *uidfile, char *readbuf, int readbuflen)
{
FILE *dasduid;
int offset = 0;
if ((dasduid = fopen(uidfile,"r")) == NULL)
return -1;
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);
if (strlen(readbuf) <= 1)
return -1;
return 0;
}
static int dinfo_read_dasd_vlabel (char *device, struct volume_label *vlabel,
char *readbuf)
{
struct dasd_data data;
struct volume_label tmp;
int vlsize = sizeof(struct volume_label);
unsigned long vlabel_start;
char vollbl[5];
int f;
char *space;
if ((f = open(device, O_RDONLY)) < 0) {
printf("Could not open device node.\n");
goto error;
}
if (ioctl(f, BLKSSZGET, &data.blksize) != 0) {
printf("Unable to figure out block size.\n");
goto error;
}
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;
}
}
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) ||
(strncmp(vollbl, "CMS1", 4) == 0)) {
strncpy(readbuf, vlabel->volid, 6);
dinfo_ebcdic_dec(readbuf, readbuf, 6);
space = strchr(readbuf,' ');
if (space)
*space = 0;
} else
strcpy(readbuf, "");
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_RDONLY);
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);
}
}
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)
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 (dinfo_extract_dev(dev, readbuf, readbuflen) != 0)
return -1;
return 0;
}
static int
dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
int tflag, struct FTW *ftwbuf)
{
char *tempdir;
char linkdir[128];
ssize_t i;
if (tflag != FTW_D || (strncmp((fpath + ftwbuf->base), searchbusid,
strlen(searchbusid)) != 0))
return FTW_CONTINUE;
/*
* ensure that the found entry is a busid and not a
* subchannel ID
* for large systems subchannel IDs may look like busids
*/
if (asprintf(&tempdir, "%s/driver", fpath) < 0)
return -1;
i = readlink(tempdir, linkdir, 128);
free(tempdir);
if ((i < 0) || (i >= 128))
return -1;
/* append '\0' because readlink returns non zero terminated string */
tempdir[i+1] = '\0';
if (strstr(linkdir, "dasd") == NULL)
return FTW_CONTINUE;
free(busiddir);
busiddir = strdup(fpath);
if (busiddir == NULL)
return -1;
return FTW_STOP;
}
static int
dinfo_find_entry(const char *dir, const char *searchstring,
char type, char **result)
{
DIR *directory = NULL;
struct dirent *dir_entry = NULL;
directory = opendir(dir);
if (directory == NULL)
return -1;
while ((dir_entry = readdir(directory)) != NULL) {
/* compare if the found entry has exactly the same name
and type as searched */
if ((strncmp(dir_entry->d_name, searchstring,
strlen(searchstring)) == 0)
&& (dir_entry->d_type & type)) {
*result = strdup(dir_entry->d_name);
if (*result == NULL)
goto out;
closedir(directory);
return 0; /* found */
}
}
out:
closedir(directory);
return -1; /* nothing found or error */
}
static int
dinfo_get_blockdev_from_busid(char *busid, char **blkdev)
{
int flags = FTW_PHYS; /* do not follow links */
int rc = -1;
char *tempdir = NULL;
char *result = NULL;
char *sysfsdir = "/sys/devices/";
/* dinfo_is_devnode needs to know the busid */
searchbusid = busid;
if (nftw(sysfsdir, dinfo_is_busiddir, 200, flags) != FTW_STOP)
goto out;
/*
* new sysfs: busid directory contains a directory 'block'
* which contains a directory 'dasdXXX'
*/
rc = dinfo_find_entry(busiddir, "block", DT_DIR, &result);
if (rc == 0) {
if (asprintf(&tempdir, "%s/%s/", busiddir, result) < 0) {
rc = -1;
goto out2;
}
rc = dinfo_find_entry(tempdir, "dasd", DT_DIR, blkdev);
} else {
/*
* old sysfs: entry for busiddir contain a link
* 'block:dasdXXX'
*/
rc = dinfo_find_entry(busiddir, "block:", DT_LNK, &result);
if (rc != 0)
goto out2;
*blkdev = strdup(strchr(result, ':') + 1);
if (*blkdev == NULL)
rc = -1;
}
out:
free(tempdir);
out2:
free(busiddir);
free(result);
return rc;
}
static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
{
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);
if ((block_dev = fopen(sys_dev_path,"r")) == NULL)
continue;
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 (strncmp(stat_dev, readbuf,
MAX(strlen(stat_dev), strlen(readbuf)-1)) == 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;
int print_extended_uid = 0;
int print_vlabel = 0;
char *blockdev = NULL;
char *busid = NULL;
char *devnode = NULL;
struct volume_label vlabel;
char *srchuid;
int i, rc = 0;
util_prg_init(&prg);
util_opt_init(opt_vec, NULL);
while (1) {
c = util_opt_getopt_long(argc, argv);
if (c == -1)
break;
switch (c) {
case 'a':
print_uid = 1;
print_vlabel = 1;
print_extended_uid = 1;
break;
case 'u':
print_uid = 1;
break;
case 'x':
print_extended_uid = 1;
break;
case 'l':
print_vlabel = 1;
break;
case 'i':
busid=strdup(optarg);
break;
case 'b':
blockdev=strdup(optarg);
break;
case 'd':
devnode=strdup(optarg);
break;
case 'e':
export = 1;
break;
case 'h':
util_prg_print_help();
util_opt_print_help();
exit(EXIT_SUCCESS);
case 'v':
util_prg_print_version();
exit(EXIT_SUCCESS);
default:
fprintf(stderr, "Try 'dasdinfo --help' for more "
"information.\n");
exit(1);
}
}
uname(&uname_buf);
sscanf(uname_buf.release, "%d.%d", &version,&release);
if (strcmp(uname_buf.sysname,"Linux") ||
version < 2 || (version == 2 && release < 6)) {
printf("%s %d.%d is not supported\n", uname_buf.sysname,
version,release);
exit(1);
}
if (!busid && !blockdev && !devnode) {
printf("Error: please specify a device using either -b, -i "
"or -d\n");
exit(1);
}
if ((busid && blockdev) || (busid && devnode) || (blockdev && devnode)) {
printf("Error: please specify device only once, either -b, -i "
"or -d\n");
exit(1);
}
if (!print_uid && !print_extended_uid && !print_vlabel) {
printf("Error: no action specified (e.g. -u)\n");
exit(1);
}
if (((readbuf = dinfo_malloc(readbuflen)) == NULL) ||
((uidfile = dinfo_malloc(readbuflen)) == NULL))
exit(1);
/* 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 (export) {
printf("ID_BUS=ccw\n");
printf("ID_TYPE=disk\n");
}
if (print_uid) {
if (dinfo_read_dasd_uid(uidfile, readbuf, readbuflen) == 0) {
/* look for the 4th '.' and cut there */
srchuid = readbuf - 1;
for (i = 0; i < 4; ++i) {
srchuid = index(srchuid + 1, '.');
if (!srchuid)
break;
}
if (srchuid) {
srchuid[0] = '\n';
srchuid[1] = 0;
}
if (export) {
printf("ID_UID=%s",readbuf);
} else
printf("%s",readbuf);
if (!print_vlabel && !print_extended_uid)
goto out;
}
}
if (print_extended_uid) {
if (dinfo_read_dasd_uid(uidfile, readbuf, readbuflen) == 0) {
if (export) {
printf("ID_XUID=%s",readbuf);
} else
printf("%s",readbuf);
if (!print_vlabel)
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) != 0)
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) {
if ((device = dinfo_malloc(readbuflen)) == NULL)
exit(1);
strcpy(device, devnode);
}
if (dinfo_read_dasd_vlabel(device, &vlabel, readbuf) == 0) {
if (export) {
printf("ID_SERIAL=%s\n",readbuf);
} else
printf("%s\n", readbuf);
goto out;
}
error:
printf("Error: could not read unique DASD ID\n");
rc = 1;
out:
if (device && (busid || blockdev))
dinfo_free_devnode(device);
free(uidfile);
free(device);
free(readbuf);
exit(rc);
}