chiark / gitweb /
[PATCH] multipath update
[elogind.git] / udev-add.c
index 0d3131300ff9d175373d79d897493b7c3d376381..19196bec543953ff2551be758a20e65838c1cd7f 100644 (file)
 #include <grp.h>
 #ifndef __KLIBC__
 #include <pwd.h>
+#include <utmp.h>
 #endif
 
 #include "libsysfs/sysfs/libsysfs.h"
 #include "udev.h"
 #include "udev_version.h"
 #include "udev_dbus.h"
+#include "udev_selinux.h"
 #include "logging.h"
 #include "namedev.h"
 #include "udevdb.h"
 #include "klibc_fixups.h"
 
+#define LOCAL_USER "$local"
+
 /* 
  * Right now the major/minor of a device is stored in a file called
  * "dev" in sysfs.
@@ -131,6 +135,37 @@ static int make_node(char *filename, int major, int minor, unsigned int mode, ui
        return 0;
 }
 
+/* get the local logged in user */
+static void set_to_local_user(char *user)
+{
+       struct utmp *u;
+       time_t recent = 0;
+
+       strnfieldcpy(user, default_owner_str, OWNER_SIZE);
+       setutent();
+       while (1) {
+               u = getutent();
+               if (u == NULL)
+                       break;
+
+               /* is this a user login ? */
+               if (u->ut_type != USER_PROCESS)
+                       continue;
+
+               /* is this a local login ? */
+               if (strcmp(u->ut_host, ""))
+                       continue;
+
+               if (u->ut_time > recent) {
+                       recent = u->ut_time;
+                       strfieldcpy(user, u->ut_user);
+                       dbg("local user is '%s'", user);
+                       break;
+               }
+       }
+       endutent();
+}
+
 static int create_node(struct udevice *dev, int fake)
 {
        struct stat stats;
@@ -174,6 +209,9 @@ static int create_node(struct udevice *dev, int fake)
                if (endptr[0] == '\0')
                        uid = (uid_t) id;
                else {
+                       if (strncmp(dev->owner, LOCAL_USER, sizeof(LOCAL_USER)) == 0)
+                               set_to_local_user(dev->owner);
+
                        struct passwd *pw = getpwnam(dev->owner);
                        if (pw == NULL)
                                dbg("specified user unknown '%s'", dev->owner);
@@ -210,13 +248,17 @@ static int create_node(struct udevice *dev, int fake)
                info("creating device partition nodes '%s[1-%i]'", filename, dev->partitions);
                if (!fake) {
                        for (i = 1; i <= dev->partitions; i++) {
-                               sprintf(partitionname, "%s%i", filename, i);
+                               strfieldcpy(partitionname, filename);
+                               strintcat(partitionname, i);
                                make_node(partitionname, dev->major,
                                          dev->minor + i, dev->mode, uid, gid);
                        }
                }
        }
 
+       if (!fake)
+               selinux_add_node(filename);
+
        /* create symlink if requested */
        if (dev->symlink[0] != '\0') {
                symlinks = dev->symlink;
@@ -247,8 +289,6 @@ static int create_node(struct udevice *dev, int fake)
                                i++;
                        }
 
-                       if (linktarget[0] == '\0')
-                               strfieldcpy(linktarget, "./");
                        strfieldcat(linktarget, &dev->name[tail]);
 
                        /* unlink existing files to ensure that our symlink is created */