make sure path exists before mknod is called
[project/procd.git] / hotplug.c
index 6583de4..c2276ed 100644 (file)
--- a/hotplug.c
+++ b/hotplug.c
@@ -66,6 +66,18 @@ static char *hotplug_msg_find_var(struct blob_attr *msg, const char *name)
        return NULL;
 }
 
+static void mkdir_p(char *dir)
+{
+       char *l = strrchr(dir, '/');
+
+       if (l) {
+               *l = '\0';
+               mkdir_p(dir);
+               *l = '/';
+               mkdir(dir, 0755);
+       }
+}
+
 static void handle_makedev(struct blob_attr *msg, struct blob_attr *data)
 {
        static struct blobmsg_policy mkdev_policy[2] = {
@@ -80,6 +92,12 @@ static void handle_makedev(struct blob_attr *msg, struct blob_attr *data)
        blobmsg_parse_array(mkdev_policy, 2, tb, blobmsg_data(data), blobmsg_data_len(data));
        if (tb[0] && tb[1] && minor && major && subsystem) {
                mode_t m = S_IFCHR;
+               char *d = strdup(blobmsg_get_string(tb[0]));
+
+               d = dirname(d);
+               mkdir_p(d);
+               free(d);
+
                if (!strcmp(subsystem, "block"))
                        m = S_IFBLK;
                mknod(blobmsg_get_string(tb[0]),
@@ -422,13 +440,11 @@ void hotplug(char *rules)
        nls.nl_groups = -1;
 
        if ((hotplug_fd.fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)) == -1) {
-               ERROR("Failed to open hotplug socket\n");
-               perror("socket");
+               ERROR("Failed to open hotplug socket: %s\n", strerror(errno));
                exit(1);
        }
        if (bind(hotplug_fd.fd, (void *)&nls, sizeof(struct sockaddr_nl))) {
-               ERROR("Failed to bind hotplug socket\n");
-               perror("socket");
+               ERROR("Failed to bind hotplug socket: %s\n", strerror(errno));
                exit(1);
        }
 
@@ -436,3 +452,9 @@ void hotplug(char *rules)
        queue_proc.cb = queue_proc_cb;
        uloop_fd_add(&hotplug_fd, ULOOP_READ);
 }
+
+void hotplug_shutdown(void)
+{
+       uloop_fd_delete(&hotplug_fd);
+       close(hotplug_fd.fd);
+}