X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=namedev.c;h=fdda039f5993f41a42cdd8502ea24334fa447410;hb=616a7078071362b32a4db73fe3314feb46438258;hp=fdc6252bf66fa46583ca97b4b9fab0389b12bb12;hpb=a2505f4d1da4793991a4d2b2dc8f93b9b89d9672;p=elogind.git diff --git a/namedev.c b/namedev.c index fdc6252bf..fdda039f5 100644 --- a/namedev.c +++ b/namedev.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -151,20 +152,21 @@ static mode_t get_default_mode(struct sysfs_class_device *class_dev) static void apply_format(struct udevice *udev, unsigned char *string) { - char name[NAME_SIZE]; char temp[NAME_SIZE]; + char temp1[NAME_SIZE]; char *tail; char *pos; char *pos2; char *pos3; int num; + pos = string; while (1) { num = 0; - pos = strchr(string, '%'); + pos = strchr(pos, '%'); if (pos) { - *pos = '\0'; + pos[0] = '\0'; tail = pos+1; if (isdigit(tail[0])) { num = (int) strtoul(&pos[1], &tail, 10); @@ -173,7 +175,7 @@ static void apply_format(struct udevice *udev, unsigned char *string) break; } } - strfieldcpy(name, tail+1); + strfieldcpy(temp, tail+1); switch (tail[0]) { case 'b': @@ -217,8 +219,8 @@ static void apply_format(struct udevice *udev, unsigned char *string) break; if (num) { /* get part of return string */ - strncpy(temp, udev->program_result, sizeof(temp)); - pos2 = temp; + strncpy(temp1, udev->program_result, sizeof(temp1)); + pos2 = temp1; while (num) { num--; pos3 = strsep(&pos2, " "); @@ -236,11 +238,15 @@ static void apply_format(struct udevice *udev, unsigned char *string) dbg("substitute result string '%s'", udev->program_result); } break; + case '%': + strcat(pos, "%"); + pos++; + break; default: dbg("unknown substitution type '%%%c'", pos[1]); break; } - strcat(string, name); + strcat(string, temp); } else break; } @@ -309,7 +315,7 @@ static int execute_program(char *path, char *value, int len) int value_set = 0; char buffer[256]; char *pos; - char *args[CALLOUT_MAXARG]; + char *args[PROGRAM_MAXARG]; int i; dbg("executing '%s'", path); @@ -331,7 +337,7 @@ static int execute_program(char *path, char *value, int len) if (strchr(path, ' ')) { /* exec with arguments */ pos = path; - for (i=0; i < CALLOUT_MAXARG-1; i++) { + for (i=0; i < PROGRAM_MAXARG-1; i++) { args[i] = strsep(&pos, " "); if (args[i] == NULL) break; @@ -509,11 +515,8 @@ static struct sysfs_device *get_sysfs_device(struct sysfs_class_device *class_de { struct sysfs_device *sysfs_device; struct sysfs_class_device *class_dev_parent; + struct timespec tspec; 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. @@ -524,69 +527,54 @@ static struct sysfs_device *get_sysfs_device(struct sysfs_class_device *class_de * 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"); + class_dev_parent = sysfs_get_classdev_parent(class_dev); + if (class_dev_parent) + dbg("Really a partition"); - loop = 2; + tspec.tv_sec = 0; + tspec.tv_nsec = 10000000; /* sleep 10 millisec */ + loop = 10; 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); - } + nanosleep(&tspec, NULL); + if (class_dev_parent) + sysfs_device = sysfs_get_classdev_device(class_dev_parent); + else + sysfs_device = sysfs_get_classdev_device(class_dev); - 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); */ + goto device_found; } dbg("Timed out waiting for device symlink, continuing on anyway..."); + +device_found: + /* We have another issue with just the wait above - the sysfs part of + * the kernel may not be quick enough to have created the link to the + * device under the "bus" subsystem. Due to this, the sysfs_device->bus + * will not contain the actual bus name :( + * + * Libsysfs now provides a new API sysfs_get_device_bus(), so use it + * if needed + */ + if (sysfs_device) { + + if (sysfs_device->bus[0] != '\0') + goto bus_found; + + loop = 10; + tspec.tv_nsec = 10000000; + while (loop--) { + nanosleep(&tspec, NULL); + sysfs_get_device_bus(sysfs_device); + + if (sysfs_device->bus[0] != '\0') + goto bus_found; + } + dbg("Timed out waiting to find the device bus, continuing on anyway\n"); + goto exit; +bus_found: + dbg("Device %s is registered with bus %s\n", + sysfs_device->name, sysfs_device->bus); + } exit: return sysfs_device; }