linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: Re: udev hangs under high loads
Date: Mon, 25 Oct 2004 02:51:14 +0000	[thread overview]
Message-ID: <20041025025114.GA29168@vrfy.org> (raw)
In-Reply-To: <20041023054119.GA11915@kroah.com>

[-- Attachment #1: Type: text/plain, Size: 3669 bytes --]

On Sun, Oct 24, 2004 at 07:08:41AM +0200, Kay Sievers wrote:
> On Sat, Oct 23, 2004 at 08:31:04AM +0200, Kay Sievers wrote:
> > On Fri, Oct 22, 2004 at 10:41:19PM -0700, Greg KH wrote:
> > > One of my coworkers (hi Nish) is trying to get 10000 disk support tested
> > > and working properly with linux and ran into a nasty udev issue
> > > yesterday.  It seems that under a very high load, with a whole bunch of
> > > hotplug events happening (for when the disks get added to the system),
> > > udev hangs.
> > > 
> > > It hangs in the "grabbing the database lock" portion of the code (don't
> > > have actual logs of where it hangs, will try to get that next week.)
> > > But the interesting thing is we almost handle everything properly.  
> > > udev creates the node, tries to write to the database.  Then the timer
> > > expires and we report this.  After the timer expires, udev is done for.
> > > It just sits and spins, doing a nanosleep constantly.  Have 500 of those
> > > instances all running at once, all at a nice level of -10 is a sure way
> > > to bring a box (even a relatively big one) down hard.
> > > 
> > > So, while I'll agree finding the root tdb locking bug is a good idea, I
> > > wanted to point out that perhaps we should just exit udev if our timeout
> > > expires, instead of still waiting around.  Or do you have a better
> > > solution?
> > 
> > Maybe the time the udev process locks the db is too long for that setup
> > and the serialization of the concurrent locks will take longer than the
> > timout of the process?
> > 
> > Here is a patch that tries to limit the access time to the db.
> > The current udev opens the db, reads all the rules, writes to the
> > db, executes the scripts and then closes the db. With this patch we open
> > the db after the rules and close it directly after writing to it.
> > 
> > A rate limit in udevd may help here too, to keep that under control.
> > 
> > > Try testing this out on your own using the scsi_debug module and adding
> > > a few hundred disks.  It also helps if you have scsi generic support
> > > enabled, as that creates 2 udev events for every disk created.
> > 
> > I expect that this is completely different on a SMP machine, but I will
> > try again. I once tried it with 200 disks and this was working well.
> 
> Here is another idea. I've ripped out the tdb code completely. We are
> maintaining a directory of files at /dev/.udevdb/* now. Every node will
> have a corresponding file (the slashes in DEVPATH are replaced by another
> char), that carries all neccessary data.  The files are human readable:
> 
>   [root@pim default]# ls -l /dev/.udevdb/*hda*
>   -rw-r--r--  1 root root 26 Oct 24 06:32 /dev/.udevdb/block@hda
>   -rw-r--r--  1 root root 32 Oct 24 06:32 /dev/.udevdb/block@hda@hda1
>   -rw-r--r--  1 root root 32 Oct 24 06:32 /dev/.udevdb/block@hda@hda2
>   -rw-r--r--  1 root root 32 Oct 24 06:32 /dev/.udevdb/block@hda@hda3
>   -rw-r--r--  1 root root 54 Oct 24 06:32 /dev/.udevdb/block@hdc
> 
>   [root@pim default]# cat /dev/.udevdb/block@hdc
>   P:/block/hdc
>   N:hdc
>   S:cdrom dvd cdwriter dvdwriter
>   A:0
> 
> This way we have _no_ locking at all in userspace, every event operation
> is completely independent from other events. No need to synchronize anything,
> which is expected to be much much faster and reliable on your 10.000 disk
> system. It may also work over NFS.
> 
> The patch is complete, but not well tested. It just stopped working on
> it, after the regression test was successful and my box was able to
> reboot and remove the symlinks grabbed form the files :)

New patch with a fix for a bug introduced in udevinfo.

Thanks,
Kay

[-- Attachment #2: udev-kill-tdb-02.patch --]
[-- Type: text/plain, Size: 35723 bytes --]

diff -Nru a/Makefile b/Makefile
--- a/Makefile	2004-10-25 04:48:06 +02:00
+++ b/Makefile	2004-10-25 04:48:06 +02:00
@@ -113,11 +113,6 @@
 
 CFLAGS := -pipe
 
-# set up the proper tdb spinlock code if we can
-ifeq ($(strip $(ARCH)),i386)
-	CFLAGS += -DUSE_SPINLOCKS -DINTEL_SPINLOCKS
-endif
-
 ifeq ($(strip $(USE_LOG)),true)
 	CFLAGS  += -DLOG
 endif
@@ -201,9 +196,6 @@
 	fi
 	$(MAKE) -C klibc SUBDIRS=klibc
 
-TDB =	tdb/tdb.o	\
-	tdb/spinlock.o
-
 SYSFS =	$(PWD)/libsysfs/sysfs_bus.o	\
 	$(PWD)/libsysfs/sysfs_class.o	\
 	$(PWD)/libsysfs/sysfs_device.o	\
@@ -221,8 +213,7 @@
 	namedev.o	\
 	namedev_parse.o	\
 	dev_d.o		\
-	$(SYSFS)	\
-	$(TDB)
+	$(SYSFS)
 
 HEADERS =	udev.h		\
 		udev_lib.h	\
@@ -262,8 +253,8 @@
 udev_version.h:
 	@echo "Creating udev_version.h"
 	@echo \#define UDEV_VERSION		\"$(VERSION)\" > $@
-	@echo \#define UDEV_ROOT		\"$(udevdir)/\" >> $@
-	@echo \#define UDEV_DB			\"$(udevdir)/.udev.tdb\" >> $@
+	@echo \#define UDEV_ROOT		\"$(udevdir)\" >> $@
+	@echo \#define UDEV_DB			\"$(udevdir)/.udevdb\" >> $@
 	@echo \#define UDEV_CONFIG_DIR		\"$(configdir)\" >> $@
 	@echo \#define UDEV_CONFIG_FILE		\"$(configdir)/udev.conf\" >> $@
 	@echo \#define UDEV_RULES_FILE		\"$(configdir)/rules.d\" >> $@
@@ -300,7 +291,7 @@
 	$(QUIET) $(STRIPCMD) $@
 
 $(INFO): $(LIBC) $(INFO).o $(OBJS) $(HEADERS)
-	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevinfo.o udev_lib.o udev_config.o udevdb.o $(SYSFS) $(TDB) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) udevinfo.o udev_lib.o udev_config.o udevdb.o $(SYSFS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
 	$(QUIET) $(STRIPCMD) $@
 
 $(DAEMON): $(LIBC) $(DAEMON).o $(OBJS) udevd.h
@@ -337,7 +328,8 @@
 	$(MAKE) -C klibc spotless
 	-rm -f klibc/linux
 
-DISTFILES = $(shell find . \( -not -name '.' \) -print | grep -v -e CVS -e "\.tar\.gz$" -e "\/\." -e releases -e BitKeeper -e SCCS -e "\.tdb$" -e test/sys | sort )
+DISTFILES = $(shell find . \( -not -name '.' \) -print | grep -v -e CVS -e "\.tar\.gz" -e "\/\." -e releases -e BitKeeper -e SCCS -e test/sys | sort )
+#DISTFILES = $(shell find . \( -not -name '.' \) -print | grep -v -e CVS -e "\.tar\.gz$" -e "\/\." -e releases -e BitKeeper -e SCCS -e "\.tdb$" -e test/sys | sort )
 DISTDIR := $(RELEASE_NAME)
 srcdir = .
 release: clean
@@ -430,7 +422,7 @@
 	- ln -f -s $(sbindir)/$(WAIT) $(DESTDIR)$(hotplugdir)/05-wait_for_sysfs.hotplug
 ifndef DESTDIR
 	- killall udevd
-	- rm -f $(udevdir)/.udev.tdb
+	- rm -f $(udevdir)/.udev/*
 endif
 	@extras="$(EXTRAS)" ; for target in $$extras ; do \
 		echo $$target ; \
@@ -456,7 +448,7 @@
 	- rm $(usrbindir)/$(TESTER)
 	- rm $(usrbindir)/$(WAIT)
 	- rmdir $(hotplugdir)
-	- rm $(udevdir)/.udev.tdb
+	- rm -f $(udevdir)/.udev/*
 	- rmdir $(udevdir)
 	@extras="$(EXTRAS)" ; for target in $$extras ; do \
 		echo $$target ; \
diff -Nru a/dev_d.c b/dev_d.c
--- a/dev_d.c	2004-10-25 04:48:06 +02:00
+++ b/dev_d.c	2004-10-25 04:48:06 +02:00
@@ -47,7 +47,6 @@
 	switch (pid) {
 	case 0:
 		/* child */
-		udevdb_exit();  /* close udevdb */
 		fd = open("/dev/null", O_RDWR);
 		if ( fd >= 0) {
 			dup2(fd, STDOUT_FILENO);
diff -Nru a/etc/udev/udev.conf.in b/etc/udev/udev.conf.in
--- a/etc/udev/udev.conf.in	2004-10-25 04:48:06 +02:00
+++ b/etc/udev/udev.conf.in	2004-10-25 04:48:06 +02:00
@@ -6,16 +6,16 @@
 
 
 # udev_root - where in the filesystem to place the device nodes
-udev_root="@udevdir@/"
+udev_root="@udevdir@"
 
 # udev_db - The name and location of the udev database.
-udev_db="@udevdir@/.udev.tdb"
+udev_db="@udevdir@/.udevdb"
 
 # udev_rules - The name and location of the udev rules file
-udev_rules="@configdir@/rules.d/"
+udev_rules="@configdir@/rules.d"
 
 # udev_permissions - The name and location of the udev permission file
-udev_permissions="@configdir@/permissions.d/"
+udev_permissions="@configdir@/permissions.d"
 
 # default_mode - set the default mode for all nodes that have no
 #                explicit match in the permissions file
diff -Nru a/namedev.c b/namedev.c
--- a/namedev.c	2004-10-25 04:48:06 +02:00
+++ b/namedev.c	2004-10-25 04:48:06 +02:00
@@ -184,29 +184,29 @@
  *  @param  name                Name to check for
  *  @return                     0 if <name> didn't exist and N otherwise.
  */
-static unsigned int find_free_number (struct udevice *udev, char *name)
+static int find_free_number(struct udevice *udev, const char *name)
 {
-	char temp[NAME_SIZE];
-	char path[NAME_SIZE];
-	struct udevice dev;
-	int result;
-
-	/* have to sweep the database for each lookup */
-	result = 0;
-	strncpy(temp, name, sizeof (temp));
+	char filename[NAME_SIZE];
+	int num = 0;
+	struct udevice db_udev;
+
+	strfieldcpy(filename, name);
 	while (1) {
-		if (udevdb_get_dev_byname(temp, path, &dev) != 0)
-			goto found;
-		/* symlink might be stale if $(udevroot) isn't cleaned; check
-		 * on major/minor to see if it's the same device
-		 */
-		if (dev.major == udev->major && dev.minor == udev->minor)
-			goto found;
-		snprintf (temp, sizeof(temp), "%s%d", name, ++result);
+		dbg("look for existing node '%s'", filename);
+		memset(&db_udev, 0x00, sizeof(struct udevice));
+		if (udevdb_get_dev_byname(&db_udev, filename) != 0) {
+			dbg("free num=%d", num);
+			return num;
+		}
+
+		num++;
+		if (num > 1000) {
+			info("find_free_number gone crazy (num=%d), aborted", num);
+			return -1;
+		}
+		snprintf(filename, NAME_SIZE-1, "%s%d", name, num);
+		filename[NAME_SIZE-1] = '\0';
 	}
-
-found:
-	return result;
 }
 
 static void apply_format(struct udevice *udev, char *string, size_t maxsize,
@@ -329,7 +329,7 @@
 		case 'e':
 			next_free_number = find_free_number(udev, string);
 			if (next_free_number > 0) {
-				snprintf(temp2, sizeof(temp2), "%d", next_free_number);
+				sprintf(temp2, "%d", next_free_number);
 				strfieldcatmax(string, temp2, maxsize);
 			}
 			break;
diff -Nru a/test/udev-test.pl b/test/udev-test.pl
--- a/test/udev-test.pl	2004-10-25 04:48:06 +02:00
+++ b/test/udev-test.pl	2004-10-25 04:48:06 +02:00
@@ -30,7 +30,7 @@
 my $sysfs     = "sys/";
 my $udev_bin  = "../udev";
 my $udev_root = "udev-root/"; # !!! directory will be removed !!!
-my $udev_db   = ".udev.tdb";
+my $udev_db   = ".udevdb";
 my $perm      = "udev.permissions";
 my $main_conf = "udev-test.conf";
 my $conf_tmp  = "udev-test.rules";
@@ -1258,7 +1258,7 @@
 	}
 
 	if (defined($config->{option}) && $config->{option} eq "clear") {
-		unlink($udev_db);
+		system("rm -rf $udev_db");
 		system("rm -rf $udev_root");
 		mkdir($udev_root) || die "unable to create udev_root: $udev_root\n";
 	}
@@ -1302,7 +1302,7 @@
 print "$error errors occured\n\n";
 
 # cleanup
-unlink($udev_db);
+system("rm -rf $udev_db");
 system("rm -rf $udev_root");
 unlink($conf_tmp);
 unlink($main_conf);
diff -Nru a/udev.8.in b/udev.8.in
--- a/udev.8.in	2004-10-25 04:48:06 +02:00
+++ b/udev.8.in	2004-10-25 04:48:06 +02:00
@@ -74,7 +74,7 @@
 .TP
 .B udev_db
 The name and location of the udev database. The default value is
-.IR @udevdir@/.udev.tdb .
+.IR @udevdir@/.udevdb .
 .TP
 .B udev_rules
 The name of the udev rules file or directory to look for files with the suffix
@@ -117,7 +117,7 @@
 udev_root="/udev"
 
 # udev_db - The name and location of the udev database
-udev_db="/udev/.udev.tdb"
+udev_db="/udev/.udevdb"
 
 # udev_rules - The name of the udev rules file or directory to look
                for files with the suffix .rules
diff -Nru a/udev.c b/udev.c
--- a/udev.c	2004-10-25 04:48:06 +02:00
+++ b/udev.c	2004-10-25 04:48:06 +02:00
@@ -38,8 +38,6 @@
 #include "namedev.h"
 #include "udevdb.h"
 
-/* timeout flag for udevdb */
-extern sig_atomic_t gotalarm;
 
 /* global variables */
 char **main_argv;
@@ -64,12 +62,11 @@
 {
 	switch (signum) {
 		case SIGALRM:
-			gotalarm = 1;
-			info("error: timeout reached, event probably not handled correctly");
-			break;
+			info("we give up, timeout reached, event probably not handled correctly");
+			logging_close();
+			exit(1);
 		case SIGINT:
 		case SIGTERM:
-			udevdb_exit();
 			exit(20 + signum);
 		default:
 			dbg("unhandled signal %d", signum);
@@ -156,10 +153,6 @@
 	/* trigger timout to interrupt blocking syscalls */
 	alarm(ALARM_TIMEOUT);
 
-	/* initialize udev database */
-	if (udevdb_init(UDEVDB_DEFAULT) != 0)
-		info("error: unable to initialize database, continuing without database");
-
 	switch(act_type) {
 	case UDEVSTART:
 		dbg("udevstart");
@@ -198,8 +191,6 @@
 		/* run scripts */
 		dev_d_execute(&udev);
 	}
-
-	udevdb_exit();
 
 exit:
 	logging_close();
diff -Nru a/udev.h b/udev.h
--- a/udev.h	2004-10-25 04:48:06 +02:00
+++ b/udev.h	2004-10-25 04:48:06 +02:00
@@ -41,26 +41,21 @@
 
 #define LINE_SIZE			256
 
-/* length of public data to store in udevdb */
-#define UDEVICE_DB_LEN (offsetof(struct udevice, devpath))
-
 struct udevice {
+	char devpath[DEVPATH_SIZE];
+	char subsystem[SUBSYSTEM_SIZE];
 	char name[NAME_SIZE];
 	char owner[OWNER_SIZE];
 	char group[GROUP_SIZE];
 	char type;
 	int major;
 	int minor;
-	unsigned int mode;	/* not mode_t due to conflicting definitions in different libcs */
+	mode_t mode;
 	char symlink[NAME_SIZE];
 	int partitions;
 	int config_line;
 	char config_file[NAME_SIZE];
 	long config_uptime;
-
-	/* private data, not stored in udevdb */
-	char devpath[DEVPATH_SIZE];
-	char subsystem[SUBSYSTEM_SIZE];
 	char bus_id[SYSFS_NAME_LEN];
 	char bus[SYSFS_NAME_LEN];
 	char program_result[NAME_SIZE];
@@ -81,7 +76,7 @@
 extern char **main_envp;
 extern char sysfs_path[SYSFS_PATH_MAX];
 extern char udev_root[PATH_MAX];
-extern char udev_db_filename[PATH_MAX+NAME_MAX];
+extern char udev_db_path[PATH_MAX+NAME_MAX];
 extern char udev_permissions_filename[PATH_MAX+NAME_MAX];
 extern char udev_config_filename[PATH_MAX+NAME_MAX];
 extern char udev_rules_filename[PATH_MAX+NAME_MAX];
diff -Nru a/udev_add.c b/udev_add.c
--- a/udev_add.c	2004-10-25 04:48:06 +02:00
+++ b/udev_add.c	2004-10-25 04:48:06 +02:00
@@ -68,37 +68,6 @@
 	return -1;
 }
 
-static int create_path(char *file)
-{
-	char p[NAME_SIZE];
-	char *pos;
-	int retval;
-	struct stat stats;
-	
-	strfieldcpy(p, file);
-	pos = strchr(p+1, '/');
-	while (1) {
-		pos = strchr(pos+1, '/');
-		if (pos == NULL)
-			break;
-		*pos = 0x00;
-		if (stat(p, &stats)) {
-			selinux_setfscreatecon(p, S_IFDIR);
-			retval = mkdir(p, 0755);
-			if (retval != 0) {
-				dbg("mkdir(%s) failed with error '%s'",
-				    p, strerror(errno));
-				return retval;
-			}
-			dbg("created '%s'", p);
-		} else {
-			selinux_setfilecon(p, S_IFDIR);
-		}
-		*pos = '/';
-	}
-	return 0;
-}
-
 static int make_node(char *file, int major, int minor, unsigned int mode, uid_t uid, gid_t gid)
 {
 	struct stat stats;
@@ -152,8 +121,6 @@
 static int create_node(struct udevice *udev)
 {
 	char filename[NAME_SIZE];
-	char linkname[NAME_SIZE];
-	char linktarget[NAME_SIZE];
 	char partitionname[NAME_SIZE];
 	uid_t uid = 0;
 	gid_t gid = 0;
@@ -162,8 +129,8 @@
 	char *pos;
 	int len;
 
-	strfieldcpy(filename, udev_root);
-	strfieldcat(filename, udev->name);
+	snprintf(filename, NAME_SIZE-1, "%s/%s", udev_root, udev->name);
+	filename[NAME_SIZE-1] = '\0';
 
 	switch (udev->type) {
 	case 'b':
@@ -239,9 +206,13 @@
 
 	/* create symlink(s) if requested */
 	foreach_strpart(udev->symlink, " ", pos, len) {
+		char linkname[NAME_SIZE];
+		char linktarget[NAME_SIZE];
+
 		strfieldcpymax(linkname, pos, len+1);
-		strfieldcpy(filename, udev_root);
-		strfieldcat(filename, linkname);
+		snprintf(filename, NAME_SIZE-1, "%s/%s", udev_root, linkname);
+		filename[NAME_SIZE-1] = '\0';
+
 		dbg("symlink '%s' to node '%s' requested", filename, udev->name);
 		if (!udev->test_run)
 			if (strrchr(linkname, '/'))
@@ -337,7 +308,8 @@
 			    "remove might not work for custom names");
 
 		/* use full path to the environment */
-		snprintf(udev->devname, NAME_SIZE-1, "%s%s", udev_root, udev->name);
+		snprintf(udev->devname, NAME_SIZE-1, "%s/%s", udev_root, udev->name);
+		udev->devname[NAME_SIZE-1] = '\0';
 
 	} else if (udev->type == 'n') {
 		/* look if we want to change the name of the netif */
diff -Nru a/udev_config.c b/udev_config.c
--- a/udev_config.c	2004-10-25 04:48:06 +02:00
+++ b/udev_config.c	2004-10-25 04:48:06 +02:00
@@ -42,7 +42,7 @@
 /* global variables */
 char sysfs_path[SYSFS_PATH_MAX];
 char udev_root[PATH_MAX];
-char udev_db_filename[PATH_MAX+NAME_MAX];
+char udev_db_path[PATH_MAX+NAME_MAX];
 char udev_permissions_filename[PATH_MAX+NAME_MAX];
 char udev_rules_filename[PATH_MAX+NAME_MAX];
 char udev_config_filename[PATH_MAX+NAME_MAX];
@@ -72,7 +72,7 @@
 	 * If any config values are specified, they will
 	 * override these values. */
 	strfieldcpy(udev_root, UDEV_ROOT);
-	strfieldcpy(udev_db_filename, UDEV_DB);
+	strfieldcpy(udev_db_path, UDEV_DB);
 	strfieldcpy(udev_config_filename, UDEV_CONFIG_FILE);
 	strfieldcpy(udev_rules_filename, UDEV_RULES_FILE);
 	strfieldcpy(udev_permissions_filename, UDEV_PERMISSION_FILE);
@@ -181,24 +181,25 @@
 
 		if (strcasecmp(variable, "udev_root") == 0) {
 			strfieldcpy(udev_root, value);
-			leading_slash(udev_root);
+			no_trailing_slash(udev_root);
 			continue;
 		}
 
 		if (strcasecmp(variable, "udev_db") == 0) {
-			strfieldcpy(udev_db_filename, value);
+			strfieldcpy(udev_db_path, value);
+			no_trailing_slash(udev_db_path);
 			continue;
 		}
 
 		if (strcasecmp(variable, "udev_rules") == 0) {
 			strfieldcpy(udev_rules_filename, value);
-			no_leading_slash(udev_rules_filename);
+			no_trailing_slash(udev_rules_filename);
 			continue;
 		}
 
 		if (strcasecmp(variable, "udev_permissions") == 0) {
 			strfieldcpy(udev_permissions_filename, value);
-			no_leading_slash(udev_permissions_filename);
+			no_trailing_slash(udev_permissions_filename);
 			continue;
 		}
 
@@ -244,7 +245,7 @@
 		temp = getenv("SYSFS_PATH");
 		if (temp != NULL) {
 			strfieldcpy(sysfs_path, temp);
-			no_leading_slash(sysfs_path);
+			no_trailing_slash(sysfs_path);
 		}
 
 		temp = getenv("UDEV_CONFIG_FILE");
@@ -255,7 +256,7 @@
 	dbg("sysfs_path='%s'", sysfs_path);
 	dbg_parse("udev_root = %s", udev_root);
 	dbg_parse("udev_config_filename = %s", udev_config_filename);
-	dbg_parse("udev_db_filename = %s", udev_db_filename);
+	dbg_parse("udev_db_path = %s", udev_db_path);
 	dbg_parse("udev_rules_filename = %s", udev_rules_filename);
 	dbg_parse("udev_permissions_filename = %s", udev_permissions_filename);
 	dbg_parse("udev_log = %d", udev_log);
@@ -264,7 +265,7 @@
 
 	dbg("udev_root = %s", udev_root);
 	dbg("udev_config_filename = %s", udev_config_filename);
-	dbg("udev_db_filename = %s", udev_db_filename);
+	dbg("udev_db_path = %s", udev_db_path);
 	dbg("udev_rules_filename = %s", udev_rules_filename);
 	dbg("udev_permissions_filename = %s", udev_permissions_filename);
 	dbg("udev_log_str = %d", udev_log);
diff -Nru a/udev_lib.c b/udev_lib.c
--- a/udev_lib.c	2004-10-25 04:48:06 +02:00
+++ b/udev_lib.c	2004-10-25 04:48:06 +02:00
@@ -120,6 +120,33 @@
 	udev->type = get_device_type(devpath, subsystem);
 }
 
+int create_path(const char *path)
+{
+	char p[NAME_SIZE];
+	char *pos;
+	struct stat stats;
+
+	strcpy (p, path);
+	pos = strrchr(p, '/');
+	if (pos == p || pos == NULL)
+		return 0;
+
+	while (pos[-1] == '/')
+		pos--;
+
+	pos[0] = '\0';
+
+	dbg("stat '%s'\n", p);
+	if (stat (p, &stats) == 0 && (stats.st_mode & S_IFMT) == S_IFDIR)
+		return 0;
+
+	if (create_path (p) != 0)
+		return -1;
+
+	dbg("mkdir '%s'\n", p);
+	return mkdir(p, 0755);
+}
+
 int file_map(const char *filename, char **buf, size_t *bufsize)
 {
 	struct stat stats;
@@ -161,18 +188,7 @@
 	return count - cur;
 }
 
-void leading_slash(char *path)
-{
-	int len;
-
-	len = strlen(path);
-	if (len > 0 && path[len-1] != '/') {
-		path[len] = '/';
-		path[len+1] = '\0';
-	}
-}
-
-void no_leading_slash(char *path)
+void no_trailing_slash(char *path)
 {
 	int len;
 
@@ -249,9 +265,8 @@
 
 	/* call function for every file in the list */
 	list_for_each_entry_safe(loop_file, tmp_file, &file_list, list) {
-		strfieldcpy(file, dirname);
-		strfieldcat(file, "/");
-		strfieldcat(file, loop_file->name);
+		snprintf(file, NAME_SIZE-1, "%s/%s", dirname, loop_file->name);
+		file[NAME_SIZE-1] = '\0';
 
 		fnct(file);
 
diff -Nru a/udev_lib.h b/udev_lib.h
--- a/udev_lib.h	2004-10-25 04:48:06 +02:00
+++ b/udev_lib.h	2004-10-25 04:48:06 +02:00
@@ -83,11 +83,11 @@
 extern char *get_subsystem(char *subsystem);
 extern char get_device_type(const char *path, const char *subsystem);
 extern void udev_set_values(struct udevice *udev, const char* devpath, const char *subsystem);
+extern int create_path(const char *path);
 extern int file_map(const char *filename, char **buf, size_t *bufsize);
 extern void file_unmap(char *buf, size_t bufsize);
 extern size_t buf_get_line(char *buf, size_t buflen, size_t cur);
-extern void leading_slash(char *path);
-extern void no_leading_slash(char *path);
+extern void no_trailing_slash(char *path);
 extern int  call_foreach_file(int fnct(char *f) , char *filename, char *extension);
 extern int set_cloexec_flag (int desc, int value);
 
diff -Nru a/udev_remove.c b/udev_remove.c
--- a/udev_remove.c	2004-10-25 04:48:06 +02:00
+++ b/udev_remove.c	2004-10-25 04:48:06 +02:00
@@ -102,10 +102,9 @@
 	return retval;
 }
 
-static int delete_node(struct udevice *dev)
+static int delete_node(struct udevice *udev)
 {
 	char filename[NAME_SIZE];
-	char linkname[NAME_SIZE];
 	char partitionname[NAME_SIZE];
 	int retval;
 	int i;
@@ -113,8 +112,8 @@
 	int len;
 	int num;
 
-	strfieldcpy(filename, udev_root);
-	strfieldcat(filename, dev->name);
+	snprintf(filename, NAME_SIZE-1, "%s/%s", udev_root, udev->name);
+	filename[NAME_SIZE-1] = '\0';
 
 	info("removing device node '%s'", filename);
 	retval = secure_unlink(filename);
@@ -122,7 +121,7 @@
 		return retval;
 
 	/* remove all_partitions nodes */
-	num = dev->partitions;
+	num = udev->partitions;
 	if (num > 0) {
 		info("removing all_partitions '%s[1-%i]'", filename, num);
 		if (num > PARTITIONS_COUNT) {
@@ -137,13 +136,15 @@
 	}
 
 	/* remove subdirectories */
-	if (strchr(dev->name, '/'))
+	if (strchr(udev->name, '/'))
 		delete_path(filename);
 
-	foreach_strpart(dev->symlink, " ", pos, len) {
+	foreach_strpart(udev->symlink, " ", pos, len) {
+		char linkname[NAME_SIZE];
+
 		strfieldcpymax(linkname, pos, len+1);
-		strfieldcpy(filename, udev_root);
-		strfieldcat(filename, linkname);
+		snprintf(filename, NAME_SIZE-1, "%s/%s", udev_root, linkname);
+		filename[NAME_SIZE-1] = '\0';
 
 		dbg("unlinking symlink '%s'", filename);
 		retval = unlink(filename);
@@ -154,7 +155,7 @@
 				filename, strerror(errno));
 			return retval;
 		}
-		if (strchr(dev->symlink, '/')) {
+		if (strchr(udev->symlink, '/')) {
 			delete_path(filename);
 		}
 	}
@@ -168,18 +169,14 @@
  */
 int udev_remove_device(struct udevice *udev)
 {
-	struct udevice db_dev;
 	const char *temp;
 	int retval;
 
 	if (udev->type != 'b' && udev->type != 'c')
 		return 0;
 
-	retval = udevdb_get_dev(udev->devpath, &db_dev);
-	if (retval == 0) {
-		/* copy over the stored values to our device */
-		memcpy(udev, &db_dev, UDEVICE_DB_LEN);
-	} else {
+	retval = udevdb_get_dev(udev);
+	if (retval) {
 		/* fall back to kernel name */
 		temp = strrchr(udev->devpath, '/');
 		if (temp == NULL)
@@ -189,10 +186,10 @@
 	}
 
 	dbg("remove name='%s'", udev->name);
-	udevdb_delete_dev(udev->devpath);
+	udevdb_delete_dev(udev);
 
 	/* use full path to the environment */
-	snprintf(udev->devname, NAME_SIZE-1, "%s%s", udev_root, udev->name);
+	snprintf(udev->devname, NAME_SIZE-1, "%s/%s", udev_root, udev->name);
 
 	return delete_node(udev);
 }
diff -Nru a/udevd.c b/udevd.c
--- a/udevd.c	2004-10-25 04:48:06 +02:00
+++ b/udevd.c	2004-10-25 04:48:06 +02:00
@@ -147,7 +147,7 @@
 	switch (pid) {
 	case 0:
 		/* child */
-		execle(udev_bin, "udev", msg->subsystem, NULL, env);
+		execle(udev_bin, udev_bin, msg->subsystem, NULL, env);
 		dbg("exec of child failed");
 		_exit(1);
 		break;
diff -Nru a/udevdb.c b/udevdb.c
--- a/udevdb.c	2004-10-25 04:48:06 +02:00
+++ b/udevdb.c	2004-10-25 04:48:06 +02:00
@@ -1,10 +1,10 @@
 /*
- * udevdb.c - udev database library
+ * udevdb.c
  *
  * Userspace devfs
  *
  * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2003 IBM Corp.
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
  *
  *	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
@@ -21,216 +21,194 @@
  *
  */
 
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <stddef.h>
 #include <fcntl.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <errno.h>
-#include <signal.h>
+#include <dirent.h>
 
 #include "libsysfs/sysfs/libsysfs.h"
 #include "udev.h"
 #include "udev_lib.h"
-#include "udev_version.h"
 #include "logging.h"
-#include "namedev.h"
 #include "udevdb.h"
-#include "tdb/tdb.h"
 
-static TDB_CONTEXT *udevdb;
-sig_atomic_t gotalarm;
+#define PATH_TO_NAME_CHAR		'@'
 
-int udevdb_add_dev(struct udevice *udev)
+static int get_db_filename(struct udevice *udev, char *filename, int len)
 {
-	TDB_DATA key, data;
-	char keystr[SYSFS_PATH_MAX];
-
-	if (udev->test_run)
-		return 0;
-
-	if (udevdb == NULL)
-		return -1;
+	char devpath[SYSFS_PATH_MAX];
+	char *pos;
 
-	memset(keystr, 0x00, SYSFS_PATH_MAX);
-	strfieldcpy(keystr, udev->devpath);
-	key.dptr = keystr;
-	key.dsize = strlen(keystr) + 1;
-
-	data.dptr = (void *) udev;
-	data.dsize = UDEVICE_DB_LEN;
-	dbg("store key '%s' for device '%s'", keystr, udev->name);
+	/* replace '/' to transform path into a filename */
+	strfieldcpy(devpath, udev->devpath);
+	pos = strchr(&devpath[1], '/');
+	while (pos) {
+		pos[0] = PATH_TO_NAME_CHAR;
+		pos = strchr(&pos[1], '/');
+	}
+	snprintf(filename, len-1, "%s%s", udev_db_path, devpath);
+	filename[len-1] = '\0';
 
-	return tdb_store(udevdb, key, data, TDB_REPLACE); 
+	return 0;
 }
 
-int udevdb_get_dev(const char *path, struct udevice *udev)
+int udevdb_add_dev(struct udevice *udev)
 {
-	TDB_DATA key, data;
+	char filename[SYSFS_PATH_MAX];
+	FILE *f;
 
-	if (udevdb == NULL)
-		return -1;
+	if (udev->test_run)
+		return 0;
 
-	if (path == NULL)
-		return -ENODEV;
+	get_db_filename(udev, filename, SYSFS_PATH_MAX);
 
-	key.dptr = (void *)path;
-	key.dsize = strlen(path) + 1;
+	create_path(filename);
 
-	data = tdb_fetch(udevdb, key);
-	if (data.dptr == NULL || data.dsize == 0)
-		return -ENODEV;
+	f = fopen(filename, "w");
+	if (f == NULL) {
+		dbg("unable to create db file '%s'", filename);
+		return -1;
+	}
+	dbg("storing data for device '%s' in '%s'", udev->devpath, filename);
 
-	memset(udev, 0x00, sizeof(struct udevice));
-	memcpy(udev, data.dptr, UDEVICE_DB_LEN);
+	fprintf(f, "P:%s\n", udev->devpath);
+	fprintf(f, "N:%s\n", udev->name);
+	fprintf(f, "S:%s\n", udev->symlink);
+	fprintf(f, "A:%d\n", udev->partitions);
+
+	fclose(f);
 
 	return 0;
 }
 
-int udevdb_delete_dev(const char *path)
+static int parse_db_file(struct udevice *udev, const char *filename)
 {
-	TDB_DATA key;
-	char keystr[SYSFS_PATH_MAX];
+	char line[NAME_SIZE];
+	char *bufline;
+	char *buf;
+	size_t bufsize;
+	size_t cur;
+	size_t count;
 
-	if (udevdb == NULL)
+	if (file_map(filename, &buf, &bufsize) != 0) {
+		dbg("unable to read db file '%s'", filename);
 		return -1;
+	}
 
-	if (path == NULL)
-		return -EINVAL;
-
-	memset(keystr, 0, sizeof(keystr));
-	strfieldcpy(keystr, path);
+	cur = 0;
+	while (cur < bufsize) {
+		count = buf_get_line(buf, bufsize, cur);
+		bufline = &buf[cur];
+		cur += count+1;
+
+		switch(bufline[0]) {
+		case 'P':
+			if (count > DEVPATH_SIZE)
+				count = DEVPATH_SIZE-1;
+			strncpy(udev->devpath, &bufline[2], count-2);
+			break;
+		case 'N':
+			if (count > NAME_SIZE)
+				count = NAME_SIZE-1;
+			strncpy(udev->name, &bufline[2], count-2);
+			break;
+		case 'S':
+			if (count > NAME_SIZE)
+				count = NAME_SIZE-1;
+			strncpy(udev->symlink, &bufline[2], count-2);
+			break;
+		case 'A':
+			strfieldcpy(line, &bufline[2]);
+			udev->partitions = atoi(line);
+			break;
+		}
+	}
 
-	key.dptr = keystr;
-	key.dsize = strlen(keystr) + 1;
+	if (udev->name[0] == '\0')
+		return -1;
 
-	return tdb_delete(udevdb, key);
+	return 0;
 }
 
-/**
- * udevdb_exit: closes database
- */
-void udevdb_exit(void)
+int udevdb_get_dev(struct udevice *udev)
 {
-	if (udevdb != NULL) {
-		tdb_close(udevdb);
-		udevdb = NULL;
-	}
+	char filename[SYSFS_PATH_MAX];
+
+	get_db_filename(udev, filename, SYSFS_PATH_MAX);
+
+	return parse_db_file(udev, filename);
 }
 
-/**
- * udevdb_init: initializes database
- * @init_flag: UDEVDB_INTERNAL - database stays in memory
- *	       UDEVDB_DEFAULT - database is written to a file
- */
-int udevdb_init(int init_flag)
+int udevdb_delete_dev(struct udevice *udev)
 {
-	if (init_flag != UDEVDB_DEFAULT && init_flag != UDEVDB_INTERNAL)
-		return -EINVAL;
+	char filename[SYSFS_PATH_MAX];
 
-	tdb_set_lock_alarm(&gotalarm);
+	get_db_filename(udev, filename, SYSFS_PATH_MAX);
+	unlink(filename);
 
-	udevdb = tdb_open(udev_db_filename, 0, init_flag, O_RDWR | O_CREAT, 0644);
-	if (udevdb == NULL) {
-		if (init_flag == UDEVDB_INTERNAL)
-			dbg("unable to initialize in-memory database");
-		else
-			dbg("unable to initialize database at '%s'", udev_db_filename);
-		return -EACCES;
-	}
 	return 0;
 }
 
-/**
- * udevdb_open_ro: open database for reading
- */
-int udevdb_open_ro(void)
+int udevdb_get_dev_byname(struct udevice *udev, const char *name)
 {
-	udevdb = tdb_open(udev_db_filename, 0, 0, O_RDONLY, 0);
-	if (udevdb == NULL) {
-		dbg("unable to open database at '%s'", udev_db_filename);
-		return -EACCES;
+	struct dirent *ent;
+	DIR *dir;
+	char filename[NAME_SIZE];
+	struct udevice db_udev;
+
+	dir = opendir(udev_db_path);
+	if (dir == NULL) {
+		dbg("unable to udev db '%s'", udev_db_path);
+		return -1;
 	}
-	return 0;
-}
 
-static int (*user_record_callback) (const char *path, struct udevice *dev);
+	while (1) {
+		ent = readdir(dir);
+		if (ent == NULL || ent->d_name[0] == '\0')
+			break;
 
-static int traverse_callback(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
-{
-	return user_record_callback((char*) key.dptr, (struct udevice*) dbuf.dptr);
-}
+		if (ent->d_name[0] == '.')
+			continue;
 
-/**
- * udevdb_call_foreach: dumps whole database by passing record data to user function
- * @user_record_handler: user function called for every record in the database
- */
-int udevdb_call_foreach(int (*user_record_handler) (const char *path, struct udevice *dev))
-{
-	int retval = 0;
+		snprintf(filename, NAME_SIZE-1, "%s/%s", udev_db_path, ent->d_name);
+		filename[NAME_SIZE-1] = '\0';
 
-	if (udevdb == NULL)
-		return -1;
+		memset(&db_udev, 0x00, sizeof(struct udevice));
+		if (parse_db_file(&db_udev, filename) == 0) {
+			char *pos;
+			int len;
 
-	if (user_record_handler == NULL) {
-		dbg("invalid user record handling function");
-		return -EINVAL;
-	}
-	user_record_callback = user_record_handler;
-	retval = tdb_traverse(udevdb, traverse_callback, NULL);
-	if (retval < 0)
-		return -ENODEV;
-	else
-		return 0;
-}
+			if (strncmp(name, db_udev.name, NAME_SIZE) == 0) {
+				goto found;
+			}
 
-static struct udevice *find_dev;
-static char *find_path;
-static const char *find_name;
-static int find_found;
+			foreach_strpart(db_udev.symlink, " ", pos, len) {
+				if (strncmp(name, pos, len) != 0)
+					continue;
 
-static int find_device_by_name(const char *path, struct udevice *udev)
-{
-	char *pos;
-	int len;
+				if (len == strlen(name))
+					goto found;
+			}
 
-	if (strncmp(udev->name, find_name, sizeof(udev->name)) == 0) {
-		memcpy(find_dev, udev, sizeof(struct udevice));
-		strfieldcpymax(find_path, path, NAME_SIZE);
-		find_found = 1;
-		/* stop search */
-		return 1;
-	}
-	/* look for matching symlink*/
-	foreach_strpart(udev->symlink, " ", pos, len) {
-		if (strncmp(pos, find_name, len) != 0)
-			continue;
+		}
+	}
 
-		if (len != strlen(find_name))
-			continue;
+	closedir(dir);
 
-		memcpy(find_dev, udev, sizeof(struct udevice));
-		strfieldcpymax(find_path, path, NAME_SIZE);
-		find_found = 1;
-		return 1;
-	}
-	return 0;
-}
+	return -1;
 
-/**
- * udevdb_get_dev_byname: search device with given name by traversing the whole database
- */
-int udevdb_get_dev_byname(const char *name, char *path, struct udevice *dev)
-{
-	find_found = 0;
-	find_path = path;
-	find_dev = dev;
-	find_name = name;
-	udevdb_call_foreach(find_device_by_name);
-	if (find_found == 1)
-		return 0;
-	else
-		return -1;
+found:
+	closedir(dir);
+
+	strfieldcpy(udev->devpath, db_udev.devpath);
+	strfieldcpy(udev->name, db_udev.name);
+	strfieldcpy(udev->symlink, db_udev.symlink);
+	udev->partitions = db_udev.partitions;
+
+	return 0;
 }
diff -Nru a/udevdb.h b/udevdb.h
--- a/udevdb.h	2004-10-25 04:48:06 +02:00
+++ b/udevdb.h	2004-10-25 04:48:06 +02:00
@@ -1,22 +1,34 @@
 /*
- * udevdb header file
+ * udevdb.h
+ *
+ * Userspace devfs
+ *
+ * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ *	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 _UDEVDB_H_
 #define _UDEVDB_H_
 
-/* Udevdb initialization flags */
-#define UDEVDB_DEFAULT	0	/* defaults database to use file */
-#define UDEVDB_INTERNAL	1	/* don't store db on disk, use in memory */
-
-/* function prototypes */
-extern void udevdb_exit(void);
-extern int udevdb_init(int init_flag);
-extern int udevdb_open_ro(void);
-extern int udevdb_call_foreach(int (*user_record_handler) (const char *path, struct udevice *dev));
 
 extern int udevdb_add_dev(struct udevice *dev);
-extern int udevdb_get_dev(const char *path, struct udevice *dev);
-extern int udevdb_delete_dev(const char *path);
-extern int udevdb_get_dev_byname(const char *name, char *path, struct udevice *dev);
+extern int udevdb_get_dev(struct udevice *dev);
+extern int udevdb_delete_dev(struct udevice *dev);
+
+extern int udevdb_get_dev_byname(struct udevice *udev, const char *name);
 
 #endif /* _UDEVDB_H_ */
diff -Nru a/udevinfo.8 b/udevinfo.8
--- a/udevinfo.8	2004-10-25 04:48:06 +02:00
+++ b/udevinfo.8	2004-10-25 04:48:06 +02:00
@@ -29,7 +29,7 @@
 .RB Needs " \-p " or " \-n " specified.
 .br
 Valid types are:
-.BR name ", " symlink ", " mode " ," owner " , " group " , " path " or " all.
+.BR name ", " symlink ", " path " or " all.
 .TP
 .BI \-p " sysfs_path"
 Specify the sysfs path of the device to query.
@@ -45,9 +45,6 @@
 attributes along the device chain. Useful for finding
 unique attributes to compose a rule.
 .RB Needs " \-p " specified.
-.TP
-.B \-d
-Dump the whole database.
 .TP
 .B \-h
 Print help text.
diff -Nru a/udevinfo.c b/udevinfo.c
--- a/udevinfo.c	2004-10-25 04:48:06 +02:00
+++ b/udevinfo.c	2004-10-25 04:48:06 +02:00
@@ -103,19 +103,11 @@
 	return retval;
 }
 
-/* callback for database dump */
-static int print_record(const char *path, struct udevice *dev)
+static int print_record(struct udevice *udev)
 {
-	printf("P: %s\n", path);
-	printf("N: %s\n", dev->name);
-	printf("T: %c\n", dev->type);
-	printf("M: %#o\n", dev->mode);
-	printf("S: %s\n", dev->symlink);
-	printf("O: %s\n", dev->owner);
-	printf("G: %s\n", dev->group);
-	printf("F: %s\n", dev->config_file);
-	printf("L: %i\n", dev->config_line);
-	printf("U: %li\n", dev->config_uptime);
+	printf("P: %s\n", udev->devpath);
+	printf("N: %s\n", udev->name);
+	printf("S: %s\n", udev->symlink);
 	printf("\n");
 	return 0;
 }
@@ -125,9 +117,6 @@
 	NAME,
 	PATH,
 	SYMLINK,
-	MODE,
-	OWNER,
-	GROUP,
 	ALL
 };
 
@@ -213,7 +202,7 @@
 	static const char short_options[] = "adn:p:q:rVh";
 	int option;
 	int retval = 1;
-	struct udevice dev;
+	struct udevice udev;
 	int root = 0;
 	int attributes = 0;
 	enum query_type query = NONE;
@@ -254,21 +243,6 @@
 				break;
 			}
 
-			if (strcmp(optarg, "mode") == 0) {
-				query = MODE;
-				break;
-			}
-
-			if (strcmp(optarg, "owner") == 0) {
-				query = OWNER;
-				break;
-			}
-
-			if (strcmp(optarg, "group") == 0) {
-				query = GROUP;
-				break;
-			}
-
 			if (strcmp(optarg, "path") == 0) {
 				query = PATH;
 				break;
@@ -290,16 +264,6 @@
 			attributes = 1;
 			break;
 
-		case 'd':
-			retval = udevdb_open_ro();
-			if (retval != 0) {
-				printf("unable to open udev database\n");
-				exit(2);
-			}
-			udevdb_call_foreach(print_record);
-			udevdb_exit();
-			exit(0);
-
 		case 'V':
 			printf("udevinfo, version %s\n", UDEV_VERSION);
 			exit(0);
@@ -314,12 +278,6 @@
 
 	/* process options */
 	if (query != NONE) {
-		retval = udevdb_open_ro();
-		if (retval != 0) {
-			printf("unable to open udev database\n");
-			return -EACCES;
-		}
-
 		if (path[0] != '\0') {
 			/* remove sysfs_path if given */
 			if (strncmp(path, sysfs_path, strlen(sysfs_path)) == 0) {
@@ -334,7 +292,9 @@
 					pos = path;
 				}
 			}
-			retval = udevdb_get_dev(pos, &dev);
+			memset(&udev, 0x00, sizeof(struct udevice));
+			strfieldcpy(udev.devpath, pos);
+			retval = udevdb_get_dev(&udev);
 			if (retval != 0) {
 				printf("device not found in database\n");
 				goto exit;
@@ -344,15 +304,21 @@
 
 		if (name[0] != '\0') {
 			/* remove udev_root if given */
-			if (strncmp(name, udev_root, strlen(udev_root)) == 0) {
-				pos = name + strlen(udev_root);
+			int len = strlen(udev_root);
+
+			if (strncmp(name, udev_root, len) == 0) {
+				pos = &name[len+1];
 			} else
 				pos = name;
-			retval = udevdb_get_dev_byname(pos, path, &dev);
+
+			memset(&udev, 0x00, sizeof(struct udevice));
+			strfieldcpy(udev.name, pos);
+			retval = udevdb_get_dev_byname(&udev, pos);
 			if (retval != 0) {
 				printf("device not found in database\n");
 				goto exit;
 			}
+
 			goto print;
 		}
 
@@ -362,25 +328,16 @@
 print:
 		switch(query) {
 		case NAME:
-			if (root)
-				strfieldcpy(result, udev_root);
-			strfieldcat(result, dev.name);
+			if (root) {
+				snprintf(result, NAME_SIZE-1, "%s/%s", udev_root, udev.name);
+				result[NAME_SIZE-1] = '\0';
+			} else {
+				strfieldcpy(result, udev.name);
+			}
 			break;
 
 		case SYMLINK:
-			strfieldcpy(result, dev.symlink);
-			break;
-
-		case MODE:
-			sprintf(result, "%#o", dev.mode);
-			break;
-
-		case GROUP:
-			strfieldcpy(result, dev.group);
-			break;
-
-		case OWNER:
-			strfieldcpy(result, dev.owner);
+			strfieldcpy(result, udev.symlink);
 			break;
 
 		case PATH:
@@ -388,7 +345,7 @@
 			break;
 
 		case ALL:
-			print_record(path, &dev);
+			print_record(&udev);
 			goto exit;
 
 		default:
@@ -397,7 +354,6 @@
 		printf("%s\n", result);
 
 exit:
-		udevdb_exit();
 		return retval;
 	}
 
@@ -427,9 +383,6 @@
 	       "  -q TYPE  query database for the specified value:\n"
 	       "             'name'    name of device node\n"
 	       "             'symlink' pointing to node\n"
-	       "             'mode'    permissions of node\n"
-	       "             'owner'   of node\n"
-	       "             'group'   of node\n"
 	       "             'path'    sysfs device path\n"
 	       "             'all'     all values\n"
 	       "\n"
@@ -438,7 +391,6 @@
 	       "\n"
 	       "  -r       print udev root\n"
 	       "  -a       print all SYSFS_attributes along the device chain\n"
-	       "  -d       dump whole database\n"
 	       "  -V       print udev version\n"
 	       "  -h       print this help text\n"
 	       "\n");

  parent reply	other threads:[~2004-10-25  2:51 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-10-23  5:41 udev hangs under high loads Greg KH
2004-10-23  6:31 ` Kay Sievers
2004-10-24  5:08 ` Kay Sievers
2004-10-24  5:53 ` Olaf Hering
2004-10-24 15:53 ` Kay Sievers
2004-10-24 15:57 ` Olaf Hering
2004-10-24 19:27 ` Kevin P. Fleming
2004-10-24 19:46 ` Kay Sievers
2004-10-24 19:51 ` Marco d'Itri
2004-10-24 19:56 ` Kay Sievers
2004-10-25  2:51 ` Kay Sievers [this message]
2004-10-25  7:01 ` Greg KH
2004-10-25 17:07 ` Kay Sievers
2004-10-25 17:12 ` Kevin P. Fleming
2004-10-25 17:27 ` Nishanth Aravamudan
2004-10-25 17:53 ` Kay Sievers
2004-10-25 20:55 ` Nishanth Aravamudan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20041025025114.GA29168@vrfy.org \
    --to=kay.sievers@vrfy.org \
    --cc=linux-hotplug@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).