X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_rules.c;h=eccea3b57c75c1a4aae4db773c2bdd1e4ff78e4f;hp=e464404b5947e14a9eb4a97a6edbb0266c0cc2ab;hb=573bdd7e7588b70105c2976859696037899e9d4d;hpb=5ee7ecfb0f07e8c98c1c2b3d988191ad458cf097 diff --git a/udev_rules.c b/udev_rules.c index e464404b5..eccea3b57 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -455,24 +455,35 @@ static int import_parent_into_env(struct udevice *udev, const char *filter) return rc; } -static int pass_env_to_socket(const char *sockname, const char *devpath, const char *action) +static int pass_env_to_socket(const char *sockpath, const char *devpath, const char *action) { int sock; struct sockaddr_un saddr; - socklen_t addrlen; + socklen_t saddrlen; + struct stat stats; char buf[2048]; size_t bufpos = 0; int i; ssize_t count; int retval = 0; - dbg("pass environment to socket '%s'", sockname); + dbg("pass environment to socket '%s'", sockpath); sock = socket(AF_LOCAL, SOCK_DGRAM, 0); memset(&saddr, 0x00, sizeof(struct sockaddr_un)); saddr.sun_family = AF_LOCAL; - /* abstract namespace only */ - strcpy(&saddr.sun_path[1], sockname); - addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1; + if (sockpath[0] == '@') { + /* abstract namespace socket requested */ + strlcpy(&saddr.sun_path[1], &sockpath[1], sizeof(saddr.sun_path)-1); + saddrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]); + } else if (stat(sockpath, &stats) == 0 && S_ISSOCK(stats.st_mode)) { + /* existing socket file */ + strlcpy(saddr.sun_path, sockpath, sizeof(saddr.sun_path)); + saddrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path); + } else { + /* no socket file, assume abstract namespace socket */ + strlcpy(&saddr.sun_path[1], sockpath, sizeof(saddr.sun_path)-1); + saddrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]); + } bufpos = snprintf(buf, sizeof(buf)-1, "%s@%s", action, devpath); bufpos++; @@ -483,10 +494,10 @@ static int pass_env_to_socket(const char *sockname, const char *devpath, const c if (bufpos > sizeof(buf)) bufpos = sizeof(buf); - count = sendto(sock, &buf, bufpos, 0, (struct sockaddr *)&saddr, addrlen); + count = sendto(sock, &buf, bufpos, 0, (struct sockaddr *)&saddr, saddrlen); if (count < 0) retval = -1; - info("passed %zi bytes to socket '%s', ", count, sockname); + info("passed %zi bytes to socket '%s', ", count, sockpath); close(sock); return retval; @@ -586,6 +597,44 @@ out: return found; } +static int attr_subst_subdir(char *attr, size_t len) +{ + char *pos; + int found = 0; + + pos = strstr(attr, "/*/"); + if (pos != NULL) { + char str[PATH_SIZE]; + DIR *dir; + + pos[1] = '\0'; + strlcpy(str, &pos[2], sizeof(str)); + dir = opendir(attr); + if (dir != NULL) { + struct dirent *dent; + + for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { + struct stat stats; + + if (dent->d_name[0] == '.') + continue; + strlcat(attr, dent->d_name, len); + strlcat(attr, str, len); + if (stat(attr, &stats) == 0) { + found = 1; + break; + } + pos[1] = '\0'; + } + closedir(dir); + } + if (!found) + strlcat(attr, str, len); + } + + return found; +} + void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize) { char temp[PATH_SIZE]; @@ -1023,6 +1072,8 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) strlcpy(filename, tmp, sizeof(filename)); } + attr_subst_subdir(filename, sizeof(filename)); + match = (stat(filename, &statbuf) == 0); info("'%s' %s", filename, match ? "exists" : "does not exist"); if (match && rule->test_mode_mask > 0) { @@ -1244,7 +1295,6 @@ try_parent: if (pair->key.operation == KEY_OP_ASSIGN) { const char *key_name = key_pair_name(rule, pair); char devpath[PATH_SIZE]; - char *pos; char *attrib; char attr[PATH_SIZE] = ""; char value[NAME_SIZE]; @@ -1266,27 +1316,7 @@ try_parent: strlcat(attr, key_name, sizeof(attr)); } - pos = strstr(attr, "/*/"); - if (pos != NULL) { - char str[PATH_SIZE]; - DIR *dir; - - pos[1] = '\0'; - strlcpy(str, &pos[2], sizeof(str)); - dir = opendir(attr); - if (dir != NULL) { - struct dirent *dent; - - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - if (dent->d_name[0] == '.') - continue; - strlcat(attr, dent->d_name, sizeof(attr)); - break; - } - closedir(dir); - } - strlcat(attr, str, sizeof(attr)); - } + attr_subst_subdir(attr, sizeof(attr)); strlcpy(value, key_val(rule, &pair->key), sizeof(value)); udev_rules_apply_format(udev, value, sizeof(value));