Date: 2005-08-01 Initial Package Version: 096 Description: I've used path_id and cdrom_id in 50-udev.rules, then added the following single line to 52-optical_gen.rules: SUBSYSTEM=="block", ACTION=="add", ENV{ID_CDROM}=="?*", ENV{GENERATED}!="yes", PROGRAM="/lib/udev/optical_gen /etc/udev/rules.d/51-optical.rules", SYMLINK+="%c" See the manpage for more info. Diffstat: extras/optical_gen/Makefile | 69 +++++++++++++ extras/optical_gen/optical_gen.8 | 28 +++++ extras/optical_gen/optical_gen.c | 194 +++++++++++++++++++++++++++++++++++++++ test/simple-build-check.sh | 1 4 files changed, 292 insertions(+) Signed-off-by: Miklos Vajna diff -Naur udev-096.orig/extras/optical_gen/Makefile udev-096/extras/optical_gen/Makefile --- udev-096.orig/extras/optical_gen/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ udev-096/extras/optical_gen/Makefile 2006-08-02 04:04:38.000000000 +0200 @@ -0,0 +1,69 @@ +# Makefile for udev extra invoked from the udev main Makefile +# +# Copyright (C) 2004-2005 Kay Sievers +# +# Released under the GNU General Public License, version 2. +# + +PROG = optical_gen +OBJ = +HEADERS = +GEN_HEADERS = +MAN_PAGES = + +prefix = +etcdir = ${prefix}/etc +sbindir = ${prefix}/sbin +usrbindir = ${prefix}/usr/bin +usrsbindir = ${prefix}/usr/sbin +libudevdir = ${prefix}/lib/udev +mandir = ${prefix}/usr/share/man +configdir = ${etcdir}/udev/ + +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} + +all: $(PROG) $(MAN_PAGES) +.PHONY: all +.DEFAULT: all + +%.o: %.c $(GEN_HEADERS) + $(E) " CC " $@ + $(Q) $(CC) -c $(CFLAGS) $< -o $@ + +$(PROG): %: $(HEADERS) %.o $(OBJS) + $(E) " LD " $@ + $(Q) $(LD) $(LDFLAGS) $@.o $(OBJS) -o $@ $(LIBUDEV) $(LIB_OBJS) + +# man pages +%.8: %.xml + $(E) " XMLTO " $@ + $(Q) xmlto man $? +.PRECIOUS: %.8 + +clean: + $(E) " CLEAN " + $(Q) rm -f $(PROG) $(OBJS) $(GEN_HEADERS) +.PHONY: clean + +install-bin: all + $(INSTALL_PROGRAM) -D $(PROG) $(DESTDIR)$(libudevdir)/$(PROG) +.PHONY: install-bin + +uninstall-bin: + - rm $(DESTDIR)$(libudevdir)/$(PROG) +.PHONY: uninstall-bin + +install-man: + $(INSTALL_DATA) -D $(PROG).8 $(DESTDIR)$(mandir)/man8/$(PROG).8 +.PHONY: install-man + +uninstall-man: + -rm -f $(DESTDIR)$(mandir)/man8/$(PROG).8 +.PHONY: uninstall-man + +install-config: + @echo "no config file to install" +.PHONY: install-config diff -Naur udev-096.orig/extras/optical_gen/optical_gen.8 udev-096/extras/optical_gen/optical_gen.8 --- udev-096.orig/extras/optical_gen/optical_gen.8 1970-01-01 01:00:00.000000000 +0100 +++ udev-096/extras/optical_gen/optical_gen.8 2006-08-02 04:03:34.000000000 +0200 @@ -0,0 +1,28 @@ +.TH OPTICAL_GEN 8 "August 2006" "" "Linux Administrator's Manual" +.SH NAME +optical_gen \- udev callout to generate persistent rules for optical devices +.SH SYNOPSIS +.BI optical_gen +\fIto-update.rule\fP +.SH "DESCRIPTION" +.B optical_gen +generates device-specific udev rules on-the-fly. The parameter it takes is a +file where the rules will will be written or to where they will be appended. +It requires the previous usage of cdrom_id and path_id since the generated +rules are consist of the ouput of those utilities. +.SH USAGE +.B optical_gen +should be called in a rules file after the to-be-generated one in the priority +list so that the device names will be persistent. +.SH ENVIRONMENT +.B optical_gen +requires the following environment variables: +ID_PATH. + +It utilizes the the following environment variables: +ID_CDROM, ID_CDROM_CD_RW, ID_CDROM_DVD and ID_CDROM_DVD_R. +.SH SEE ALSO +.BR udev (7) +.SH AUTHORS +Written by Miklos Vajna . + diff -Naur udev-096.orig/extras/optical_gen/optical_gen.c udev-096/extras/optical_gen/optical_gen.c --- udev-096.orig/extras/optical_gen/optical_gen.c 1970-01-01 01:00:00.000000000 +0100 +++ udev-096/extras/optical_gen/optical_gen.c 2006-08-02 13:56:05.000000000 +0200 @@ -0,0 +1,194 @@ +/* + * optical_gen.c + * + * Copyright (C) 2006 Miklos Vajna + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include + +#define DEV_MAX 512 +#define LINE_LEN 512 +#define ALIASES_LEN 64 + +int cdroms[DEV_MAX], cdrws[DEV_MAX], dvds[DEV_MAX], dvdrws[DEV_MAX]; +char aliases[ALIASES_LEN]=""; + +/* check one typeN token and 'register' it */ +int check_type(char *type, char *str, int *buf) +{ + char *num, *ptr; + int i; + + if(type && !strncmp(type, str, strlen(str))) { + ptr = type + strlen(str); + /* type must be followed by a number or a separator */ + if(ptr && (!isdigit(*ptr) && *ptr != ' ' && *ptr != '"')) { + return(-1); + } + num = strdup(type + strlen(str)); + ptr = num; + while(ptr && *ptr != ' ') { + ptr++; + } + if(ptr) { + *ptr = '\0'; + } + i = atoi(num); + free(num); + if(i < DEV_MAX) { + buf[i] = 1; + return(0); + } + } + return(-1); +} + +int parse_existing(char *fname) +{ + FILE *fp; + + fp = fopen(fname, "r"); + if(!fp) { + return(-1); + } + memset(cdroms, 0, sizeof(cdroms)); + memset(cdrws, 0, sizeof(cdrws)); + memset(dvds, 0, sizeof(dvds)); + memset(dvdrws, 0, sizeof(dvdrws)); + while(!feof(fp)) { + char line[LINE_LEN], *type; + + if(fgets(line, LINE_LEN, fp) == NULL) { + break; + } + /* prevent duplicated rules */ + if(strstr(line, getenv("ID_PATH"))) { + fclose(fp); + return(0); + } + if(!strncmp(line, "SUBSYSTEM", strlen("SUBSYSTEM"))) { + type = strstr(line, "+=") + 3; + /* search for tokens till the end of the string */ + while(type && *type != '"') { + check_type(type, "cdrom", cdroms); + check_type(type, "cdrw", cdrws); + check_type(type, "dvd", dvds); + check_type(type, "dvdrw", dvdrws); + /* skip to the next token */ + while(type && *type != ' ') { + if(*type != '"') { + type++; + } else { + break; + } + } + if(*type == ' ') { + type++; + } + } + } + } + fclose(fp); + return(1); +} + +int register_if(char *env, char *type, int *buf) +{ + int i; + + if(!getenv(env)) { + return(-1); + } + + for(i = 0; i < DEV_MAX; i++) { + if(!buf[i]) { + if(i == 0) { + sprintf(aliases+strlen(aliases), "%s ", type); + } else { + sprintf(aliases+strlen(aliases), "%s%d ", type, i); + } + break; + } + } + return(0); +} + +int update_rules(char *fn) +{ + FILE *fp; + struct stat buf; + int header = 0; + + if(stat(fn, &buf)) { + header = 1; + } + + fp = fopen(fn, "a"); + if(!fp) { + return(-1); + } + + if(header) { + fprintf(fp, "# udev persistent rules for optical devices\n\n"); + } + /* drop the last space from the end of 'aliases' */ + aliases[strlen(aliases)-1]='\0'; + fprintf(fp, "SUBSYSTEM==\"block\", ACTION==\"add\", ENV{ID_PATH}==\"%s\", SYMLINK+=\"%s\", " + "ENV{GENERATED}=\"yes\"\n", getenv("ID_PATH"), aliases); + fclose(fp); + return(0); +} + +int main(int argc, char **argv) +{ + int fd; + + if(argc < 2) { + printf("usage: %s rules_file\n", argv[0]); + return(1); + } + if(!getenv("ID_PATH")) { + printf("No ID_PATH variable is set!\n"); + return(1); + } + + /* uevents are processed by udev in parallel, but only one instance of + * optical_gen should update the rules */ + fd = open("/sys", O_RDONLY); + if(fd < 0) { + return(1); + } + if(flock(fd, LOCK_EX) < 0) { + return(1); + } + if (parse_existing(argv[1]) != 0) { + register_if("ID_CDROM", "cdrom", cdroms); + register_if("ID_CDROM_CD_RW", "cdrw", cdrws); + register_if("ID_CDROM_DVD", "dvd", dvds); + register_if("ID_CDROM_DVD_R", "dvdrw", dvdrws); + update_rules(argv[1]); + printf("%s\n", aliases); + } + flock(fd, LOCK_UN); + close(fd); + return(0); +} diff -Naur udev-096.orig/test/simple-build-check.sh udev-096/test/simple-build-check.sh --- udev-096.orig/test/simple-build-check.sh 2006-07-09 21:48:19.000000000 +0200 +++ udev-096/test/simple-build-check.sh 2006-08-02 04:06:02.000000000 +0200 @@ -8,6 +8,7 @@ extras/usb_id \ extras/dasd_id \ extras/cdrom_id \ + extras/optical_gen \ extras/edd_id \ extras/floppy \ extras/run_directory \