+
+ if (device->directory == NULL) {
+ device->directory = sysfs_open_directory(device->path);
+ if (device->directory == NULL)
+ return NULL;
+ }
+ if (device->directory->attributes == NULL) {
+ if ((sysfs_read_dir_attributes(device->directory)) != 0)
+ return NULL;
+ }
+ return (device->directory->attributes);
+}
+
+/**
+ * sysfs_refresh_device_attributes: refreshes the device's list of attributes
+ * @device: sysfs_device whose attributes to refresh
+ *
+ * NOTE: Upon return, prior references to sysfs_attributes for this device
+ * _may_ not be valid
+ *
+ * Returns list of attributes on success and NULL on failure
+ */
+struct dlist *sysfs_refresh_device_attributes(struct sysfs_device *device)
+{
+ if (device == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (device->directory == NULL)
+ return (sysfs_get_device_attributes(device));
+
+ if ((sysfs_refresh_dir_attributes(device->directory)) != 0) {
+ dprintf("Error refreshing device attributes\n");
+ return NULL;
+ }
+
+ return (device->directory->attributes);
+}
+
+/**
+ * sysfs_get_device_attr: searches dev's attributes by name
+ * @dev: device to look through
+ * @name: attribute name to get
+ * returns sysfs_attribute reference with success or NULL with error.
+ */
+struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
+ const char *name)
+{
+ struct dlist *attrlist = NULL;
+
+ if (dev == NULL || name == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ attrlist = sysfs_get_device_attributes(dev);
+ if (attrlist == NULL)
+ return NULL;
+
+ return sysfs_get_directory_attribute(dev->directory, (char *)name);
+}
+
+/**
+ * get_device_absolute_path: looks up the bus the device is on, gets
+ * absolute path to the device
+ * @device: device for which path is needed
+ * @path: buffer to store absolute path
+ * @psize: size of "path"
+ * Returns 0 on success -1 on failure
+ */
+static int get_device_absolute_path(const char *device, const char *bus,
+ char *path, size_t psize)
+{
+ char bus_path[SYSFS_PATH_MAX];
+
+ if (device == NULL || path == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(bus_path, 0, SYSFS_PATH_MAX);
+ if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX) != 0) {
+ dprintf ("Sysfs not supported on this system\n");
+ return -1;
+ }
+ safestrcat(bus_path, "/");
+ safestrcat(bus_path, SYSFS_BUS_NAME);
+ safestrcat(bus_path, "/");
+ safestrcat(bus_path, bus);
+ safestrcat(bus_path, "/");
+ safestrcat(bus_path, SYSFS_DEVICES_NAME);
+ safestrcat(bus_path, "/");
+ safestrcat(bus_path, device);
+ /*
+ * We now are at /sys/bus/"bus_name"/devices/"device" which is a link.
+ * Now read this link to reach to the device.
+ */
+ if ((sysfs_get_link(bus_path, path, psize)) != 0) {
+ dprintf("Error getting to device %s\n", device);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * sysfs_open_device: open a device by id (use the "bus" subsystem)
+ * @bus: bus the device belongs to
+ * @bus_id: bus_id of the device to open - has to be the "bus_id" in
+ * /sys/bus/xxx/devices
+ * returns struct sysfs_device if found, NULL otherwise
+ * NOTE:
+ * 1. Use sysfs_close_device to close the device
+ * 2. Bus the device is on must be supplied
+ * Use sysfs_find_device_bus to get the bus name
+ */
+struct sysfs_device *sysfs_open_device(const char *bus, const char *bus_id)
+{
+ char sysfs_path[SYSFS_PATH_MAX];
+ struct sysfs_device *device = NULL;
+
+ if (bus_id == NULL || bus == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ memset(sysfs_path, 0, SYSFS_PATH_MAX);
+ if ((get_device_absolute_path(bus_id, bus, sysfs_path,
+ SYSFS_PATH_MAX)) != 0) {
+ dprintf("Error getting to device %s\n", bus_id);
+ return NULL;
+ }
+
+ device = sysfs_open_device_path(sysfs_path);
+ if (device == NULL) {
+ dprintf("Error opening device %s\n", bus_id);
+ return NULL;
+ }
+
+ return device;
+}
+
+/**
+ * sysfs_get_device_parent: opens up given device's parent and returns a
+ * reference to its sysfs_device
+ * @dev: sysfs_device whose parent is requested
+ * Returns sysfs_device of the parent on success and NULL on failure
+ */
+struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev)
+{
+ char ppath[SYSFS_PATH_MAX], *tmp = NULL;
+
+ if (dev == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (dev->parent != NULL)
+ return (dev->parent);
+
+ memset(ppath, 0, SYSFS_PATH_MAX);
+ safestrcpy(ppath, dev->path);
+ tmp = strrchr(ppath, '/');
+ if (tmp == NULL) {
+ dprintf("Invalid path to device %s\n", ppath);
+ return NULL;
+ }
+ if (*(tmp + 1) == '\0') {
+ *tmp = '\0';
+ tmp = strrchr(tmp, '/');
+ if (tmp == NULL) {
+ dprintf("Invalid path to device %s\n", ppath);