+ struct util_name_entry *name_loop;
+ char path[UTIL_PATH_SIZE];
+ char value[UTIL_NAME_SIZE];
+ struct stat statbuf;
+ int fd;
+ ssize_t size;
+ const char *val = NULL;
+
+ /* look for possibly already cached result */
+ list_for_each_entry(name_loop, &udev_device->attr_list, node) {
+ if (strcmp(name_loop->name, attr) == 0) {
+ info(udev_device->udev, "'%s' in cache '%s'\n", attr, name_loop->value);
+ return name_loop->value;
+ }
+ }
+
+ util_strlcpy(path, udev_device_get_syspath(udev_device), sizeof(path));
+ util_strlcat(path, "/", sizeof(path));
+ util_strlcat(path, attr, sizeof(path));
+
+ if (lstat(path, &statbuf) != 0) {
+ info(udev_device->udev, "stat '%s' failed: %s\n", path, strerror(errno));
+ goto out;
+ }
+
+ if (S_ISLNK(statbuf.st_mode)) {
+ /* links return the last element of the target path */
+ char target[UTIL_NAME_SIZE];
+ int len;
+ char *pos;
+
+ len = readlink(path, target, sizeof(target));
+ if (len > 0) {
+ target[len] = '\0';
+ pos = strrchr(target, '/');
+ if (pos != NULL) {
+ pos = &pos[1];
+ info(udev_device->udev, "cache '%s' with link value '%s'\n", attr, pos);
+ val = util_name_list_add(udev_device->udev, &udev_device->attr_list, attr, pos, 0)->value;
+ }
+ }
+ goto out;
+ }
+
+ /* skip directories */
+ if (S_ISDIR(statbuf.st_mode))
+ goto out;
+
+ /* skip non-readable files */
+ if ((statbuf.st_mode & S_IRUSR) == 0)
+ goto out;
+
+ /* read attribute value */
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ info(udev_device->udev, "attribute '%s' can not be opened\n", path);
+ goto out;
+ }
+ size = read(fd, value, sizeof(value));
+ close(fd);
+ if (size < 0)
+ goto out;
+ if (size == sizeof(value))
+ goto out;
+
+ /* got a valid value, store it in cache and return it */
+ value[size] = '\0';
+ util_remove_trailing_chars(value, '\n');
+ info(udev_device->udev, "'%s' has attribute value '%s'\n", path, value);
+ val = util_name_list_add(udev_device->udev, &udev_device->attr_list, attr, value, 0)->value;
+out:
+ return val;
+}
+int device_set_syspath(struct udev_device *udev_device, const char *syspath)
+{
+ const char *pos;
+
+ udev_device->syspath = strdup(syspath);
+ if (udev_device->syspath == NULL)