+static struct sysfs_device *get_sysfs_device(struct sysfs_class_device *class_dev)
+{
+ struct sysfs_device *sysfs_device;
+ struct sysfs_class_device *class_dev_parent;
+ int loop;
+ char filename[SYSFS_PATH_MAX + 6];
+ int retval;
+ char *temp;
+ int partition = 0;
+
+ /* Figure out where the device symlink is at. For char devices this will
+ * always be in the class_dev->path. But for block devices, it's different.
+ * The main block device will have the device symlink in it's path, but
+ * all partitions have the symlink in its parent directory.
+ * But we need to watch out for block devices that do not have parents, yet
+ * look like a partition (fd0, loop0, etc.) They all do not have a device
+ * symlink yet. We do sit and spin on waiting for them right now, we should
+ * possibly have a whitelist for these devices here...
+ */
+ strcpy(filename, class_dev->path);
+ dbg("filename = %s", filename);
+ if (strcmp(class_dev->classname, SYSFS_BLOCK_NAME) == 0) {
+ if (isdigit(class_dev->path[strlen(class_dev->path)-1])) {
+ temp = strrchr(filename, '/');
+ if (temp) {
+ char *temp2 = strrchr(filename, '/');
+ partition = 1;
+ *temp = 0x00;
+ dbg("temp2 = %s", temp2);
+ if (temp2 && (strcmp(temp2, "/block") == 0)) {
+ /* oops, we have no parent block device, so go back to original directory */
+ strcpy(filename, class_dev->path);
+ partition = 0;
+ }
+ }
+ }
+ }
+ strcat(filename, "/device");
+
+ loop = 2;
+ while (loop--) {
+ struct stat buf;
+ dbg("looking for '%s'", filename);
+ retval = stat(filename, &buf);
+ if (!retval)
+ break;
+ /* sleep to give the kernel a chance to create the device file */
+ sleep(1);
+ }
+
+ loop = 1; /* FIXME put a real value in here for when everything is fixed... */
+ while (loop--) {
+ /* find the sysfs_device for this class device */
+ /* Wouldn't it really be nice if libsysfs could do this for us? */
+ sysfs_device = sysfs_get_classdev_device(class_dev);
+ if (sysfs_device != NULL)
+ goto exit;
+
+ /* if it's a partition, we need to get the parent device */
+ if (partition) {
+ /* FIXME HACK HACK HACK HACK
+ * for some reason partitions need this extra sleep here, in order
+ * to wait for the device properly. Once the libsysfs code is
+ * fixed properly, this sleep should go away, and we can just loop above.
+ */
+ sleep(1);
+ dbg("really is a partition");
+ class_dev_parent = sysfs_get_classdev_parent(class_dev);
+ if (class_dev_parent == NULL) {
+ dbg("sysfs_get_classdev_parent for class device '%s' failed", class_dev->name);
+ } else {
+ dbg("class_dev_parent->name='%s'", class_dev_parent->name);
+ sysfs_device = sysfs_get_classdev_device(class_dev_parent);
+ if (sysfs_device != NULL)
+ goto exit;
+ }
+ }
+ /* sleep to give the kernel a chance to create the link */
+ /* FIXME remove comment...
+ sleep(1); */
+ }
+ dbg("Timed out waiting for device symlink, continuing on anyway...");
+exit:
+ return sysfs_device;
+}
+