+ /* run programs collected by RUN-key*/
+ if (retval == 0 && !udev->ignore_device && udev_run)
+ retval = udev_rules_run(udev);
+
+ udev_device_cleanup(udev);
+ return retval;
+}
+
+enum event_state {
+ EVENT_QUEUED,
+ EVENT_FINISHED,
+ EVENT_FAILED,
+};
+
+static void export_event_state(struct udevd_uevent_msg *msg, enum event_state state)
+{
+ char filename[PATH_SIZE];
+ char filename_failed[PATH_SIZE];
+ size_t start;
+
+ /* location of queue file */
+ snprintf(filename, sizeof(filename), "%s/"EVENT_QUEUE_DIR"/%llu", udev_root, msg->seqnum);
+
+ /* location of failed file */
+ strlcpy(filename_failed, udev_root, sizeof(filename_failed));
+ strlcat(filename_failed, "/", sizeof(filename_failed));
+ start = strlcat(filename_failed, EVENT_FAILED_DIR"/", sizeof(filename_failed));
+ strlcat(filename_failed, msg->devpath, sizeof(filename_failed));
+ path_encode(&filename_failed[start], sizeof(filename_failed) - start);
+
+ switch (state) {
+ case EVENT_QUEUED:
+ unlink(filename_failed);
+ delete_path(filename_failed);
+
+ create_path(filename);
+ symlink(msg->devpath, filename);
+ break;
+ case EVENT_FINISHED:
+ if (msg->devpath_old != NULL) {
+ /* "move" event - rename failed file to current name, do not delete failed */
+ char filename_failed_old[PATH_SIZE];
+
+ strlcpy(filename_failed_old, udev_root, sizeof(filename_failed_old));
+ strlcat(filename_failed_old, "/", sizeof(filename_failed_old));
+ start = strlcat(filename_failed_old, EVENT_FAILED_DIR"/", sizeof(filename_failed_old));
+ strlcat(filename_failed_old, msg->devpath_old, sizeof(filename_failed_old));
+ path_encode(&filename_failed_old[start], sizeof(filename) - start);
+
+ if (rename(filename_failed_old, filename_failed) == 0)
+ info("renamed devpath, moved failed state of '%s' to %s'",
+ msg->devpath_old, msg->devpath);
+ } else {
+ unlink(filename_failed);
+ delete_path(filename_failed);