X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udev-add.c;h=19196bec543953ff2551be758a20e65838c1cd7f;hb=534c853df52810b63b126e7e43d051a682829464;hp=87cf57c3b662a5a786a1d8c8542552da24d58f21;hpb=0bad3406c1e8eba6d5af2cbfd44d8a61231fa2bb;p=elogind.git diff --git a/udev-add.c b/udev-add.c index 87cf57c3b..19196bec5 100644 --- a/udev-add.c +++ b/udev-add.c @@ -32,17 +32,21 @@ #include #ifndef __KLIBC__ #include +#include #endif -#include +#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. @@ -78,7 +82,7 @@ static int create_path(char *file) int retval; struct stat stats; - strncpy(p, file, sizeof(p)); + strfieldcpy(p, file); pos = strchr(p+1, '/'); while (1) { pos = strchr(pos+1, '/'); @@ -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; @@ -145,8 +180,8 @@ static int create_node(struct udevice *dev, int fake) int i; int tail; - strncpy(filename, udev_root, sizeof(filename)); - strncat(filename, dev->name, sizeof(filename)); + strfieldcpy(filename, udev_root); + strfieldcat(filename, dev->name); switch (dev->type) { case 'b': @@ -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; @@ -225,8 +267,8 @@ static int create_node(struct udevice *dev, int fake) if (linkname == NULL || linkname[0] == '\0') break; - strncpy(filename, udev_root, sizeof(filename)); - strncat(filename, linkname, sizeof(filename)); + strfieldcpy(filename, udev_root); + strfieldcat(filename, linkname); dbg("symlink '%s' to node '%s' requested", filename, dev->name); if (!fake) if (strrchr(linkname, '/')) @@ -243,13 +285,11 @@ static int create_node(struct udevice *dev, int fake) } while (linkname[i] != '\0') { if (linkname[i] == '/') - strcat(linktarget, "../"); + strfieldcat(linktarget, "../"); i++; } - if (linktarget[0] == '\0') - strcpy(linktarget, "./"); - strcat(linktarget, &dev->name[tail]); + strfieldcat(linktarget, &dev->name[tail]); /* unlink existing files to ensure that our symlink is created */ if (!fake && (lstat(filename, &stats) == 0)) { @@ -278,8 +318,8 @@ static struct sysfs_class_device *get_class_dev(char *device_name) char dev_path[SYSFS_PATH_MAX]; struct sysfs_class_device *class_dev = NULL; - strcpy(dev_path, sysfs_path); - strcat(dev_path, device_name); + strfieldcpy(dev_path, sysfs_path); + strfieldcat(dev_path, device_name); dbg("looking at '%s'", dev_path); /* open up the sysfs class device for this thing... */ @@ -304,9 +344,9 @@ static int sleep_for_dev(char *path) int loop = SECONDS_TO_WAIT_FOR_DEV; int retval; - strcpy(filename, sysfs_path); - strcat(filename, path); - strcat(filename, "/dev"); + strfieldcpy(filename, sysfs_path); + strfieldcat(filename, path); + strfieldcat(filename, "/dev"); while (loop--) { struct stat buf;