[PATCH] libsysfs update for refresh + namedev.c changes
Please find inlined a patch which contains updates to libsysfs (pre-release) for refresh and also changes to namedev.c to take advantage of it.
This commit is contained in:
parent
1782087e4f
commit
616a707807
|
@ -62,18 +62,20 @@ struct sysfs_link {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfs_directory {
|
struct sysfs_directory {
|
||||||
|
unsigned char name[SYSFS_NAME_LEN];
|
||||||
|
unsigned char path[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
|
/* Private: for internal use only */
|
||||||
struct dlist *subdirs;
|
struct dlist *subdirs;
|
||||||
struct dlist *links;
|
struct dlist *links;
|
||||||
struct dlist *attributes;
|
struct dlist *attributes;
|
||||||
unsigned char name[SYSFS_NAME_LEN];
|
|
||||||
unsigned char path[SYSFS_PATH_MAX];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sysfs_driver {
|
struct sysfs_driver {
|
||||||
unsigned char name[SYSFS_NAME_LEN];
|
unsigned char name[SYSFS_NAME_LEN];
|
||||||
unsigned char path[SYSFS_PATH_MAX];
|
unsigned char path[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
/* for internal use only */
|
/* Private: for internal use only */
|
||||||
struct dlist *devices;
|
struct dlist *devices;
|
||||||
struct sysfs_directory *directory;
|
struct sysfs_directory *directory;
|
||||||
};
|
};
|
||||||
|
@ -85,7 +87,7 @@ struct sysfs_device {
|
||||||
unsigned char driver_name[SYSFS_NAME_LEN];
|
unsigned char driver_name[SYSFS_NAME_LEN];
|
||||||
unsigned char path[SYSFS_PATH_MAX];
|
unsigned char path[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
/* for internal use only */
|
/* Private: for internal use only */
|
||||||
struct sysfs_device *parent;
|
struct sysfs_device *parent;
|
||||||
struct dlist *children;
|
struct dlist *children;
|
||||||
struct sysfs_directory *directory;
|
struct sysfs_directory *directory;
|
||||||
|
@ -95,7 +97,7 @@ struct sysfs_root_device {
|
||||||
unsigned char name[SYSFS_NAME_LEN];
|
unsigned char name[SYSFS_NAME_LEN];
|
||||||
unsigned char path[SYSFS_PATH_MAX];
|
unsigned char path[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
/* for internal use only */
|
/* Private: for internal use only */
|
||||||
struct dlist *devices;
|
struct dlist *devices;
|
||||||
struct sysfs_directory *directory;
|
struct sysfs_directory *directory;
|
||||||
};
|
};
|
||||||
|
@ -104,7 +106,7 @@ struct sysfs_bus {
|
||||||
unsigned char name[SYSFS_NAME_LEN];
|
unsigned char name[SYSFS_NAME_LEN];
|
||||||
unsigned char path[SYSFS_PATH_MAX];
|
unsigned char path[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
/* internal use only */
|
/* Private: for internal use only */
|
||||||
struct dlist *drivers;
|
struct dlist *drivers;
|
||||||
struct dlist *devices;
|
struct dlist *devices;
|
||||||
struct sysfs_directory *directory;
|
struct sysfs_directory *directory;
|
||||||
|
@ -115,7 +117,7 @@ struct sysfs_class_device {
|
||||||
unsigned char classname[SYSFS_NAME_LEN];
|
unsigned char classname[SYSFS_NAME_LEN];
|
||||||
unsigned char path[SYSFS_PATH_MAX];
|
unsigned char path[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
/* for internal use only */
|
/* Private: for internal use only */
|
||||||
struct sysfs_class_device *parent;
|
struct sysfs_class_device *parent;
|
||||||
struct sysfs_device *sysdevice; /* NULL if virtual */
|
struct sysfs_device *sysdevice; /* NULL if virtual */
|
||||||
struct sysfs_driver *driver; /* NULL if not implemented */
|
struct sysfs_driver *driver; /* NULL if not implemented */
|
||||||
|
@ -126,7 +128,7 @@ struct sysfs_class {
|
||||||
unsigned char name[SYSFS_NAME_LEN];
|
unsigned char name[SYSFS_NAME_LEN];
|
||||||
unsigned char path[SYSFS_PATH_MAX];
|
unsigned char path[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
/* for internal use only */
|
/* Private: for internal use only */
|
||||||
struct dlist *devices;
|
struct dlist *devices;
|
||||||
struct sysfs_directory *directory;
|
struct sysfs_directory *directory;
|
||||||
};
|
};
|
||||||
|
@ -138,8 +140,8 @@ extern "C" {
|
||||||
/*
|
/*
|
||||||
* Function Prototypes
|
* Function Prototypes
|
||||||
*/
|
*/
|
||||||
extern int sysfs_trailing_slash(unsigned char *path);
|
|
||||||
extern int sysfs_get_mnt_path(unsigned char *mnt_path, size_t len);
|
extern int sysfs_get_mnt_path(unsigned char *mnt_path, size_t len);
|
||||||
|
extern int sysfs_remove_trailing_slash(unsigned char *path);
|
||||||
extern int sysfs_get_name_from_path(const unsigned char *path,
|
extern int sysfs_get_name_from_path(const unsigned char *path,
|
||||||
unsigned char *name, size_t len);
|
unsigned char *name, size_t len);
|
||||||
extern int sysfs_path_is_dir(const unsigned char *path);
|
extern int sysfs_path_is_dir(const unsigned char *path);
|
||||||
|
@ -161,7 +163,9 @@ extern int sysfs_write_attribute(struct sysfs_attribute *sysattr,
|
||||||
const unsigned char *new_value, size_t len);
|
const unsigned char *new_value, size_t len);
|
||||||
extern unsigned char *sysfs_get_value_from_attributes(struct dlist *attr,
|
extern unsigned char *sysfs_get_value_from_attributes(struct dlist *attr,
|
||||||
const unsigned char * name);
|
const unsigned char * name);
|
||||||
extern int sysfs_refresh_attributes(struct dlist *attrlist);
|
extern int sysfs_refresh_dir_attributes(struct sysfs_directory *sysdir);
|
||||||
|
extern int sysfs_refresh_dir_links(struct sysfs_directory *sysdir);
|
||||||
|
extern int sysfs_refresh_dir_subdirs(struct sysfs_directory *sysdir);
|
||||||
extern void sysfs_close_directory(struct sysfs_directory *sysdir);
|
extern void sysfs_close_directory(struct sysfs_directory *sysdir);
|
||||||
extern struct sysfs_directory *sysfs_open_directory(const unsigned char *path);
|
extern struct sysfs_directory *sysfs_open_directory(const unsigned char *path);
|
||||||
extern int sysfs_read_dir_attributes(struct sysfs_directory *sysdir);
|
extern int sysfs_read_dir_attributes(struct sysfs_directory *sysdir);
|
||||||
|
@ -179,6 +183,9 @@ extern struct sysfs_link *sysfs_get_subdirectory_link
|
||||||
(struct sysfs_directory *dir, unsigned char *linkname);
|
(struct sysfs_directory *dir, unsigned char *linkname);
|
||||||
extern struct sysfs_attribute *sysfs_get_directory_attribute
|
extern struct sysfs_attribute *sysfs_get_directory_attribute
|
||||||
(struct sysfs_directory *dir, unsigned char *attrname);
|
(struct sysfs_directory *dir, unsigned char *attrname);
|
||||||
|
extern struct dlist *sysfs_get_dir_attributes(struct sysfs_directory *dir);
|
||||||
|
extern struct dlist *sysfs_get_dir_links(struct sysfs_directory *dir);
|
||||||
|
extern struct dlist *sysfs_get_dir_subdirs(struct sysfs_directory *dir);
|
||||||
|
|
||||||
/* sysfs driver access */
|
/* sysfs driver access */
|
||||||
extern void sysfs_close_driver(struct sysfs_driver *driver);
|
extern void sysfs_close_driver(struct sysfs_driver *driver);
|
||||||
|
@ -189,9 +196,12 @@ extern struct sysfs_attribute *sysfs_get_driver_attr
|
||||||
(struct sysfs_driver *drv, const unsigned char *name);
|
(struct sysfs_driver *drv, const unsigned char *name);
|
||||||
extern struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver);
|
extern struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver);
|
||||||
extern struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver);
|
extern struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver);
|
||||||
|
extern struct dlist *sysfs_refresh_driver_devices(struct sysfs_driver *driver);
|
||||||
extern struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver);
|
extern struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver);
|
||||||
extern struct sysfs_device *sysfs_get_driver_device
|
extern struct sysfs_device *sysfs_get_driver_device
|
||||||
(struct sysfs_driver *driver, const unsigned char *name);
|
(struct sysfs_driver *driver, const unsigned char *name);
|
||||||
|
extern struct dlist *sysfs_refresh_driver_attributes
|
||||||
|
(struct sysfs_driver *driver);
|
||||||
extern struct sysfs_attribute *sysfs_open_driver_attr(const unsigned char *bus,
|
extern struct sysfs_attribute *sysfs_open_driver_attr(const unsigned char *bus,
|
||||||
const unsigned char *drv, const unsigned char *attrib);
|
const unsigned char *drv, const unsigned char *attrib);
|
||||||
|
|
||||||
|
@ -205,9 +215,12 @@ extern struct sysfs_device *sysfs_open_device
|
||||||
(const unsigned char *bus_id, const unsigned char *bus);
|
(const unsigned char *bus_id, const unsigned char *bus);
|
||||||
extern struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev);
|
extern struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev);
|
||||||
extern struct sysfs_device *sysfs_open_device_path(const unsigned char *path);
|
extern struct sysfs_device *sysfs_open_device_path(const unsigned char *path);
|
||||||
|
extern int sysfs_get_device_bus(struct sysfs_device *dev);
|
||||||
extern struct sysfs_attribute *sysfs_get_device_attr
|
extern struct sysfs_attribute *sysfs_get_device_attr
|
||||||
(struct sysfs_device *dev, const unsigned char *name);
|
(struct sysfs_device *dev, const unsigned char *name);
|
||||||
extern struct dlist *sysfs_get_device_attributes(struct sysfs_device *device);
|
extern struct dlist *sysfs_get_device_attributes(struct sysfs_device *device);
|
||||||
|
extern struct dlist *sysfs_refresh_device_attributes
|
||||||
|
(struct sysfs_device *device);
|
||||||
extern struct sysfs_attribute *sysfs_open_device_attr(const unsigned char *bus,
|
extern struct sysfs_attribute *sysfs_open_device_attr(const unsigned char *bus,
|
||||||
const unsigned char *bus_id, const unsigned char *attrib);
|
const unsigned char *bus_id, const unsigned char *attrib);
|
||||||
|
|
||||||
|
@ -221,6 +234,7 @@ extern struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus,
|
||||||
extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus);
|
extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus);
|
||||||
extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus);
|
extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus);
|
||||||
extern struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus);
|
extern struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus);
|
||||||
|
extern struct dlist *sysfs_refresh_bus_attributes(struct sysfs_bus *bus);
|
||||||
extern struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus,
|
extern struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus,
|
||||||
unsigned char *attrname);
|
unsigned char *attrname);
|
||||||
extern struct sysfs_device *sysfs_open_bus_device(unsigned char *busname,
|
extern struct sysfs_device *sysfs_open_bus_device(unsigned char *busname,
|
||||||
|
@ -247,6 +261,8 @@ extern struct sysfs_class_device *sysfs_get_class_device
|
||||||
(struct sysfs_class *class, unsigned char *name);
|
(struct sysfs_class *class, unsigned char *name);
|
||||||
extern struct dlist *sysfs_get_classdev_attributes
|
extern struct dlist *sysfs_get_classdev_attributes
|
||||||
(struct sysfs_class_device *cdev);
|
(struct sysfs_class_device *cdev);
|
||||||
|
extern struct dlist *sysfs_refresh_classdev_attributes
|
||||||
|
(struct sysfs_class_device *cdev);
|
||||||
extern struct sysfs_attribute *sysfs_get_classdev_attr
|
extern struct sysfs_attribute *sysfs_get_classdev_attr
|
||||||
(struct sysfs_class_device *clsdev, const unsigned char *name);
|
(struct sysfs_class_device *clsdev, const unsigned char *name);
|
||||||
extern struct sysfs_attribute *sysfs_open_classdev_attr
|
extern struct sysfs_attribute *sysfs_open_classdev_attr
|
||||||
|
|
|
@ -209,9 +209,7 @@ struct sysfs_bus *sysfs_open_bus(const unsigned char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sysfs_trailing_slash(buspath) == 0)
|
strcat(buspath, "/");
|
||||||
strcat(buspath, "/");
|
|
||||||
|
|
||||||
strcat(buspath, SYSFS_BUS_NAME);
|
strcat(buspath, SYSFS_BUS_NAME);
|
||||||
strcat(buspath, "/");
|
strcat(buspath, "/");
|
||||||
strcat(buspath, name);
|
strcat(buspath, name);
|
||||||
|
@ -226,6 +224,11 @@ struct sysfs_bus *sysfs_open_bus(const unsigned char *name)
|
||||||
}
|
}
|
||||||
strcpy(bus->name, name);
|
strcpy(bus->name, name);
|
||||||
strcpy(bus->path, buspath);
|
strcpy(bus->path, buspath);
|
||||||
|
if ((sysfs_remove_trailing_slash(bus->path)) != 0) {
|
||||||
|
dprintf("Incorrect path to bus %s\n", bus->path);
|
||||||
|
sysfs_close_bus(bus);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return bus;
|
return bus;
|
||||||
}
|
}
|
||||||
|
@ -296,20 +299,37 @@ struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus)
|
||||||
if (bus->directory->attributes == NULL) {
|
if (bus->directory->attributes == NULL) {
|
||||||
if ((sysfs_read_dir_attributes(bus->directory)) != 0)
|
if ((sysfs_read_dir_attributes(bus->directory)) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
|
||||||
if ((sysfs_path_is_dir(bus->path)) != 0) {
|
|
||||||
dprintf("Bus at %s no longer exists\n", bus->path);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if ((sysfs_refresh_attributes
|
|
||||||
(bus->directory->attributes)) != 0) {
|
|
||||||
dprintf("Error refreshing bus attributes\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return bus->directory->attributes;
|
return bus->directory->attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_refresh_bus_attributes: refreshes the bus's list of attributes
|
||||||
|
* @bus: sysfs_bus whose attributes to refresh
|
||||||
|
*
|
||||||
|
* NOTE: Upon return, prior references to sysfs_attributes for this bus
|
||||||
|
* _may_ not be valid
|
||||||
|
*
|
||||||
|
* Returns list of attributes on success and NULL on failure
|
||||||
|
*/
|
||||||
|
struct dlist *sysfs_refresh_bus_attributes(struct sysfs_bus *bus)
|
||||||
|
{
|
||||||
|
if (bus == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bus->directory == NULL)
|
||||||
|
return (sysfs_get_bus_attributes(bus));
|
||||||
|
|
||||||
|
if ((sysfs_refresh_dir_attributes(bus->directory)) != 0) {
|
||||||
|
dprintf("Error refreshing bus attributes\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bus->directory->attributes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_get_bus_attribute: gets a specific bus attribute, if buses had
|
* sysfs_get_bus_attribute: gets a specific bus attribute, if buses had
|
||||||
* attributes.
|
* attributes.
|
||||||
|
@ -357,8 +377,7 @@ struct sysfs_device *sysfs_open_bus_device(unsigned char *busname,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sysfs_trailing_slash(path) == 0)
|
strcat(path, "/");
|
||||||
strcat(path, "/");
|
|
||||||
strcat(path, SYSFS_BUS_NAME);
|
strcat(path, SYSFS_BUS_NAME);
|
||||||
strcat(path, "/");
|
strcat(path, "/");
|
||||||
strcat(path, busname);
|
strcat(path, busname);
|
||||||
|
|
|
@ -160,6 +160,11 @@ struct sysfs_class_device *sysfs_open_class_device_path
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(cdev->path, path);
|
strcpy(cdev->path, path);
|
||||||
|
if ((sysfs_remove_trailing_slash(cdev->path)) != 0) {
|
||||||
|
dprintf("Invalid path to class device %s\n", cdev->path);
|
||||||
|
sysfs_close_class_device(cdev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
set_classdev_classname(cdev);
|
set_classdev_classname(cdev);
|
||||||
|
|
||||||
return cdev;
|
return cdev;
|
||||||
|
@ -179,6 +184,10 @@ struct dlist *sysfs_get_class_devices(struct sysfs_class *cls)
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cls->devices != NULL)
|
||||||
|
return cls->devices;
|
||||||
|
|
||||||
if (cls->directory == NULL) {
|
if (cls->directory == NULL) {
|
||||||
cls->directory = sysfs_open_directory(cls->path);
|
cls->directory = sysfs_open_directory(cls->path);
|
||||||
if (cls->directory == NULL)
|
if (cls->directory == NULL)
|
||||||
|
@ -226,16 +235,16 @@ struct sysfs_class *sysfs_open_class(const unsigned char *name)
|
||||||
dprintf("Sysfs not supported on this system\n");
|
dprintf("Sysfs not supported on this system\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (sysfs_trailing_slash(classpath) == 0)
|
|
||||||
strcat(classpath, "/");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We shall now treat "block" also as a class. Hence, check here
|
* We shall now treat "block" also as a class. Hence, check here
|
||||||
* if "name" is "block" and proceed accordingly
|
* if "name" is "block" and proceed accordingly
|
||||||
*/
|
*/
|
||||||
if (strcmp(name, SYSFS_BLOCK_NAME) == 0) {
|
if (strcmp(name, SYSFS_BLOCK_NAME) == 0) {
|
||||||
|
strcat(classpath, "/");
|
||||||
strcat(classpath, SYSFS_BLOCK_NAME);
|
strcat(classpath, SYSFS_BLOCK_NAME);
|
||||||
} else {
|
} else {
|
||||||
|
strcat(classpath, "/");
|
||||||
strcat(classpath, SYSFS_CLASS_NAME);
|
strcat(classpath, SYSFS_CLASS_NAME);
|
||||||
strcat(classpath, "/");
|
strcat(classpath, "/");
|
||||||
strcat(classpath, name);
|
strcat(classpath, name);
|
||||||
|
@ -252,6 +261,11 @@ struct sysfs_class *sysfs_open_class(const unsigned char *name)
|
||||||
}
|
}
|
||||||
strcpy(cls->name, name);
|
strcpy(cls->name, name);
|
||||||
strcpy(cls->path, classpath);
|
strcpy(cls->path, classpath);
|
||||||
|
if ((sysfs_remove_trailing_slash(cls->path)) != 0) {
|
||||||
|
dprintf("Invalid path to class device %s\n", cls->path);
|
||||||
|
sysfs_close_class(cls);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
@ -264,8 +278,6 @@ struct sysfs_class *sysfs_open_class(const unsigned char *name)
|
||||||
struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *class,
|
struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *class,
|
||||||
unsigned char *name)
|
unsigned char *name)
|
||||||
{
|
{
|
||||||
struct dlist *devlist = NULL;
|
|
||||||
|
|
||||||
if (class == NULL || name == NULL) {
|
if (class == NULL || name == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -273,7 +285,7 @@ struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *class,
|
||||||
|
|
||||||
if (class->devices == NULL) {
|
if (class->devices == NULL) {
|
||||||
class->devices = sysfs_get_class_devices(class);
|
class->devices = sysfs_get_class_devices(class);
|
||||||
if (devlist == NULL)
|
if (class->devices == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return (struct sysfs_class_device *)dlist_find_custom(class->devices,
|
return (struct sysfs_class_device *)dlist_find_custom(class->devices,
|
||||||
|
@ -291,14 +303,21 @@ struct sysfs_device *sysfs_get_classdev_device
|
||||||
(struct sysfs_class_device *clsdev)
|
(struct sysfs_class_device *clsdev)
|
||||||
{
|
{
|
||||||
struct sysfs_link *devlink = NULL;
|
struct sysfs_link *devlink = NULL;
|
||||||
|
unsigned char devpath[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
if (clsdev == NULL) {
|
if (clsdev == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
strcpy(devpath, clsdev->path);
|
||||||
if (clsdev->sysdevice != NULL)
|
strcat(devpath, "/device");
|
||||||
return (clsdev->sysdevice);
|
if ((sysfs_path_is_link(devpath)) != 0) {
|
||||||
|
if (clsdev->sysdevice != NULL) {
|
||||||
|
sysfs_close_device(clsdev->sysdevice);
|
||||||
|
clsdev->sysdevice = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (clsdev->directory == NULL) {
|
if (clsdev->directory == NULL) {
|
||||||
clsdev->directory = sysfs_open_directory(clsdev->path);
|
clsdev->directory = sysfs_open_directory(clsdev->path);
|
||||||
|
@ -306,8 +325,24 @@ struct sysfs_device *sysfs_get_classdev_device
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
devlink = sysfs_get_directory_link(clsdev->directory, "device");
|
devlink = sysfs_get_directory_link(clsdev->directory, "device");
|
||||||
if (devlink == NULL)
|
if (devlink == NULL) {
|
||||||
|
if (clsdev->sysdevice != NULL) {
|
||||||
|
dprintf("Device link no longer exists\n");
|
||||||
|
sysfs_close_device(clsdev->sysdevice);
|
||||||
|
clsdev->sysdevice = NULL;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clsdev->sysdevice != NULL) {
|
||||||
|
if (!strncmp(devlink->target, clsdev->sysdevice->path,
|
||||||
|
SYSFS_PATH_MAX))
|
||||||
|
/* sysdevice hasn't changed */
|
||||||
|
return (clsdev->sysdevice);
|
||||||
|
else
|
||||||
|
/* come here only if the device link for has changed */
|
||||||
|
sysfs_close_device(clsdev->sysdevice);
|
||||||
|
}
|
||||||
|
|
||||||
clsdev->sysdevice = sysfs_open_device_path(devlink->target);
|
clsdev->sysdevice = sysfs_open_device_path(devlink->target);
|
||||||
if (clsdev->sysdevice == NULL)
|
if (clsdev->sysdevice == NULL)
|
||||||
|
@ -329,31 +364,56 @@ struct sysfs_driver *sysfs_get_classdev_driver
|
||||||
(struct sysfs_class_device *clsdev)
|
(struct sysfs_class_device *clsdev)
|
||||||
{
|
{
|
||||||
struct sysfs_link *drvlink = NULL;
|
struct sysfs_link *drvlink = NULL;
|
||||||
|
unsigned char drvpath[SYSFS_PATH_MAX];
|
||||||
|
|
||||||
if (clsdev == NULL) {
|
if (clsdev == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
strcpy(drvpath, clsdev->path);
|
||||||
if (clsdev->driver != NULL)
|
strcat(drvpath, "/driver");
|
||||||
return (clsdev->driver);
|
if ((sysfs_path_is_link(drvpath)) != 0) {
|
||||||
|
if (clsdev->driver != NULL) {
|
||||||
|
sysfs_close_driver(clsdev->driver);
|
||||||
|
clsdev->driver = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (clsdev->directory == NULL) {
|
if (clsdev->directory == NULL) {
|
||||||
clsdev->directory = sysfs_open_directory(clsdev->path);
|
clsdev->directory = sysfs_open_directory(clsdev->path);
|
||||||
if (clsdev->directory == NULL)
|
if (clsdev->directory == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
drvlink = sysfs_get_directory_link(clsdev->directory, "driver");
|
drvlink = sysfs_get_directory_link(clsdev->directory, "driver");
|
||||||
if (drvlink != NULL) {
|
if (drvlink == NULL) {
|
||||||
clsdev->driver = sysfs_open_driver_path(drvlink->target);
|
if (clsdev->driver != NULL) {
|
||||||
if (clsdev->driver == NULL)
|
dprintf("Driver link no longer exists\n");
|
||||||
return NULL;
|
sysfs_close_driver(clsdev->driver);
|
||||||
|
clsdev->driver = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (clsdev->driver != NULL) {
|
||||||
|
if (!strncmp(drvlink->target, clsdev->driver->path,
|
||||||
|
SYSFS_PATH_MAX))
|
||||||
|
/* driver hasn't changed */
|
||||||
|
return (clsdev->driver);
|
||||||
|
else
|
||||||
|
/* come here only if the device link for has changed */
|
||||||
|
sysfs_close_driver(clsdev->driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
clsdev->driver = sysfs_open_driver_path(drvlink->target);
|
||||||
|
if (clsdev->driver == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (clsdev->sysdevice != NULL)
|
||||||
|
strcpy(clsdev->sysdevice->driver_name, clsdev->driver->name);
|
||||||
|
|
||||||
return (clsdev->driver);
|
return (clsdev->driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* get_blockdev_parent: Get the parent class device for a "block" subsystem
|
* get_blockdev_parent: Get the parent class device for a "block" subsystem
|
||||||
* device if present
|
* device if present
|
||||||
* @clsdev: block subsystem class device whose parent needs to be found
|
* @clsdev: block subsystem class device whose parent needs to be found
|
||||||
|
@ -361,48 +421,34 @@ struct sysfs_driver *sysfs_get_classdev_driver
|
||||||
*/
|
*/
|
||||||
static int get_blockdev_parent(struct sysfs_class_device *clsdev)
|
static int get_blockdev_parent(struct sysfs_class_device *clsdev)
|
||||||
{
|
{
|
||||||
unsigned char parent_path[SYSFS_PATH_MAX], value[256], *c = NULL;
|
unsigned char parent_path[SYSFS_PATH_MAX], *c = NULL;
|
||||||
|
|
||||||
memset(parent_path, 0, SYSFS_PATH_MAX);
|
|
||||||
strcpy(parent_path, clsdev->path);
|
|
||||||
|
|
||||||
|
strcpy(parent_path, clsdev->path);
|
||||||
c = strstr(parent_path, SYSFS_BLOCK_NAME);
|
c = strstr(parent_path, SYSFS_BLOCK_NAME);
|
||||||
if (c == NULL) {
|
if (c == NULL) {
|
||||||
dprintf("Class device %s does not belong to BLOCK subsystem",
|
dprintf("Class device %s does not belong to BLOCK subsystem\n",
|
||||||
clsdev->name);
|
clsdev->name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
c += strlen(SYSFS_BLOCK_NAME);
|
c += strlen(SYSFS_BLOCK_NAME);
|
||||||
if (*c == '/')
|
if (*c == '/')
|
||||||
c++;
|
c++;
|
||||||
else
|
else
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
||||||
/* validate whether the given class device is a partition or not */
|
/* validate whether the given class device is a partition or not */
|
||||||
if ((strncmp(c, clsdev->name, strlen(clsdev->name))) == 0) {
|
if ((strncmp(c, clsdev->name, strlen(clsdev->name))) == 0) {
|
||||||
dprintf("%s not a partition\n", clsdev->name);
|
dprintf("%s not a partition\n", clsdev->name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
c = strchr(c, '/');
|
|
||||||
if (c == NULL)
|
c = strchr(c, '/');
|
||||||
goto errout;
|
|
||||||
*c = '\0';
|
|
||||||
|
|
||||||
/* Now validate if the parent has the "dev" attribute */
|
|
||||||
memset(value, 0, 256);
|
|
||||||
strcat(parent_path, "/dev");
|
|
||||||
if ((sysfs_read_attribute_value(parent_path, value, 256)) != 0) {
|
|
||||||
dprintf("Block device %s does not have a parent\n",
|
|
||||||
clsdev->name);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = strrchr(parent_path, '/');
|
|
||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
||||||
*c = '\0';
|
*c = '\0';
|
||||||
|
|
||||||
clsdev->parent = sysfs_open_class_device_path(parent_path);
|
clsdev->parent = sysfs_open_class_device_path(parent_path);
|
||||||
if (clsdev->parent == NULL) {
|
if (clsdev->parent == NULL) {
|
||||||
dprintf("Error opening the parent class device at %s\n",
|
dprintf("Error opening the parent class device at %s\n",
|
||||||
|
@ -467,13 +513,11 @@ static int get_classdev_path(const unsigned char *classname,
|
||||||
dprintf("Error getting sysfs mount path\n");
|
dprintf("Error getting sysfs mount path\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sysfs_trailing_slash(path) == 0)
|
|
||||||
strcat(path, "/");
|
|
||||||
|
|
||||||
if (strcmp(classname, SYSFS_BLOCK_NAME) == 0) {
|
if (strcmp(classname, SYSFS_BLOCK_NAME) == 0) {
|
||||||
|
strcat(path, "/");
|
||||||
strcat(path, SYSFS_BLOCK_NAME);
|
strcat(path, SYSFS_BLOCK_NAME);
|
||||||
} else {
|
} else {
|
||||||
|
strcat(path, "/");
|
||||||
strcat(path, SYSFS_CLASS_NAME);
|
strcat(path, SYSFS_CLASS_NAME);
|
||||||
strcat(path, "/");
|
strcat(path, "/");
|
||||||
strcat(path, classname);
|
strcat(path, classname);
|
||||||
|
@ -537,26 +581,40 @@ struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *cdev)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (cdev->directory->attributes == NULL) {
|
if (cdev->directory->attributes == NULL) {
|
||||||
if ((sysfs_read_dir_attributes(cdev->directory)) != 0) {
|
if ((sysfs_read_dir_attributes(cdev->directory)) != 0)
|
||||||
dprintf("Error reading attributes for directory %s\n",
|
|
||||||
cdev->directory->path);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((sysfs_path_is_dir(cdev->path)) != 0) {
|
|
||||||
dprintf("Class device at %s no longer exists\n",
|
|
||||||
cdev->path);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if ((sysfs_refresh_attributes
|
|
||||||
(cdev->directory->attributes)) != 0) {
|
|
||||||
dprintf("Error refreshing classdev attributes\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (cdev->directory->attributes);
|
return (cdev->directory->attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_refresh_clsassdev_attributes: refreshes the driver's list of attributes
|
||||||
|
* @clsdev: sysfs_class_device whose attributes to refresh
|
||||||
|
*
|
||||||
|
* NOTE: Upon return, prior references to sysfs_attributes for this classdev
|
||||||
|
* _may_ not be valid
|
||||||
|
*
|
||||||
|
* Returns list of attributes on success and NULL on failure
|
||||||
|
*/
|
||||||
|
struct dlist *sysfs_refresh_classdev_attributes
|
||||||
|
(struct sysfs_class_device *clsdev)
|
||||||
|
{
|
||||||
|
if (clsdev == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clsdev->directory == NULL)
|
||||||
|
return (sysfs_get_classdev_attributes(clsdev));
|
||||||
|
|
||||||
|
if ((sysfs_refresh_dir_attributes(clsdev->directory)) != 0) {
|
||||||
|
dprintf("Error refreshing class_device attributes\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (clsdev->directory->attributes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_get_classdev_attr: searches class device's attributes by name
|
* sysfs_get_classdev_attr: searches class device's attributes by name
|
||||||
* @clsdev: class device to look through
|
* @clsdev: class device to look through
|
||||||
|
@ -597,15 +655,10 @@ struct sysfs_attribute *sysfs_get_classdev_attr
|
||||||
struct sysfs_directory) {
|
struct sysfs_directory) {
|
||||||
if ((sysfs_path_is_dir(sdir->path)) != 0)
|
if ((sysfs_path_is_dir(sdir->path)) != 0)
|
||||||
continue;
|
continue;
|
||||||
if (sdir->attributes == NULL) {
|
cur = sysfs_get_directory_attribute(sdir,
|
||||||
cur = sysfs_get_directory_attribute(sdir,
|
|
||||||
(unsigned char *)name);
|
(unsigned char *)name);
|
||||||
} else {
|
if (cur == NULL)
|
||||||
if ((sysfs_refresh_attributes
|
continue;
|
||||||
(sdir->attributes)) == 0)
|
|
||||||
cur = sysfs_get_directory_attribute(sdir,
|
|
||||||
(unsigned char *)name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cur;
|
return cur;
|
||||||
|
|
|
@ -24,12 +24,12 @@
|
||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_device_bus: retrieves the bus name the device is on, checks path to
|
* sysfs_get_device_bus: retrieves the bus name the device is on, checks path
|
||||||
* bus' link to make sure it has correct device.
|
* to bus' link to make sure it has correct device.
|
||||||
* @dev: device to get busname.
|
* @dev: device to get busname.
|
||||||
* returns 0 with success and -1 with error.
|
* returns 0 with success and -1 with error.
|
||||||
*/
|
*/
|
||||||
static int get_device_bus(struct sysfs_device *dev)
|
int sysfs_get_device_bus(struct sysfs_device *dev)
|
||||||
{
|
{
|
||||||
unsigned char subsys[SYSFS_NAME_LEN], path[SYSFS_PATH_MAX];
|
unsigned char subsys[SYSFS_NAME_LEN], path[SYSFS_PATH_MAX];
|
||||||
unsigned char target[SYSFS_PATH_MAX], *bus = NULL, *c = NULL;
|
unsigned char target[SYSFS_PATH_MAX], *bus = NULL, *c = NULL;
|
||||||
|
@ -197,6 +197,11 @@ struct sysfs_device *sysfs_open_device_path(const unsigned char *path)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
strcpy(dev->path, path);
|
strcpy(dev->path, path);
|
||||||
|
if ((sysfs_remove_trailing_slash(dev->path)) != 0) {
|
||||||
|
dprintf("Invalid path to device %s\n", dev->path);
|
||||||
|
sysfs_close_device(dev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* The "name" attribute no longer exists... return the device's
|
* The "name" attribute no longer exists... return the device's
|
||||||
* sysfs representation instead, in the "dev->name" field, which
|
* sysfs representation instead, in the "dev->name" field, which
|
||||||
|
@ -204,8 +209,8 @@ struct sysfs_device *sysfs_open_device_path(const unsigned char *path)
|
||||||
*/
|
*/
|
||||||
strncpy(dev->name, dev->bus_id, SYSFS_NAME_LEN);
|
strncpy(dev->name, dev->bus_id, SYSFS_NAME_LEN);
|
||||||
|
|
||||||
if (get_device_bus(dev) != 0)
|
if (sysfs_get_device_bus(dev) != 0)
|
||||||
strcpy(dev->bus, SYSFS_UNKNOWN);
|
dprintf("Could not get device bus\n");
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
@ -334,8 +339,7 @@ struct sysfs_root_device *sysfs_open_root_device(const unsigned char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sysfs_trailing_slash(rootpath) == 0)
|
strcat(rootpath, "/");
|
||||||
strcat(rootpath, "/");
|
|
||||||
strcat(rootpath, SYSFS_DEVICES_NAME);
|
strcat(rootpath, SYSFS_DEVICES_NAME);
|
||||||
strcat(rootpath, "/");
|
strcat(rootpath, "/");
|
||||||
strcat(rootpath, name);
|
strcat(rootpath, name);
|
||||||
|
@ -352,6 +356,11 @@ struct sysfs_root_device *sysfs_open_root_device(const unsigned char *name)
|
||||||
}
|
}
|
||||||
strcpy(root->name, name);
|
strcpy(root->name, name);
|
||||||
strcpy(root->path, rootpath);
|
strcpy(root->path, rootpath);
|
||||||
|
if ((sysfs_remove_trailing_slash(root->path)) != 0) {
|
||||||
|
dprintf("Invalid path to root device %s\n", root->path);
|
||||||
|
sysfs_close_root_device(root);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,20 +382,37 @@ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device)
|
||||||
if (device->directory->attributes == NULL) {
|
if (device->directory->attributes == NULL) {
|
||||||
if ((sysfs_read_dir_attributes(device->directory)) != 0)
|
if ((sysfs_read_dir_attributes(device->directory)) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
|
||||||
if ((sysfs_path_is_dir(device->path)) != 0) {
|
|
||||||
dprintf("Device at %s no longer exists", device->path);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if ((sysfs_refresh_attributes
|
|
||||||
(device->directory->attributes)) != 0) {
|
|
||||||
dprintf("Error refreshing device attributes\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (device->directory->attributes);
|
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
|
* sysfs_get_device_attr: searches dev's attributes by name
|
||||||
* @dev: device to look through
|
* @dev: device to look through
|
||||||
|
@ -396,22 +422,19 @@ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device)
|
||||||
struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
|
struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
|
||||||
const unsigned char *name)
|
const unsigned char *name)
|
||||||
{
|
{
|
||||||
struct sysfs_attribute *cur = NULL;
|
|
||||||
struct dlist *attrlist = NULL;
|
struct dlist *attrlist = NULL;
|
||||||
|
|
||||||
if (dev == NULL || name == NULL) {
|
if (dev == NULL || name == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
attrlist = sysfs_get_device_attributes(dev);
|
attrlist = sysfs_get_device_attributes(dev);
|
||||||
if (attrlist == NULL)
|
if (attrlist == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cur = sysfs_get_directory_attribute(dev->directory,
|
return sysfs_get_directory_attribute(dev->directory,
|
||||||
(unsigned char *)name);
|
(unsigned char *)name);
|
||||||
|
|
||||||
return cur;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -437,8 +460,7 @@ static int get_device_absolute_path(const unsigned char *device,
|
||||||
dprintf ("Sysfs not supported on this system\n");
|
dprintf ("Sysfs not supported on this system\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (sysfs_trailing_slash(bus_path) == 0)
|
strcat(bus_path, "/");
|
||||||
strcat(bus_path, "/");
|
|
||||||
strcat(bus_path, SYSFS_BUS_NAME);
|
strcat(bus_path, SYSFS_BUS_NAME);
|
||||||
strcat(bus_path, "/");
|
strcat(bus_path, "/");
|
||||||
strcat(bus_path, bus);
|
strcat(bus_path, bus);
|
||||||
|
|
|
@ -195,7 +195,7 @@ int sysfs_write_attribute(struct sysfs_attribute *sysattr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) {
|
if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) {
|
||||||
dprintf("Attribute %s already has the requested value %s\n",
|
dprintf("Attr %s already has the requested value %s\n",
|
||||||
sysattr->name, new_value);
|
sysattr->name, new_value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#ifdef __KLIBC__
|
#ifdef __KLIBC__
|
||||||
pgsize = 0x1000;
|
pgsize = 0x1000;
|
||||||
#else
|
#else
|
||||||
pgsize = sysconf(_SC_PAGESIZE);
|
pgsize = sysconf(_SC_PAGESIZE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -468,6 +468,13 @@ struct sysfs_directory *sysfs_open_directory(const unsigned char *path)
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sysfs_path_is_dir(path) != 0) {
|
||||||
|
dprintf("Invalid path directory %s\n", path);
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
sdir = alloc_directory();
|
sdir = alloc_directory();
|
||||||
if (sdir == NULL) {
|
if (sdir == NULL) {
|
||||||
dprintf("Error allocating directory %s\n", path);
|
dprintf("Error allocating directory %s\n", path);
|
||||||
|
@ -513,39 +520,6 @@ struct sysfs_link *sysfs_open_link(const unsigned char *linkpath)
|
||||||
return ln;
|
return ln;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* sysfs_refresh_attributes: Refresh attributes list
|
|
||||||
* @attrlist: list of attributes to refresh
|
|
||||||
* Returns 0 on success, 1 on failure
|
|
||||||
*/
|
|
||||||
int sysfs_refresh_attributes(struct dlist *attrlist)
|
|
||||||
{
|
|
||||||
struct sysfs_attribute *attr = NULL;
|
|
||||||
|
|
||||||
if (attrlist == NULL) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
dlist_for_each_data(attrlist, attr, struct sysfs_attribute) {
|
|
||||||
if (attr->method & SYSFS_METHOD_SHOW) {
|
|
||||||
if ((sysfs_read_attribute(attr)) != 0) {
|
|
||||||
dprintf("Error reading attribute %s\n",
|
|
||||||
attr->path);
|
|
||||||
if ((sysfs_path_is_file(attr->path)) != 0) {
|
|
||||||
dprintf("Attr %s no longer exists\n",
|
|
||||||
attr->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((sysfs_path_is_file(attr->path)) != 0) {
|
|
||||||
dprintf("Attr %s no longer exists\n",
|
|
||||||
attr->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add_attribute: open and add attribute at path to given directory
|
* add_attribute: open and add attribute at path to given directory
|
||||||
* @sysdir: directory to add attribute to
|
* @sysdir: directory to add attribute to
|
||||||
|
@ -633,7 +607,6 @@ int sysfs_read_dir_attributes(struct sysfs_directory *sysdir)
|
||||||
{
|
{
|
||||||
DIR *dir = NULL;
|
DIR *dir = NULL;
|
||||||
struct dirent *dirent = NULL;
|
struct dirent *dirent = NULL;
|
||||||
struct stat astats;
|
|
||||||
unsigned char file_path[SYSFS_PATH_MAX];
|
unsigned char file_path[SYSFS_PATH_MAX];
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
|
@ -655,11 +628,7 @@ int sysfs_read_dir_attributes(struct sysfs_directory *sysdir)
|
||||||
strncpy(file_path, sysdir->path, SYSFS_PATH_MAX);
|
strncpy(file_path, sysdir->path, SYSFS_PATH_MAX);
|
||||||
strcat(file_path, "/");
|
strcat(file_path, "/");
|
||||||
strcat(file_path, dirent->d_name);
|
strcat(file_path, dirent->d_name);
|
||||||
if ((lstat(file_path, &astats)) != 0) {
|
if ((sysfs_path_is_file(file_path)) == 0)
|
||||||
dprintf("stat failed\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (S_ISREG(astats.st_mode))
|
|
||||||
retval = add_attribute(sysdir, file_path);
|
retval = add_attribute(sysdir, file_path);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
@ -675,7 +644,6 @@ int sysfs_read_dir_links(struct sysfs_directory *sysdir)
|
||||||
{
|
{
|
||||||
DIR *dir = NULL;
|
DIR *dir = NULL;
|
||||||
struct dirent *dirent = NULL;
|
struct dirent *dirent = NULL;
|
||||||
struct stat astats;
|
|
||||||
unsigned char file_path[SYSFS_PATH_MAX];
|
unsigned char file_path[SYSFS_PATH_MAX];
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
|
@ -697,11 +665,7 @@ int sysfs_read_dir_links(struct sysfs_directory *sysdir)
|
||||||
strncpy(file_path, sysdir->path, SYSFS_PATH_MAX);
|
strncpy(file_path, sysdir->path, SYSFS_PATH_MAX);
|
||||||
strcat(file_path, "/");
|
strcat(file_path, "/");
|
||||||
strcat(file_path, dirent->d_name);
|
strcat(file_path, dirent->d_name);
|
||||||
if ((lstat(file_path, &astats)) != 0) {
|
if ((sysfs_path_is_link(file_path)) == 0) {
|
||||||
dprintf("stat failed\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (S_ISLNK(astats.st_mode)) {
|
|
||||||
retval = add_link(sysdir, file_path);
|
retval = add_link(sysdir, file_path);
|
||||||
if (retval != 0)
|
if (retval != 0)
|
||||||
break;
|
break;
|
||||||
|
@ -720,7 +684,6 @@ int sysfs_read_dir_subdirs(struct sysfs_directory *sysdir)
|
||||||
{
|
{
|
||||||
DIR *dir = NULL;
|
DIR *dir = NULL;
|
||||||
struct dirent *dirent = NULL;
|
struct dirent *dirent = NULL;
|
||||||
struct stat astats;
|
|
||||||
unsigned char file_path[SYSFS_PATH_MAX];
|
unsigned char file_path[SYSFS_PATH_MAX];
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
|
@ -742,11 +705,7 @@ int sysfs_read_dir_subdirs(struct sysfs_directory *sysdir)
|
||||||
strncpy(file_path, sysdir->path, SYSFS_PATH_MAX);
|
strncpy(file_path, sysdir->path, SYSFS_PATH_MAX);
|
||||||
strcat(file_path, "/");
|
strcat(file_path, "/");
|
||||||
strcat(file_path, dirent->d_name);
|
strcat(file_path, dirent->d_name);
|
||||||
if ((lstat(file_path, &astats)) != 0) {
|
if ((sysfs_path_is_dir(file_path)) == 0)
|
||||||
dprintf("stat failed\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (S_ISDIR(astats.st_mode))
|
|
||||||
retval = add_subdirectory(sysdir, file_path);
|
retval = add_subdirectory(sysdir, file_path);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
@ -801,6 +760,90 @@ int sysfs_read_directory(struct sysfs_directory *sysdir)
|
||||||
return(retval);
|
return(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_refresh_dir_attributes: Refresh attributes list
|
||||||
|
* @sysdir: directory whose list of attributes to refresh
|
||||||
|
* Returns 0 on success, 1 on failure
|
||||||
|
*/
|
||||||
|
int sysfs_refresh_dir_attributes(struct sysfs_directory *sysdir)
|
||||||
|
{
|
||||||
|
if (sysdir == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((sysfs_path_is_dir(sysdir->path)) != 0) {
|
||||||
|
dprintf("Invalid path to directory %s\n", sysdir->path);
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (sysdir->attributes != NULL) {
|
||||||
|
dlist_destroy(sysdir->attributes);
|
||||||
|
sysdir->attributes = NULL;
|
||||||
|
}
|
||||||
|
if ((sysfs_read_dir_attributes(sysdir)) != 0) {
|
||||||
|
dprintf("Error refreshing attributes for directory %s\n",
|
||||||
|
sysdir->path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_refresh_dir_links: Refresh links list
|
||||||
|
* @sysdir: directory whose list of links to refresh
|
||||||
|
* Returns 0 on success, 1 on failure
|
||||||
|
*/
|
||||||
|
int sysfs_refresh_dir_links(struct sysfs_directory *sysdir)
|
||||||
|
{
|
||||||
|
if (sysdir == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((sysfs_path_is_dir(sysdir->path)) != 0) {
|
||||||
|
dprintf("Invalid path to directory %s\n", sysdir->path);
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (sysdir->links != NULL) {
|
||||||
|
dlist_destroy(sysdir->links);
|
||||||
|
sysdir->links = NULL;
|
||||||
|
}
|
||||||
|
if ((sysfs_read_dir_links(sysdir)) != 0) {
|
||||||
|
dprintf("Error refreshing links for directory %s\n",
|
||||||
|
sysdir->path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_refresh_dir_subdirs: Refresh subdirs list
|
||||||
|
* @sysdir: directory whose list of subdirs to refresh
|
||||||
|
* Returns 0 on success, 1 on failure
|
||||||
|
*/
|
||||||
|
int sysfs_refresh_dir_subdirs(struct sysfs_directory *sysdir)
|
||||||
|
{
|
||||||
|
if (sysdir == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((sysfs_path_is_dir(sysdir->path)) != 0) {
|
||||||
|
dprintf("Invalid path to directory %s\n", sysdir->path);
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (sysdir->subdirs != NULL) {
|
||||||
|
dlist_destroy(sysdir->subdirs);
|
||||||
|
sysdir->subdirs = NULL;
|
||||||
|
}
|
||||||
|
if ((sysfs_read_dir_subdirs(sysdir)) != 0) {
|
||||||
|
dprintf("Error refreshing subdirs for directory %s\n",
|
||||||
|
sysdir->path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_get_directory_attribute: retrieves attribute attrname from current
|
* sysfs_get_directory_attribute: retrieves attribute attrname from current
|
||||||
* directory only
|
* directory only
|
||||||
|
@ -826,19 +869,25 @@ struct sysfs_attribute *sysfs_get_directory_attribute
|
||||||
|
|
||||||
attr = (struct sysfs_attribute *)dlist_find_custom
|
attr = (struct sysfs_attribute *)dlist_find_custom
|
||||||
(dir->attributes, attrname, dir_attribute_name_equal);
|
(dir->attributes, attrname, dir_attribute_name_equal);
|
||||||
if (attr == NULL) {
|
if (attr != NULL) {
|
||||||
|
if ((sysfs_read_attribute(attr)) != 0) {
|
||||||
|
dprintf("Error reading attribute %s\n", attr->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
memset(new_path, 0, SYSFS_PATH_MAX);
|
memset(new_path, 0, SYSFS_PATH_MAX);
|
||||||
strcpy(new_path, dir->path);
|
strcpy(new_path, dir->path);
|
||||||
strcat(new_path, "/");
|
strcat(new_path, "/");
|
||||||
strcat(new_path, attrname);
|
strcat(new_path, attrname);
|
||||||
if ((sysfs_path_is_file(new_path)) == 0) {
|
if ((sysfs_path_is_file(new_path)) == 0) {
|
||||||
if ((add_attribute(dir, new_path)) == 0) {
|
if ((add_attribute(dir, new_path)) == 0) {
|
||||||
attr = (struct sysfs_attribute *)
|
attr = (struct sysfs_attribute *)
|
||||||
dlist_find_custom(dir->attributes,
|
dlist_find_custom(dir->attributes,
|
||||||
attrname, dir_attribute_name_equal);
|
attrname, dir_attribute_name_equal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,9 +904,13 @@ struct sysfs_link *sysfs_get_directory_link
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (dir->links == NULL)
|
if (dir->links == NULL) {
|
||||||
if ((sysfs_read_dir_links(dir) != 0) || (dir->links == NULL))
|
if ((sysfs_read_dir_links(dir) != 0) || (dir->links == NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
} else {
|
||||||
|
if ((sysfs_refresh_dir_links(dir)) != 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return (struct sysfs_link *)dlist_find_custom(dir->links,
|
return (struct sysfs_link *)dlist_find_custom(dir->links,
|
||||||
linkname, dir_link_name_equal);
|
linkname, dir_link_name_equal);
|
||||||
|
@ -940,3 +993,63 @@ struct sysfs_link *sysfs_get_subdirectory_link(struct sysfs_directory *dir,
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_get_dir_attributes: returns dlist of directory attributes
|
||||||
|
* @dir: directory to retrieve attributes from
|
||||||
|
* returns dlist of attributes or NULL
|
||||||
|
*/
|
||||||
|
struct dlist *sysfs_get_dir_attributes(struct sysfs_directory *dir)
|
||||||
|
{
|
||||||
|
if (dir == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir->attributes == NULL) {
|
||||||
|
if (sysfs_read_dir_attributes(dir) != 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (dir->attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_get_dir_links: returns dlist of directory links
|
||||||
|
* @dir: directory to return links for
|
||||||
|
* returns dlist of links or NULL
|
||||||
|
*/
|
||||||
|
struct dlist *sysfs_get_dir_links(struct sysfs_directory *dir)
|
||||||
|
{
|
||||||
|
if (dir == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir->links == NULL) {
|
||||||
|
if (sysfs_read_dir_links(dir) != 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (dir->links);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_get_dir_subdirs: returns dlist of directory subdirectories
|
||||||
|
* @dir: directory to return subdirs for
|
||||||
|
* returns dlist of subdirs or NULL
|
||||||
|
*/
|
||||||
|
struct dlist *sysfs_get_dir_subdirs(struct sysfs_directory *dir)
|
||||||
|
{
|
||||||
|
if (dir == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir->subdirs == NULL) {
|
||||||
|
if (sysfs_read_dir_subdirs(dir) != 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (dir->subdirs);
|
||||||
|
}
|
||||||
|
|
|
@ -103,6 +103,11 @@ struct sysfs_driver *sysfs_open_driver_path(const unsigned char *path)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
strcpy(driver->path, path);
|
strcpy(driver->path, path);
|
||||||
|
if ((sysfs_remove_trailing_slash(driver->path)) != 0) {
|
||||||
|
dprintf("Invalid path to driver %s\n", driver->path);
|
||||||
|
sysfs_close_driver(driver);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return driver;
|
return driver;
|
||||||
}
|
}
|
||||||
|
@ -125,25 +130,37 @@ struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (driver->directory->attributes == NULL) {
|
if (driver->directory->attributes == NULL) {
|
||||||
if ((sysfs_read_dir_attributes(driver->directory)) != 0) {
|
if ((sysfs_read_dir_attributes(driver->directory)) != 0)
|
||||||
dprintf("Error reading driver attributes\n");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((sysfs_path_is_dir(driver->path)) != 0) {
|
|
||||||
dprintf("Driver at %s no longer exists\n",
|
|
||||||
driver->path);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if ((sysfs_refresh_attributes
|
|
||||||
(driver->directory->attributes)) != 0) {
|
|
||||||
dprintf("Error refreshing driver attributes\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return(driver->directory->attributes);
|
return(driver->directory->attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_refresh_driver_attributes: refreshes the driver's list of attributes
|
||||||
|
* @driver: sysfs_driver whose attributes to refresh
|
||||||
|
*
|
||||||
|
* NOTE: Upon return, prior references to sysfs_attributes for this driver
|
||||||
|
* _may_ not be valid
|
||||||
|
*
|
||||||
|
* Returns list of attributes on success and NULL on failure
|
||||||
|
*/
|
||||||
|
struct dlist *sysfs_refresh_driver_attributes(struct sysfs_driver *driver)
|
||||||
|
{
|
||||||
|
if (driver == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (driver->directory == NULL)
|
||||||
|
return (sysfs_get_driver_attributes(driver));
|
||||||
|
|
||||||
|
if ((sysfs_refresh_dir_attributes(driver->directory)) != 0) {
|
||||||
|
dprintf("Error refreshing driver attributes\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return (driver->directory->attributes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_get_driver_attr: searches driver's attributes by name
|
* sysfs_get_driver_attr: searches driver's attributes by name
|
||||||
* @drv: driver to look through
|
* @drv: driver to look through
|
||||||
|
@ -153,7 +170,6 @@ struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver)
|
||||||
struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv,
|
struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv,
|
||||||
const unsigned char *name)
|
const unsigned char *name)
|
||||||
{
|
{
|
||||||
struct sysfs_attribute *cur = NULL;
|
|
||||||
struct dlist *attrlist = NULL;
|
struct dlist *attrlist = NULL;
|
||||||
|
|
||||||
if (drv == NULL) {
|
if (drv == NULL) {
|
||||||
|
@ -163,9 +179,10 @@ struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv,
|
||||||
|
|
||||||
attrlist = sysfs_get_driver_attributes(drv);
|
attrlist = sysfs_get_driver_attributes(drv);
|
||||||
if (attrlist != NULL)
|
if (attrlist != NULL)
|
||||||
cur = sysfs_get_directory_attribute(drv->directory,
|
return NULL;
|
||||||
|
|
||||||
|
return sysfs_get_directory_attribute(drv->directory,
|
||||||
(unsigned char *)name);
|
(unsigned char *)name);
|
||||||
return cur;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,6 +250,38 @@ struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver)
|
||||||
return (driver->devices);
|
return (driver->devices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_refresh_driver_devices: Refreshes drivers list of devices
|
||||||
|
* @driver: sysfs_driver whose devices list needs to be refreshed
|
||||||
|
*
|
||||||
|
* NOTE: Upon return from this function, prior sysfs_device references from
|
||||||
|
* this driver's list of devices _may_ not be valid
|
||||||
|
*
|
||||||
|
* Returns dlist of devices on success and NULL on failure
|
||||||
|
*/
|
||||||
|
struct dlist *sysfs_refresh_driver_devices(struct sysfs_driver *driver)
|
||||||
|
{
|
||||||
|
if (driver == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (driver->devices != NULL) {
|
||||||
|
dlist_destroy(driver->devices);
|
||||||
|
driver->devices = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (driver->directory == NULL)
|
||||||
|
return (sysfs_get_driver_devices(driver));
|
||||||
|
|
||||||
|
if ((sysfs_refresh_dir_links(driver->directory)) != 0) {
|
||||||
|
dprintf("Error refreshing driver links\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (sysfs_get_driver_devices(driver));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_get_driver_device: looks up a device from a list of driver's devices
|
* sysfs_get_driver_device: looks up a device from a list of driver's devices
|
||||||
* and returns its sysfs_device corresponding to it
|
* and returns its sysfs_device corresponding to it
|
||||||
|
@ -285,8 +334,7 @@ static int get_driver_path(const unsigned char *bus,
|
||||||
dprintf("Error getting sysfs mount path\n");
|
dprintf("Error getting sysfs mount path\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (sysfs_trailing_slash(path) == 0)
|
strcat(path, "/");
|
||||||
strcat(path, "/");
|
|
||||||
strcat(path, SYSFS_BUS_NAME);
|
strcat(path, SYSFS_BUS_NAME);
|
||||||
strcat(path, "/");
|
strcat(path, "/");
|
||||||
strcat(path, bus);
|
strcat(path, bus);
|
||||||
|
|
|
@ -26,6 +26,30 @@
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sysfs_remove_trailing_slash: Removes any trailing '/' in the given path
|
||||||
|
* @path: Path to look for the trailing '/'
|
||||||
|
* Returns 0 on success 1 on error
|
||||||
|
*/
|
||||||
|
int sysfs_remove_trailing_slash(unsigned char *path)
|
||||||
|
{
|
||||||
|
unsigned char *c = NULL;
|
||||||
|
|
||||||
|
if (path == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
c = strrchr(path, '/');
|
||||||
|
if (c == NULL) {
|
||||||
|
dprintf("Invalid path %s\n", path);
|
||||||
|
errno = EINVAL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (*(c+1) == '\0')
|
||||||
|
*c = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_get_mnt_path: Gets the mount point for specified filesystem.
|
* sysfs_get_mnt_path: Gets the mount point for specified filesystem.
|
||||||
* @fs_type: filesystem type to retrieve mount point
|
* @fs_type: filesystem type to retrieve mount point
|
||||||
|
@ -72,27 +96,13 @@ static int sysfs_get_fs_mnt_path(const unsigned char *fs_type,
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
if ((sysfs_remove_trailing_slash(mnt_path)) != 0)
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* sysfs_trailing_slash: checks if there's a trailing slash to path
|
|
||||||
* @path: path to check
|
|
||||||
* returns 1 if true and 0 if not
|
|
||||||
*/
|
|
||||||
int sysfs_trailing_slash(unsigned char *path)
|
|
||||||
{
|
|
||||||
unsigned char *s = NULL;
|
|
||||||
|
|
||||||
if (path == NULL)
|
|
||||||
return 0;
|
|
||||||
s = &path[strlen(path)-1];
|
|
||||||
if (strncmp(s, "/", 1) == 0)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sysfs_get_mnt_path: Gets the sysfs mount point.
|
* sysfs_get_mnt_path: Gets the sysfs mount point.
|
||||||
* @mnt_path: place to put "sysfs" mount point
|
* @mnt_path: place to put "sysfs" mount point
|
||||||
|
@ -109,9 +119,11 @@ int sysfs_get_mnt_path(unsigned char *mnt_path, size_t len)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sysfs_path = getenv(SYSFS_PATH_ENV);
|
sysfs_path = getenv(SYSFS_PATH_ENV);
|
||||||
if (sysfs_path != NULL)
|
if (sysfs_path != NULL) {
|
||||||
strncpy(mnt_path, sysfs_path, len);
|
strncpy(mnt_path, sysfs_path, len);
|
||||||
else
|
if ((sysfs_remove_trailing_slash(mnt_path)) != 0)
|
||||||
|
return 1;
|
||||||
|
} else
|
||||||
ret = sysfs_get_fs_mnt_path(SYSFS_FSTYPE_NAME, mnt_path, len);
|
ret = sysfs_get_fs_mnt_path(SYSFS_FSTYPE_NAME, mnt_path, len);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -152,7 +164,7 @@ int sysfs_get_name_from_path(const unsigned char *path, unsigned char *name,
|
||||||
strncpy(name, n, len);
|
strncpy(name, n, len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_get_link: returns link source
|
* sysfs_get_link: returns link source
|
||||||
* @path: symbolic link's path
|
* @path: symbolic link's path
|
||||||
|
@ -178,32 +190,69 @@ int sysfs_get_link(const unsigned char *path, unsigned char *target, size_t len)
|
||||||
if ((readlink(path, linkpath, SYSFS_PATH_MAX)) < 0) {
|
if ((readlink(path, linkpath, SYSFS_PATH_MAX)) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
d = linkpath;
|
d = linkpath;
|
||||||
|
/*
|
||||||
/* getting rid of leading "../.." */
|
* Three cases here:
|
||||||
while (*d == '/' || *d == '.') {
|
* 1. relative path => format ../..
|
||||||
if (*d == '/')
|
* 2. absolute path => format /abcd/efgh
|
||||||
slashes++;
|
* 3. relative path _from_ this dir => format abcd/efgh
|
||||||
d++;
|
*/
|
||||||
|
switch (*d) {
|
||||||
|
case '.':
|
||||||
|
/*
|
||||||
|
* handle the case where link is of type ./abcd/xxx
|
||||||
|
*/
|
||||||
|
strncpy(target, devdir, len);
|
||||||
|
if (*(d+1) == '/')
|
||||||
|
d += 2;
|
||||||
|
else if (*(d+1) == '.')
|
||||||
|
goto parse_path;
|
||||||
|
s = strrchr(target, '/');
|
||||||
|
if (s != NULL) {
|
||||||
|
*(s+1) = '\0';
|
||||||
|
strcat(target, d);
|
||||||
|
} else {
|
||||||
|
strcpy(target, d);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* relative path
|
||||||
|
* getting rid of leading "../.."
|
||||||
|
*/
|
||||||
|
parse_path:
|
||||||
|
while (*d == '/' || *d == '.') {
|
||||||
|
if (*d == '/')
|
||||||
|
slashes++;
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
d--;
|
||||||
|
s = &devdir[strlen(devdir)-1];
|
||||||
|
while (s != NULL && count != (slashes+1)) {
|
||||||
|
s--;
|
||||||
|
if (*s == '/')
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
strncpy(s, d, (SYSFS_PATH_MAX-strlen(devdir)));
|
||||||
|
strncpy(target, devdir, len);
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
/* absolute path - copy as is */
|
||||||
|
strncpy(target, linkpath, len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* relative path from this directory */
|
||||||
|
strncpy(target, devdir, len);
|
||||||
|
s = strrchr(target, '/');
|
||||||
|
if (s != NULL) {
|
||||||
|
*(s+1) = '\0';
|
||||||
|
strcat(target, linkpath);
|
||||||
|
} else {
|
||||||
|
strcpy(target, linkpath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d--;
|
|
||||||
|
|
||||||
s = &devdir[strlen(devdir)-1];
|
|
||||||
while (s != NULL && count != (slashes+1)) {
|
|
||||||
s--;
|
|
||||||
if (*s == '/')
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(s, d, (SYSFS_PATH_MAX-strlen(devdir)));
|
|
||||||
strncpy(target, devdir, len);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sysfs_del_name: free function for sysfs_open_subsystem_list
|
* sysfs_del_name: free function for sysfs_open_subsystem_list
|
||||||
* @name: memory area to be freed
|
* @name: memory area to be freed
|
||||||
|
@ -245,8 +294,8 @@ struct dlist *sysfs_open_subsystem_list(unsigned char *name)
|
||||||
dprintf("Error getting sysfs mount point\n");
|
dprintf("Error getting sysfs mount point\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (sysfs_trailing_slash(sysfs_path) == 0)
|
|
||||||
strcat(sysfs_path, "/");
|
strcat(sysfs_path, "/");
|
||||||
strcat(sysfs_path, name);
|
strcat(sysfs_path, name);
|
||||||
dir = sysfs_open_directory(sysfs_path);
|
dir = sysfs_open_directory(sysfs_path);
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
|
@ -318,8 +367,7 @@ struct dlist *sysfs_open_bus_devices_list(unsigned char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sysfs_trailing_slash(sysfs_path) == 0)
|
strcat(sysfs_path, "/");
|
||||||
strcat(sysfs_path, "/");
|
|
||||||
strcat(sysfs_path, SYSFS_BUS_NAME);
|
strcat(sysfs_path, SYSFS_BUS_NAME);
|
||||||
strcat(sysfs_path, "/");
|
strcat(sysfs_path, "/");
|
||||||
strcat(sysfs_path, name);
|
strcat(sysfs_path, name);
|
||||||
|
@ -376,7 +424,7 @@ int sysfs_path_is_dir(const unsigned char *path)
|
||||||
}
|
}
|
||||||
if (S_ISDIR(astats.st_mode))
|
if (S_ISDIR(astats.st_mode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,7 +447,7 @@ int sysfs_path_is_link(const unsigned char *path)
|
||||||
}
|
}
|
||||||
if (S_ISLNK(astats.st_mode))
|
if (S_ISLNK(astats.st_mode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,6 +470,6 @@ int sysfs_path_is_file(const unsigned char *path)
|
||||||
}
|
}
|
||||||
if (S_ISREG(astats.st_mode))
|
if (S_ISREG(astats.st_mode))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
105
namedev.c
105
namedev.c
|
@ -29,6 +29,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -514,11 +515,8 @@ static struct sysfs_device *get_sysfs_device(struct sysfs_class_device *class_de
|
||||||
{
|
{
|
||||||
struct sysfs_device *sysfs_device;
|
struct sysfs_device *sysfs_device;
|
||||||
struct sysfs_class_device *class_dev_parent;
|
struct sysfs_class_device *class_dev_parent;
|
||||||
|
struct timespec tspec;
|
||||||
int loop;
|
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
|
/* 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.
|
* always be in the class_dev->path. But for block devices, it's different.
|
||||||
|
@ -529,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
|
* symlink yet. We do sit and spin on waiting for them right now, we should
|
||||||
* possibly have a whitelist for these devices here...
|
* possibly have a whitelist for these devices here...
|
||||||
*/
|
*/
|
||||||
strcpy(filename, class_dev->path);
|
class_dev_parent = sysfs_get_classdev_parent(class_dev);
|
||||||
dbg("filename = %s", filename);
|
if (class_dev_parent)
|
||||||
if (strcmp(class_dev->classname, SYSFS_BLOCK_NAME) == 0) {
|
dbg("Really a partition");
|
||||||
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;
|
tspec.tv_sec = 0;
|
||||||
|
tspec.tv_nsec = 10000000; /* sleep 10 millisec */
|
||||||
|
loop = 10;
|
||||||
while (loop--) {
|
while (loop--) {
|
||||||
struct stat buf;
|
nanosleep(&tspec, NULL);
|
||||||
dbg("looking for '%s'", filename);
|
if (class_dev_parent)
|
||||||
retval = stat(filename, &buf);
|
sysfs_device = sysfs_get_classdev_device(class_dev_parent);
|
||||||
if (!retval)
|
else
|
||||||
break;
|
sysfs_device = sysfs_get_classdev_device(class_dev);
|
||||||
/* 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)
|
if (sysfs_device != NULL)
|
||||||
goto exit;
|
goto device_found;
|
||||||
|
|
||||||
/* 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...");
|
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:
|
exit:
|
||||||
return sysfs_device;
|
return sysfs_device;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue