From: Greg KH Date: Thu, 14 Jul 2005 21:13:34 +0000 (-0700) Subject: Merge gregkh@ehlo.org:/home/kay/public_html/pub/scm/linux/hotplug/udev-kay X-Git-Tag: 064~15 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=39e54555a961fa6c4c8e7d260a0e208439dc0cfa;hp=afd6b4acc8ce76f1187bf852b1404a82047d8f97 Merge gregkh@ehlo.org:/home/kay/public_html/linux/hotplug/udev-kay --- diff --git a/docs/writing_udev_rules/index.html b/docs/writing_udev_rules/index.html index 1ba43678c..c2ccdc366 100644 --- a/docs/writing_udev_rules/index.html +++ b/docs/writing_udev_rules/index.html @@ -321,7 +321,7 @@ Building on the style mentioned above, you can do even more flashy things. The u This prevents the need to excessively provide a GROUP="audio" key on every following rule which names sound devices.

-udev defaults to creating nodes with unix permissions of 0660 (read/write to owner and group), which is configured by the default_mode setting inside /etc/udev/udev.conf. There may be some situations where you do not want to use the default permissions on your device node. Fortunately, you can easily override the permissions in your rules using the MODE assignment key. As an example, the following rule defines that the inotify node shall be readable and writable to everyone: +udev defaults to creating nodes with unix permissions of 0660 (read/write to owner and group). There may be some situations where you do not want to use the default permissions on your device node. Fortunately, you can easily override the permissions in your rules using the MODE assignment key. As an example, the following rule defines that the inotify node shall be readable and writable to everyone:
KERNEL="inotify", NAME="misc/%k", SYMLINK="%k", MODE="0666"
diff --git a/etc/udev/redhat/udev.rules b/etc/udev/redhat/udev.rules index 2d4819f8c..5bed78228 100644 --- a/etc/udev/redhat/udev.rules +++ b/etc/udev/redhat/udev.rules @@ -1,7 +1,7 @@ # There are a number of modifiers that are allowed to be used in some of the # fields. See the udev man page for a full description of them. # -# default is OWNER="root" GROUP="root", MODE="0600" +# default is OWNER="root" GROUP="root", MODE="0660" # # all block devices diff --git a/extras/ata_id/ata_id.c b/extras/ata_id/ata_id.c index 34b1ccdff..9df0fdb10 100644 --- a/extras/ata_id/ata_id.c +++ b/extras/ata_id/ata_id.c @@ -107,6 +107,8 @@ int main(int argc, char *argv[]) int fd; int rc = 0; + logging_init("ata_id"); + for (i = 1 ; i < argc; i++) { char *arg = argv[i]; @@ -167,8 +169,12 @@ int main(int argc, char *argv[]) printf("ID_MODEL=%s\n", model); printf("ID_SERIAL=%s\n", serial); printf("ID_REVISION=%s\n", revision); - } else - printf("%s_%s\n", model, serial); + } else { + if (serial[0] != '\0') + printf("%s_%s\n", model, serial); + else + printf("%s\n", model); + } close: close(fd); diff --git a/extras/dasd_id/Makefile b/extras/dasd_id/Makefile new file mode 100644 index 000000000..33bb6965c --- /dev/null +++ b/extras/dasd_id/Makefile @@ -0,0 +1,52 @@ +# Makefile for dasd_id +# +# Copyright (C) 2004 Kay Sievers +# +# 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. +# + +PROG = dasd_id + +all: $(PROG) + +prefix = +exec_prefix = ${prefix} +etcdir = ${prefix}/etc +sbindir = ${exec_prefix}/sbin +usrbindir = ${exec_prefix}/usr/bin +usrsbindir = ${exec_prefix}/usr/sbin +mandir = ${prefix}/usr/share/man +devddir = ${etcdir}/dev.d/default +configdir = ${etcdir}/udev/ +initdir = ${etcdir}/init.d/ +srcdir = . + +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} + +CFLAGS+=-D_FILE_OFFSET_BITS=64 + +OBJS = dasd_id.o ../../udev.a + +$(OBJS): $(HEADERS) + +.c.o: + $(QUIET) $(CC) $(CFLAGS) -c -o $@ $< + +$(PROG): $(OBJS) $(HEADERS) + $(QUIET) $(LD) $(LDFLAGS) -o $(PROG) $(OBJS) $(LIB_OBJS) + +clean: + rm -f $(PROG) $(OBJS) + +spotless: clean + +install: all + $(INSTALL_PROGRAM) $(PROG) $(DESTDIR)$(sbindir)/$(PROG) + +uninstall: + - rm $(DESTDIR)$(sbindir)/$(PROG) diff --git a/extras/volume_id/volume_id/dasd.c b/extras/dasd_id/dasd_id.c similarity index 72% rename from extras/volume_id/volume_id/dasd.c rename to extras/dasd_id/dasd_id.c index 6f403cb92..5c2143f45 100644 --- a/extras/volume_id/volume_id/dasd.c +++ b/extras/dasd_id/dasd_id.c @@ -31,13 +31,42 @@ #include #include #include +#include #include #include -#include "volume_id.h" -#include "logging.h" -#include "util.h" -#include "dasd.h" +#include "../../logging.h" +#include "../../udev_utils.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; + + value = getenv("UDEV_LOG"); + if (value) + udev_log = log_priority(value); + else + udev_log = LOG_ERR; + } + + if (priority > udev_log) + return; + + va_start(args, format); + vsyslog(priority, format, args); + va_end(args); +} +#endif + +/* + * Only compile this on S/390. Doesn't make any sense + * for other architectures. + */ static unsigned char EBCtoASC[256] = { @@ -55,7 +84,7 @@ static unsigned char EBCtoASC[256] = -INP */ 0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B, /* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL - -SW */ + -SW */ 0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07, /* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */ 0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04, @@ -71,7 +100,7 @@ static unsigned char EBCtoASC[256] = 0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA, /* 0x60 - / ---- Ä ---- ---- ---- */ 0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F, -/* 0x68 ---- , % _ > ? */ +/* 0x68 ---- , % _ > ? */ 0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /* 0x70 --- ---- ---- ---- ---- ---- ---- */ 0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, @@ -111,15 +140,15 @@ static unsigned char EBCtoASC[256] = 0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07 }; -static void vtoc_ebcdic_dec (const unsigned char *source, unsigned char *target, int l) +static void vtoc_ebcdic_dec (const unsigned char *source, char *target, int l) { int i; for (i = 0; i < l; i++) - target[i]=EBCtoASC[(unsigned char)(source[i])]; + target[i]=(char)EBCtoASC[(unsigned char)(source[i])]; } -/* +/* * struct dasd_information_t * represents any data about the data, which is visible to userspace */ @@ -144,54 +173,101 @@ typedef struct dasd_information_t { char configuration_data[256]; /* from read_configuration_data */ } dasd_information_t; -#define _IOC_NRBITS 8 -#define _IOC_TYPEBITS 8 -#define _IOC_SIZEBITS 14 -#define _IOC_DIRBITS 2 -#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) -#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) -#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) -#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) -#define _IOC_NRSHIFT 0 -#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) -#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) -#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) #define DASD_IOCTL_LETTER 'D' - #define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,dasd_information_t) #define BLKSSZGET _IO(0x12,104) -int volume_id_probe_dasd(struct volume_id *id) +unsigned char serial[8]; + +static int dasd_id(int fd) { int blocksize; dasd_information_t info; __u8 *data; __u8 *label_raw; - unsigned char name[7]; - - dbg("probing"); - if (ioctl(id->fd, BIODASDINFO, &info) != 0) + if (ioctl(fd, BIODASDINFO, &info) != 0) { + dbg("not a dasd"); return -1; + } - if (ioctl(id->fd, BLKSSZGET, &blocksize) != 0) - return -1; + if (ioctl(fd, BLKSSZGET, &blocksize) != 0) { + err("failed to get blocksize"); + return -1; + } - data = volume_id_get_buffer(id, info.label_block * blocksize, 16); - if (data == NULL) - return -1; + if (lseek(fd,info.label_block * blocksize, SEEK_SET) == -1) { + err("seek failed on dasd"); + return -1; + } + + data = malloc(blocksize); + if (data == NULL) + return -1; + + if (read(fd, data, blocksize) == -1) { + err("read disklabel failed"); + free(data); + return -1; + } - if ((!info.FBA_layout) && (!strcmp(info.type, "ECKD"))) - label_raw = &data[8]; - else - label_raw = &data[4]; + if ((!info.FBA_layout) && (!strcmp(info.type, "ECKD"))) + label_raw = &data[8]; + else + label_raw = &data[4]; + serial[6] = '\0'; - name[6] = '\0'; - volume_id_set_usage(id, VOLUME_ID_DISKLABEL); - id->type = "dasd"; - volume_id_set_label_raw(id, label_raw, 6); - vtoc_ebcdic_dec(label_raw, name, 6); - volume_id_set_label_string(id, name, 6); + vtoc_ebcdic_dec(label_raw, serial, 6); + free(data); + + return 0; + } + +int main(int argc, char *argv[]) +{ + const char *node = NULL; + int i; + int export = 0; + int fd; + int rc = 0; - return 0; + logging_init("dasd_id"); + + for (i = 1; i < argc; i++) { + char *arg = argv[i]; + + if (strcmp(arg, "--export") == 0) { + export = 1; + } else + node = arg; + } + if (!node) { + err("no node specified"); + rc = 1; + goto exit; + } + + fd = open(node, O_RDONLY); + if (fd < 0) { + err("unable to open '%s'", node); + rc = 1; + goto exit; + } + + if (dasd_id(fd) < 0) { + err("dasd_id failed: %s", strerror(errno)); + rc = 1; + } + + if (export) { + printf("ID_TYPE=disk\n"); + printf("ID_SERIAL=%s\n",serial); + } else + printf("%s\n", serial); + + close(fd); +exit: + logging_close(); + return rc; } + diff --git a/extras/scsi_id/scsi_id.c b/extras/scsi_id/scsi_id.c index 4003ee6af..cbefb445d 100644 --- a/extras/scsi_id/scsi_id.c +++ b/extras/scsi_id/scsi_id.c @@ -52,7 +52,7 @@ * options are not supported, but other code is still left in place for * now. */ -static const char short_options[] = "bd:f:gip:s:uvVx"; +static const char short_options[] = "abd:f:gip:s:uvVx"; /* * Just duplicate per dev options. */ @@ -61,6 +61,7 @@ static const char dev_short_options[] = "bgp:"; char sysfs_mnt_path[SYSFS_PATH_MAX]; static int all_good; +static int always_info; static char *default_callout; static int dev_specified; static int sys_specified; @@ -485,6 +486,9 @@ static int set_options(int argc, char **argv, const char *short_opts, dprintf("option '%c'\n", option); switch (option) { + case 'a': + always_info = 1; + break; case 'b': all_good = 0; break; @@ -810,7 +814,7 @@ static int scsi_id(const char *target_path, char *maj_min_dev) retval = 1; } else if (scsi_get_serial(scsi_dev, maj_min_dev, page_code, serial, MAX_SERIAL_LEN)) { - retval = 1; + retval = always_info?0:1; } else { retval = 0; } diff --git a/extras/scsi_id/scsi_serial.c b/extras/scsi_id/scsi_serial.c index 20a792855..7bfa9d181 100644 --- a/extras/scsi_id/scsi_serial.c +++ b/extras/scsi_id/scsi_serial.c @@ -89,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 */ @@ -130,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; @@ -331,6 +334,9 @@ resend: 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; diff --git a/extras/usb_id/usb_id.c b/extras/usb_id/usb_id.c index bca80f8de..f4011ee89 100644 --- a/extras/usb_id/usb_id.c +++ b/extras/usb_id/usb_id.c @@ -72,7 +72,9 @@ static char revision_str[16]; static char type_str[16]; static int use_usb_info; +static int use_num_info; static int export; +static int debug; static void set_str(char *to, const unsigned char *from, int count) { @@ -259,7 +261,7 @@ static int usb_id(const char *target_path) struct sysfs_device *target_dev; struct sysfs_device *host_dev, *interface_dev, *usb_dev; struct sysfs_attribute *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev; - struct sysfs_attribute *usb_model, *usb_vendor, *usb_rev, *usb_serial; + struct sysfs_attribute *usb_model = NULL, *usb_vendor = NULL, *usb_rev, *usb_serial; struct sysfs_attribute *if_class, *if_subclass; int if_class_num; int protocol = 0; @@ -322,11 +324,12 @@ static int usb_id(const char *target_path) if_class = sysfs_get_device_attr(interface_dev, "bInterfaceClass"); if (!if_class) { info("%s: cannot get bInterfaceClass attribute", interface_dev->name); - return -1; + return 1; } if_class_num = strtoul(if_class->value, NULL, 16); if (if_class_num != 8) { set_usb_iftype(type_str, if_class->value, sizeof(type_str) - 1); + protocol = 0; } else { if_subclass = sysfs_get_device_attr(interface_dev, "bInterfaceSubClass"); @@ -338,29 +341,29 @@ static int usb_id(const char *target_path) /* Generic SPC-2 device */ scsi_vendor = sysfs_get_device_attr(scsi_dev, "vendor"); if (!scsi_vendor) { - info("%s: cannot get vendor attribute", scsi_dev->name); - return -1; + info("%s: cannot get SCSI vendor attribute", scsi_dev->name); + return 1; } set_str(vendor_str, scsi_vendor->value, sizeof(vendor_str)-1); scsi_model = sysfs_get_device_attr(scsi_dev, "model"); if (!scsi_model) { - info("%s: cannot get model attribute", scsi_dev->name); - return -1; + info("%s: cannot get SCSI model attribute", scsi_dev->name); + return 1; } set_str(model_str, scsi_model->value, sizeof(model_str)-1); scsi_type = sysfs_get_device_attr(scsi_dev, "type"); if (!scsi_type) { - info("%s: cannot get type attribute", scsi_dev->name); - return -1; + info("%s: cannot get SCSI type attribute", scsi_dev->name); + return 1; } set_scsi_type(type_str, scsi_type->value, sizeof(type_str)-1); scsi_rev = sysfs_get_device_attr(scsi_dev, "rev"); if (!scsi_rev) { - info("%s: cannot get type attribute", scsi_dev->name); - return -1; + info("%s: cannot get SCSI revision attribute", scsi_dev->name); + return 1; } set_str(revision_str, scsi_rev->value, sizeof(revision_str)-1); @@ -368,19 +371,29 @@ static int usb_id(const char *target_path) /* Fallback to USB vendor & device */ if (vendor_str[0] == '\0') { - usb_vendor = sysfs_get_device_attr(usb_dev, "manufacturer"); + if (!use_num_info) + if (!(usb_vendor = sysfs_get_device_attr(usb_dev, "manufacturer"))) + dbg("No USB vendor string found, using idVendor"); + if (!usb_vendor) { - dbg("No USB vendor string found, using idVendor"); - usb_vendor = sysfs_get_device_attr(usb_dev, "idVendor"); + if (!(usb_vendor = sysfs_get_device_attr(usb_dev, "idVendor"))) { + dbg("No USB vendor information available\n"); + sprintf(vendor_str,"0000"); + } } set_str(vendor_str,usb_vendor->value, sizeof(vendor_str) - 1); } if (model_str[0] == '\0') { - usb_model = sysfs_get_device_attr(usb_dev, "product"); + if (!use_num_info) + if (!(usb_model = sysfs_get_device_attr(usb_dev, "product"))) + dbg("No USB model string found, using idProduct"); + if (!usb_model) { - dbg("No USB model string found, using idProduct"); - usb_model = sysfs_get_device_attr(usb_dev, "idProduct"); + if (!(usb_model = sysfs_get_device_attr(usb_dev, "idProduct"))) { + dbg("No USB model information available\n"); + sprintf(model_str,"0000"); + } } set_str(model_str, usb_model->value, sizeof(model_str) - 1); } @@ -417,13 +430,20 @@ int main(int argc, char **argv) exit(1); } - while ((option = getopt(argc, argv, "ux")) != -1 ) { + while ((option = getopt(argc, argv, "dnux")) != -1 ) { if (optarg) dbg("option '%c' arg '%s'", option, optarg); else dbg("option '%c'", option); switch (option) { + case 'd': + debug = 1; + break; + case 'n': + use_num_info=1; + use_usb_info=1; + break; case 'u': use_usb_info=1; break; @@ -432,7 +452,7 @@ int main(int argc, char **argv) break; default: info("Unknown or bad option '%c' (0x%x)", option, option); - retval = -1; + retval = 1; break; } } @@ -452,25 +472,27 @@ int main(int argc, char **argv) retval = usb_id(target_path); - if (export) { - printf("ID_VENDOR=%s\n", vendor_str); - printf("ID_MODEL=%s\n", model_str); - printf("ID_REVISION=%s\n", revision_str); - if (serial_str[0] == '\0') { - printf("ID_SERIAL=%s_%s\n", - vendor_str, model_str); - } else { - printf("ID_SERIAL=%s_%s_%s\n", - vendor_str, model_str, serial_str); - } - printf("ID_TYPE=%s\n", type_str); - } else { - if (serial_str[0] == '\0') { - printf("%s_%s\n", - vendor_str, model_str); + if (retval == 0) { + if (export) { + printf("ID_VENDOR=%s\n", vendor_str); + printf("ID_MODEL=%s\n", model_str); + printf("ID_REVISION=%s\n", revision_str); + if (serial_str[0] == '\0') { + printf("ID_SERIAL=%s_%s\n", + vendor_str, model_str); + } else { + printf("ID_SERIAL=%s_%s_%s\n", + vendor_str, model_str, serial_str); + } + printf("ID_TYPE=%s\n", type_str); } else { - printf("%s_%s_%s\n", - vendor_str, model_str, serial_str); + if (serial_str[0] == '\0') { + printf("%s_%s\n", + vendor_str, model_str); + } else { + printf("%s_%s_%s\n", + vendor_str, model_str, serial_str); + } } } exit(retval); diff --git a/extras/volume_id/README b/extras/volume_id/README index a7635ff61..974a5016d 100644 --- a/extras/volume_id/README +++ b/extras/volume_id/README @@ -37,7 +37,6 @@ luks * - * - hpfs * - - - romfs * minix * -dasd * highpoint * isw_raid * lsi_raid * diff --git a/extras/volume_id/vol_id.c b/extras/volume_id/vol_id.c index 451fd355c..a4a866cfc 100644 --- a/extras/volume_id/vol_id.c +++ b/extras/volume_id/vol_id.c @@ -32,7 +32,6 @@ #include "../../udev_utils.h" #include "../../logging.h" #include "volume_id/volume_id.h" -#include "volume_id/dasd.h" #define BLKGETSIZE64 _IOR(0x12,114,size_t) @@ -136,7 +135,7 @@ int main(int argc, char *argv[]) vid = volume_id_open_node(node); if (vid == NULL) { - fprintf(stderr, "error open volume\n"); + fprintf(stderr, "%s: error open volume\n", node); rc = 2; goto exit; } @@ -147,10 +146,8 @@ int main(int argc, char *argv[]) if (volume_id_probe_all(vid, 0, size) == 0) goto print; - if (volume_id_probe_dasd(vid) == 0) - goto print; - - fprintf(stderr, "unknown volume type\n"); + if (print != PRINT_EXPORT) + fprintf(stderr, "%s: unknown volume type\n", node); rc = 3; goto exit; diff --git a/extras/volume_id/volume_id/Makefile.inc b/extras/volume_id/volume_id/Makefile.inc index acd26ff10..266d1e487 100644 --- a/extras/volume_id/volume_id/Makefile.inc +++ b/extras/volume_id/volume_id/Makefile.inc @@ -26,7 +26,6 @@ VOLUME_ID_OBJS= \ $(VOLUME_ID_BASE)/romfs.o \ $(VOLUME_ID_BASE)/sysv.o \ $(VOLUME_ID_BASE)/minix.o \ - $(VOLUME_ID_BASE)/dasd.o \ $(VOLUME_ID_BASE)/luks.o \ $(VOLUME_ID_BASE)/volume_id.o \ $(VOLUME_ID_BASE)/util.o @@ -58,7 +57,6 @@ VOLUME_ID_HEADERS= \ $(VOLUME_ID_BASE)/romfs.h \ $(VOLUME_ID_BASE)/sysv.h \ $(VOLUME_ID_BASE)/minix.h \ - $(VOLUME_ID_BASE)/dasd.h \ $(VOLUME_ID_BASE)/luks.h \ $(VOLUME_ID_BASE)/volume_id.h \ $(VOLUME_ID_BASE)/util.h diff --git a/extras/volume_id/volume_id/dasd.h b/extras/volume_id/volume_id/dasd.h deleted file mode 100644 index 751b9fda6..000000000 --- a/extras/volume_id/volume_id/dasd.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * dasdlabel - read label from s390 block device - * - * Copyright (C) 2004 Arnd Bergmann - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _VOLUME_ID_DASDLABEL_ -#define _VOLUME_ID_DASDLABEL_ - -extern int volume_id_probe_dasd(struct volume_id *id); - -#endif diff --git a/extras/volume_id/volume_id/volume_id.h b/extras/volume_id/volume_id/volume_id.h index 2266694f5..c6aef5087 100644 --- a/extras/volume_id/volume_id/volume_id.h +++ b/extras/volume_id/volume_id/volume_id.h @@ -21,7 +21,7 @@ #ifndef _VOLUME_ID_H_ #define _VOLUME_ID_H_ -#define VOLUME_ID_VERSION 44 +#define VOLUME_ID_VERSION 45 #define VOLUME_ID_LABEL_SIZE 64 #define VOLUME_ID_UUID_SIZE 36 diff --git a/test/simple-build-check.sh b/test/simple-build-check.sh index c5b429d98..7e9a940f8 100755 --- a/test/simple-build-check.sh +++ b/test/simple-build-check.sh @@ -6,6 +6,7 @@ EXTRAS="\ extras/ata_id \ extras/volume_id \ extras/usb_id \ + extras/dasd_id \ extras/run_directory" [ -z "$KERNEL_DIR" ] && KERNEL_DIR=/lib/modules/`uname -r`/build diff --git a/test/udev-test.pl b/test/udev-test.pl index 873780d70..1bb60bb76 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -1450,6 +1450,48 @@ EOF KERNEL=="ttyUSB[0-9]*", NAME="right" KERNEL=="ttyUSB[0-9]*", NAME="" KERNEL=="ttyUSB[0-9]*", NAME="wrong" +EOF + }, + { + desc => "test multi matches", + subsys => "tty", + devpath => "/class/tty/ttyUSB0", + exp_name => "right", + rules => < "test multi matches 2", + subsys => "tty", + devpath => "/class/tty/ttyUSB0", + exp_name => "right", + rules => < "IMPORT parent test sequence 1/2 (keep)", + subsys => "block", + devpath => "/block/sda", + exp_name => "parent", + option => "keep", + rules => < "IMPORT parent test sequence 2/2 (keep)", + subsys => "block", + devpath => "/block/sda/sda1", + exp_name => "parentenv-parent_right", + option => "clean", + rules => <path); + udev_init_device(&udev_parent, NULL, NULL, NULL); + /* import the udev_db of the parent */ + if (udev_db_get_device(&udev_parent, &parent->path[strlen(sysfs_path)]) == 0) { + dbg("import stored parent env '%s'", udev_parent.name); + list_for_each_entry(name_loop, &udev_parent.env_list, node) { + char name[NAME_SIZE]; + char *pos; + + strlcpy(name, name_loop->name, sizeof(name)); + pos = strchr(name, '='); + if (pos) { + pos[0] = '\0'; + pos++; + if (strcmp_pattern(filter, name) == 0) { + dbg("import key '%s'", name_loop->name); + name_list_add(&udev->env_list, name_loop->name, 0); + setenv(name, pos, 1); + } else + dbg("skip key '%s'", name_loop->name); + } + } + rc = 0; + } else + dbg("parent not found in database"); + udev_cleanup_device(&udev_parent); + } + + return rc; +} + /* finds the lowest positive N such that N isn't present in the udevdb * if doesn't exist, 0 is returned, N otherwise */ @@ -604,10 +644,12 @@ found: break; } pos = getenv(attr); - if (pos == NULL) + if (pos == NULL) { + dbg("env '%s' not avialable", attr); break; - strlcat(string, pos, maxsize); + } dbg("substitute env '%s=%s'", attr, pos); + strlcat(string, pos, maxsize); break; default: err("unknown substitution type=%i", type); @@ -635,25 +677,36 @@ static char *key_pair_name(struct udev_rule *rule, struct key_pair *pair) static int match_key(const char *key_name, struct udev_rule *rule, struct key *key, const char *val) { int match; + char value[PATH_SIZE]; char *key_value; + char *pos; if (key->operation == KEY_OP_UNSET) return 0; - key_value = rule->buf + key->val_off; + strlcpy(value, rule->buf + key->val_off, sizeof(value)); + key_value = value; - dbg("check for %s '%s' <-> '%s'", key_name, key_value, val); - match = (strcmp_pattern(key_value, val) == 0); - if (match && (key->operation != KEY_OP_NOMATCH)) { - dbg("%s is matching (matching value)", key_name); - return 0; - } - if (!match && (key->operation == KEY_OP_NOMATCH)) { - dbg("%s is matching, (non matching value)", key_name); - return 0; + dbg("key %s value='%s'", key_name, key_value); + while (key_value) { + pos = strchr(key_value, '|'); + if (pos) { + pos[0] = '\0'; + pos++; + } + dbg("match %s '%s' <-> '%s'", key_name, key_value, val); + match = (strcmp_pattern(key_value, val) == 0); + if (match && (key->operation != KEY_OP_NOMATCH)) { + dbg("%s is true (matching value)", key_name); + return 0; + } + if (!match && (key->operation == KEY_OP_NOMATCH)) { + dbg("%s is true (non-matching value)", key_name); + return 0; + } + key_value = pos; } - - dbg("%s is not matching", key_name); + dbg("%s is false", key_name); return -1; } @@ -709,14 +762,14 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule, match = (wait_for_sysfs(udev, key_val(rule, &rule->wait_for_sysfs), 3) == 0); if (match && (rule->wait_for_sysfs.operation != KEY_OP_NOMATCH)) { - dbg("WAIT_FOR_SYSFS is matching (matching value)"); + dbg("WAIT_FOR_SYSFS is true (matching value)"); return 0; } if (!match && (rule->wait_for_sysfs.operation == KEY_OP_NOMATCH)) { - dbg("WAIT_FOR_SYSFS is matching, (non matching value)"); + dbg("WAIT_FOR_SYSFS is true, (non matching value)"); return 0; } - dbg("WAIT_FOR_SYSFS is not matching"); + dbg("WAIT_FOR_SYSFS is false"); return -1; } @@ -801,12 +854,15 @@ try_parent: strlcpy(import, key_val(rule, &rule->import), sizeof(import)); apply_format(udev, import, sizeof(import), class_dev, sysfs_device); dbg("check for IMPORT import='%s'", import); - if (rule->import_exec) { + if (rule->import_type == IMPORT_PROGRAM) { dbg("run executable file import='%s'", import); rc = import_program_into_env(udev, import); - } else { + } else if (rule->import_type == IMPORT_FILE) { dbg("import file import='%s'", import); rc = import_file_into_env(udev, import); + } else if (rule->import_type == IMPORT_PARENT && class_dev) { + dbg("import parent import='%s'", import); + rc = import_parent_into_env(udev, class_dev, import); } if (rc) { dbg("IMPORT failed"); @@ -826,7 +882,7 @@ try_parent: apply_format(udev, program, sizeof(program), class_dev, sysfs_device); dbg("check for PROGRAM program='%s", program); if (execute_program(program, udev->subsystem, result, sizeof(result), NULL) != 0) { - dbg("PROGRAM is not matching"); + dbg("PROGRAM is false"); if (rule->program.operation != KEY_OP_NOMATCH) goto exit; } else { @@ -931,7 +987,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev, struct s if (rule->group.operation == KEY_OP_ASSIGN_FINAL) udev->group_final = 1; strlcpy(udev->group, key_val(rule, &rule->group), sizeof(udev->group)); - apply_format(udev, key_val(rule, &rule->group), sizeof(udev->group), class_dev, sysfs_device); + apply_format(udev, udev->group, sizeof(udev->group), class_dev, sysfs_device); dbg("applied group='%s' to '%s'", udev->group, udev->kernel_name); } diff --git a/udev_rules.h b/udev_rules.h index 959524a80..3f37d4b0b 100644 --- a/udev_rules.h +++ b/udev_rules.h @@ -54,6 +54,13 @@ struct key_pairs { struct key_pair keys[PAIRS_MAX]; }; +enum import_type { + IMPORT_UNSET, + IMPORT_PROGRAM, + IMPORT_FILE, + IMPORT_PARENT, +}; + struct udev_rule { struct key kernel_name; struct key subsystem; @@ -66,6 +73,7 @@ struct udev_rule { struct key result; struct key modalias; struct key import; + enum import_type import_type; struct key wait_for_sysfs; struct key_pairs sysfs; struct key_pairs env; @@ -81,8 +89,7 @@ struct udev_rule { unsigned int partitions; unsigned int last_rule:1, ignore_device:1, - ignore_remove:1, - import_exec:1; + ignore_remove:1; size_t bufsize; char buf[]; diff --git a/udev_rules_parse.c b/udev_rules_parse.c index a2f2f1804..7c3c2e7fc 100644 --- a/udev_rules_parse.c +++ b/udev_rules_parse.c @@ -311,9 +311,13 @@ static int add_to_rules(struct udev_rules *rules, char *line) attr = get_key_attribute(key + sizeof("IMPORT")-1); if (attr && strstr(attr, "program")) { dbg("IMPORT will be executed"); - rule->import_exec = 1; + rule->import_type = IMPORT_PROGRAM; } else if (attr && strstr(attr, "file")) { dbg("IMPORT will be included as file"); + rule->import_type = IMPORT_FILE; + } else if (attr && strstr(attr, "parent")) { + dbg("IMPORT will include the parent values"); + rule->import_type = IMPORT_PARENT; } else { /* figure it out if it is executable */ char file[PATH_SIZE]; @@ -326,8 +330,11 @@ static int add_to_rules(struct udev_rules *rules, char *line) pos[0] = '\0'; dbg("IMPORT auto mode for '%s'", file); if (!lstat(file, &stats) && (stats.st_mode & S_IXUSR)) { - dbg("IMPORT is executable, will be executed"); - rule->import_exec = 1; + dbg("IMPORT is executable, will be executed (autotype)"); + rule->import_type = IMPORT_PROGRAM; + } else { + dbg("IMPORT is not executable, will be included as file (autotype)"); + rule->import_type = IMPORT_FILE; } } add_rule_key(rule, &rule->import, operation, value); @@ -548,6 +555,7 @@ static int rules_map(struct udev_rules *rules, const char *filename) rules->buf = NULL; return -1; } + rules->mapped = 1; return 0; } diff --git a/udevd.c b/udevd.c index 8782c615e..110d8e7c4 100644 --- a/udevd.c +++ b/udevd.c @@ -167,7 +167,7 @@ static void msg_queue_insert(struct uevent_msg *msg) } /* forks event and removes event from run queue when finished */ -static void execute_udev(struct uevent_msg *msg) +static void udev_event_fork(struct uevent_msg *msg) { char *const argv[] = { "udev", msg->subsystem, NULL }; pid_t pid; @@ -181,12 +181,10 @@ static void execute_udev(struct uevent_msg *msg) close(uevent_netlink_sock); close(udevd_sock); logging_close(); - setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY); execve(udev_bin, argv, msg->envp); err("exec of child failed"); _exit(1); - break; case -1: err("fork of child failed"); msg_queue_delete(msg); @@ -389,7 +387,7 @@ static void exec_queue_manager(void) if (running_with_devpath(loop_msg, max_childs) == 0) { /* move event to run list */ list_move_tail(&loop_msg->node, &running_list); - execute_udev(loop_msg); + udev_event_fork(loop_msg); running++; dbg("moved seq %llu to running list", loop_msg->seqnum); } else @@ -722,6 +720,7 @@ static void user_sighandler(void) static int init_udevd_socket(void) { struct sockaddr_un saddr; + const int buffersize = 1024 * 1024; socklen_t addrlen; const int feature_on = 1; int retval; @@ -738,6 +737,9 @@ static int init_udevd_socket(void) return -1; } + /* set receive buffersize */ + setsockopt(udevd_sock, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); + /* the bind takes care of ensuring only one copy running */ retval = bind(udevd_sock, (struct sockaddr *) &saddr, addrlen); if (retval < 0) { @@ -755,6 +757,7 @@ static int init_udevd_socket(void) static int init_uevent_netlink_sock(void) { struct sockaddr_nl snl; + const int buffersize = 1024 * 1024; int retval; memset(&snl, 0x00, sizeof(struct sockaddr_nl)); @@ -768,6 +771,9 @@ static int init_uevent_netlink_sock(void) return -1; } + /* set receive buffersize */ + setsockopt(uevent_netlink_sock, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize)); + retval = bind(uevent_netlink_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl)); if (retval < 0) {