From f385ff6512012a75b8381938dd3f55f991b53e9a Mon Sep 17 00:00:00 2001 From: "kay.sievers@vrfy.org" Date: Wed, 23 Feb 2005 12:21:39 +0100 Subject: [PATCH] big libsysfs diet (pre 2.0 version) --- libsysfs/sysfs_dir.c | 1000 +++++++++++--------------------------------------- 1 file changed, 210 insertions(+), 790 deletions(-) (limited to 'libsysfs/sysfs_dir.c') diff --git a/libsysfs/sysfs_dir.c b/libsysfs/sysfs_dir.c index 52769916cc..c86617934b 100644 --- a/libsysfs/sysfs_dir.c +++ b/libsysfs/sysfs_dir.c @@ -3,7 +3,7 @@ * * Directory utility functions for libsysfs * - * Copyright (C) IBM Corp. 2003 + * Copyright (C) IBM Corp. 2003-2005 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,39 +23,38 @@ #include "libsysfs.h" #include "sysfs.h" -/** - * sysfs_del_attribute: routine for dlist integration - */ -static void sysfs_del_attribute(void *attr) +static int sort_char(void *new, void *old) { - sysfs_close_attribute((struct sysfs_attribute *)attr); + return ((strncmp((char *)new, (char *)old, + strlen((char *)new))) < 0 ? 1 : 0); } /** - * sysfs_del_link: routine for dlist integration + * sysfs_del_name: free function for sysfs_open_subsystem_list + * @name: memory area to be freed */ -static void sysfs_del_link(void *ln) +static void sysfs_del_name(void *name) { - sysfs_close_link((struct sysfs_link *)ln); + free(name); } /** - * sysfs_del_dir: routine for dlist integration + * sysfs_del_attribute: routine for dlist integration */ -static void sysfs_del_directory(void *dir) +static void sysfs_del_attribute(void *attr) { - sysfs_close_directory((struct sysfs_directory *)dir); + sysfs_close_attribute((struct sysfs_attribute *)attr); } /** - * dir_attribute_name_equal: compares dir attributes by name + * attr_name_equal: compares attributes by name * @a: attribute name for comparison * @b: sysfs_attribute to be compared. * returns 1 if a==b->name or 0 if not equal */ -static int dir_attribute_name_equal(void *a, void *b) +static int attr_name_equal(void *a, void *b) { - if (a == NULL || b == NULL) + if (!a || !b) return 0; if (strcmp(((char *)a), ((struct sysfs_attribute *)b)->name) == 0) @@ -64,48 +63,14 @@ static int dir_attribute_name_equal(void *a, void *b) return 0; } -/** - * dir_link_name_equal: compares dir links by name - * @a: link name for comparison - * @b: sysfs_link to be compared. - * returns 1 if a==b->name or 0 if not equal - */ -static int dir_link_name_equal(void *a, void *b) -{ - if (a == NULL || b == NULL) - return 0; - - if (strcmp(((char *)a), ((struct sysfs_link *)b)->name) == 0) - return 1; - - return 0; -} - -/** - * dir_subdir_name_equal: compares subdirs by name - * @a: name of subdirectory to compare - * @b: sysfs_directory subdirectory to be compared - * returns 1 if a==b->name or 0 if not equal - */ -static int dir_subdir_name_equal(void *a, void *b) -{ - if (a == NULL || b == NULL) - return 0; - - if (strcmp(((char *)a), ((struct sysfs_directory *)b)->name) == 0) - return 1; - - return 0; -} - /** * sysfs_close_attribute: closes and cleans up attribute * @sysattr: attribute to close. */ void sysfs_close_attribute(struct sysfs_attribute *sysattr) { - if (sysattr != NULL) { - if (sysattr->value != NULL) + if (sysattr) { + if (sysattr->value) free(sysattr->value); free(sysattr); } @@ -130,13 +95,13 @@ struct sysfs_attribute *sysfs_open_attribute(const char *path) { struct sysfs_attribute *sysattr = NULL; struct stat fileinfo; - - if (path == NULL) { + + if (!path) { errno = EINVAL; return NULL; } sysattr = alloc_attribute(); - if (sysattr == NULL) { + if (!sysattr) { dprintf("Error allocating attribute at %s\n", path); return NULL; } @@ -162,94 +127,6 @@ struct sysfs_attribute *sysfs_open_attribute(const char *path) return sysattr; } -/** - * sysfs_write_attribute: write value to the attribute - * @sysattr: attribute to write - * @new_value: value to write - * @len: length of "new_value" - * returns 0 with success and -1 with error. - */ -int sysfs_write_attribute(struct sysfs_attribute *sysattr, - const char *new_value, size_t len) -{ - int fd; - int length; - - if (sysattr == NULL || new_value == NULL || len == 0) { - errno = EINVAL; - return -1; - } - - if (!(sysattr->method & SYSFS_METHOD_STORE)) { - dprintf ("Store method not supported for attribute %s\n", - sysattr->path); - errno = EACCES; - return -1; - } - if (sysattr->method & SYSFS_METHOD_SHOW) { - /* - * read attribute again to see if we can get an updated value - */ - if ((sysfs_read_attribute(sysattr)) != 0) { - dprintf("Error reading attribute\n"); - return -1; - } - if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) { - dprintf("Attr %s already has the requested value %s\n", - sysattr->name, new_value); - return 0; - } - } - /* - * open O_WRONLY since some attributes have no "read" but only - * "write" permission - */ - if ((fd = open(sysattr->path, O_WRONLY)) < 0) { - dprintf("Error reading attribute %s\n", sysattr->path); - return -1; - } - - length = write(fd, new_value, len); - if (length < 0) { - dprintf("Error writing to the attribute %s - invalid value?\n", - sysattr->name); - close(fd); - return -1; - } else if ((unsigned int)length != len) { - dprintf("Could not write %d bytes to attribute %s\n", - len, sysattr->name); - /* - * since we could not write user supplied number of bytes, - * restore the old value if one available - */ - if (sysattr->method & SYSFS_METHOD_SHOW) { - length = write(fd, sysattr->value, sysattr->len); - close(fd); - return -1; - } - } - - /* - * Validate length that has been copied. Alloc appropriate area - * in sysfs_attribute. Verify first if the attribute supports reading - * (show method). If it does not, do not bother - */ - if (sysattr->method & SYSFS_METHOD_SHOW) { - if (length != sysattr->len) { - sysattr->value = (char *)realloc - (sysattr->value, length); - sysattr->len = length; - safestrcpymax(sysattr->value, new_value, length); - } else { - /*"length" of the new value is same as old one */ - safestrcpymax(sysattr->value, new_value, length); - } - } - - close(fd); - return 0; -} - /** * sysfs_read_attribute: reads value from attribute * @sysattr: attribute to read @@ -263,7 +140,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) long pgsize = 0; int fd; - if (sysattr == NULL) { + if (!sysattr) { errno = EINVAL; return -1; } @@ -275,7 +152,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) } pgsize = sysconf(_SC_PAGESIZE); fbuf = (char *)calloc(1, pgsize+1); - if (fbuf == NULL) { + if (!fbuf) { dprintf("calloc failed\n"); return -1; } @@ -303,7 +180,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) sysattr->len = length; close(fd); vbuf = (char *)realloc(fbuf, length+1); - if (vbuf == NULL) { + if (!vbuf) { dprintf("realloc failed\n"); free(fbuf); return -1; @@ -314,758 +191,301 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) } /** - * sysfs_read_attribute_value: given path to attribute, return its value. - * values can be up to a pagesize, if buffer is smaller the value will - * be truncated. - * @attrpath: sysfs path to attribute - * @value: buffer to put value - * @vsize: size of value buffer + * sysfs_write_attribute: write value to the attribute + * @sysattr: attribute to write + * @new_value: value to write + * @len: length of "new_value" * returns 0 with success and -1 with error. */ -int sysfs_read_attribute_value(const char *attrpath, - char *value, size_t vsize) +int sysfs_write_attribute(struct sysfs_attribute *sysattr, + const char *new_value, size_t len) { - struct sysfs_attribute *attr = NULL; - size_t length = 0; + int fd; + int length; - if (attrpath == NULL || value == NULL || vsize == 0) { + if (!sysattr || !new_value || len == 0) { errno = EINVAL; return -1; } - attr = sysfs_open_attribute(attrpath); - if (attr == NULL) { - dprintf("Invalid attribute path %s\n", attrpath); - errno = EINVAL; - return -1; - } - if((sysfs_read_attribute(attr)) != 0 || attr->value == NULL) { - dprintf("Error reading from attribute %s\n", attrpath); - sysfs_close_attribute(attr); + if (!(sysattr->method & SYSFS_METHOD_STORE)) { + dprintf ("Store method not supported for attribute %s\n", + sysattr->path); + errno = EACCES; return -1; } - length = strlen(attr->value); - if (length > vsize) - dprintf("Value length %d is larger than supplied buffer %d\n", - length, vsize); - safestrcpymax(value, attr->value, vsize); - sysfs_close_attribute(attr); - - return 0; -} - -/** - * sysfs_get_value_from_attrbutes: given a linked list of attributes and an - * attribute name, return its value - * @attr: attribute to search - * @name: name to look for - * returns char * value - could be NULL - */ -char *sysfs_get_value_from_attributes(struct dlist *attr, const char *name) -{ - struct sysfs_attribute *cur = NULL; - - if (attr == NULL || name == NULL) { - errno = EINVAL; - return NULL; - } - dlist_for_each_data(attr, cur, struct sysfs_attribute) { - if (strcmp(cur->name, name) == 0) - return cur->value; + if (sysattr->method & SYSFS_METHOD_SHOW) { + /* + * read attribute again to see if we can get an updated value + */ + if ((sysfs_read_attribute(sysattr))) { + dprintf("Error reading attribute\n"); + return -1; + } + if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) { + dprintf("Attr %s already has the requested value %s\n", + sysattr->name, new_value); + return 0; + } } - return NULL; -} - -/** - * sysfs_close_link: closes and cleans up link. - * @ln: link to close. - */ -void sysfs_close_link(struct sysfs_link *ln) -{ - if (ln != NULL) - free(ln); -} - -/** - * sysfs_close_directory: closes directory, cleans up attributes and links - * @sysdir: sysfs_directory to close - */ -void sysfs_close_directory(struct sysfs_directory *sysdir) -{ - if (sysdir != NULL) { - if (sysdir->subdirs != NULL) - dlist_destroy(sysdir->subdirs); - if (sysdir->links != NULL) - dlist_destroy(sysdir->links); - if (sysdir->attributes != NULL) - dlist_destroy(sysdir->attributes); - free(sysdir); - sysdir = NULL; + /* + * open O_WRONLY since some attributes have no "read" but only + * "write" permission + */ + if ((fd = open(sysattr->path, O_WRONLY)) < 0) { + dprintf("Error reading attribute %s\n", sysattr->path); + return -1; } -} - -/** - * alloc_directory: allocates and initializes directory structure - * returns struct sysfs_directory with success or NULL with error. - */ -static struct sysfs_directory *alloc_directory(void) -{ - return (struct sysfs_directory *) - calloc(1, sizeof(struct sysfs_directory)); -} - -/** - * alloc_link: allocates and initializes link structure - * returns struct sysfs_link with success or NULL with error. - */ -static struct sysfs_link *alloc_link(void) -{ - return (struct sysfs_link *)calloc(1, sizeof(struct sysfs_link)); -} - -/** - * sysfs_read_all_subdirs: calls sysfs_read_directory for all subdirs - * @sysdir: directory whose subdirs need reading. - * returns 0 with success and -1 with error. - */ -int sysfs_read_all_subdirs(struct sysfs_directory *sysdir) -{ - struct sysfs_directory *cursub = NULL; - int retval = 0; - if (sysdir == NULL) { - errno = EINVAL; + length = write(fd, new_value, len); + if (length < 0) { + dprintf("Error writing to the attribute %s - invalid value?\n", + sysattr->name); + close(fd); return -1; - } - if (sysdir->subdirs == NULL) - if ((sysfs_read_dir_subdirs(sysdir)) != 0) - return 0; - if (sysdir->subdirs != NULL) { - dlist_for_each_data(sysdir->subdirs, cursub, - struct sysfs_directory) { - if ((sysfs_read_dir_subdirs(cursub)) != 0) { - dprintf ("Error reading subdirectory %s\n", - cursub->name); - retval = -1; - } + } else if ((unsigned int)length != len) { + dprintf("Could not write %d bytes to attribute %s\n", + len, sysattr->name); + /* + * since we could not write user supplied number of bytes, + * restore the old value if one available + */ + if (sysattr->method & SYSFS_METHOD_SHOW) { + length = write(fd, sysattr->value, sysattr->len); + close(fd); + return -1; } } - if (!retval) - errno = 0; - return retval; -} -/** - * sysfs_open_directory: opens a sysfs directory, creates dir struct, and - * returns. - * @path: path of directory to open. - * returns: struct sysfs_directory * with success and NULL on error. - */ -struct sysfs_directory *sysfs_open_directory(const char *path) -{ - struct sysfs_directory *sdir = NULL; - - if (path == NULL) { - errno = EINVAL; - return NULL; - } - - if (sysfs_path_is_dir(path) != 0) { - dprintf("Invalid path to directory %s\n", path); - errno = EINVAL; - return NULL; - } - - sdir = alloc_directory(); - if (sdir == NULL) { - dprintf("Error allocating directory %s\n", path); - return NULL; - } - if (sysfs_get_name_from_path(path, sdir->name, SYSFS_NAME_LEN) != 0) { - dprintf("Error getting directory name from path: %s\n", path); - sysfs_close_directory(sdir); - return NULL; - } - safestrcpy(sdir->path, path); - - return sdir; -} - -/** - * sysfs_open_link: opens a sysfs link, creates struct, and returns - * @path: path of link to open. - * returns: struct sysfs_link * with success and NULL on error. - */ -struct sysfs_link *sysfs_open_link(const char *linkpath) -{ - struct sysfs_link *ln = NULL; - - if (linkpath == NULL || strlen(linkpath) > SYSFS_PATH_MAX) { - errno = EINVAL; - return NULL; - } - - ln = alloc_link(); - if (ln == NULL) { - dprintf("Error allocating link %s\n", linkpath); - return NULL; - } - safestrcpy(ln->path, linkpath); - if ((sysfs_get_name_from_path(linkpath, ln->name, SYSFS_NAME_LEN)) != 0 - || (sysfs_get_link(linkpath, ln->target, SYSFS_PATH_MAX)) != 0) { - sysfs_close_link(ln); - errno = EINVAL; - dprintf("Invalid link path %s\n", linkpath); - return NULL; + /* + * Validate length that has been copied. Alloc appropriate area + * in sysfs_attribute. Verify first if the attribute supports reading + * (show method). If it does not, do not bother + */ + if (sysattr->method & SYSFS_METHOD_SHOW) { + if (length != sysattr->len) { + sysattr->value = (char *)realloc + (sysattr->value, length); + sysattr->len = length; + safestrcpymax(sysattr->value, new_value, length); + } else { + /*"length" of the new value is same as old one */ + safestrcpymax(sysattr->value, new_value, length); + } } - - return ln; + + close(fd); + return 0; } /** * add_attribute: open and add attribute at path to given directory - * @sysdir: directory to add attribute to + * @dev: device whose attribute is to be added * @path: path to attribute - * returns 0 with success and -1 with error. + * returns pointer to attr added with success and NULL with error. */ -static int add_attribute(struct sysfs_directory *sysdir, const char *path) +static struct sysfs_attribute *add_attribute(void *dev, const char *path) { - struct sysfs_attribute *attr = NULL; + struct sysfs_attribute *attr; attr = sysfs_open_attribute(path); - if (attr == NULL) { + if (!attr) { dprintf("Error opening attribute %s\n", path); - return -1; + return NULL; } if (attr->method & SYSFS_METHOD_SHOW) { - if ((sysfs_read_attribute(attr)) != 0) { + if (sysfs_read_attribute(attr)) { dprintf("Error reading attribute %s\n", path); sysfs_close_attribute(attr); - return 0; + return NULL; } } - - if (sysdir->attributes == NULL) { - sysdir->attributes = dlist_new_with_delete - (sizeof(struct sysfs_attribute), sysfs_del_attribute); - } - dlist_unshift_sorted(sysdir->attributes, attr, sort_list); - - return 0; -} - -/** - * add_subdirectory: open and add subdirectory at path to given directory - * @sysdir: directory to add subdir to - * @path: path to subdirectory - * returns 0 with success and -1 with error. - */ -static int add_subdirectory(struct sysfs_directory *sysdir, const char *path) -{ - struct sysfs_directory *subdir = NULL; - subdir = sysfs_open_directory(path); - if (subdir == NULL) { - dprintf("Error opening directory %s\n", path); - return -1; + if (!((struct sysfs_device *)dev)->attrlist) { + ((struct sysfs_device *)dev)->attrlist = dlist_new_with_delete + (sizeof(struct sysfs_attribute), sysfs_del_attribute); } - if (sysdir->subdirs == NULL) - sysdir->subdirs = dlist_new_with_delete - (sizeof(struct sysfs_directory), sysfs_del_directory); - dlist_unshift_sorted(sysdir->subdirs, subdir, sort_list); - return 0; -} + dlist_unshift_sorted(((struct sysfs_device *)dev)->attrlist, + attr, sort_list); -/** - * add_link: open and add link at path to given directory - * @sysdir: directory to add link to - * @path: path to link - * returns 0 with success and -1 with error. - */ -static int add_link(struct sysfs_directory *sysdir, const char *path) -{ - struct sysfs_link *ln = NULL; - - ln = sysfs_open_link(path); - if (ln == NULL) { - dprintf("Error opening link %s\n", path); - return -1; - } - if (sysdir->links == NULL) - sysdir->links = dlist_new_with_delete - (sizeof(struct sysfs_link), sysfs_del_link); - dlist_unshift_sorted(sysdir->links, ln, sort_list); - return 0; + return attr; } -/** - * sysfs_read_dir_attributes: grabs attributes for the given directory - * @sysdir: sysfs directory to open - * returns 0 with success and -1 with error. +/* + * get_attribute - given a sysfs_* struct and a name, return the + * sysfs_attribute corresponding to "name" + * returns sysfs_attribute on success and NULL on error */ -int sysfs_read_dir_attributes(struct sysfs_directory *sysdir) +struct sysfs_attribute *get_attribute(void *dev, const char *name) { - DIR *dir = NULL; - struct dirent *dirent = NULL; - char file_path[SYSFS_PATH_MAX]; - int retval = 0; + struct sysfs_attribute *cur = NULL; + char path[SYSFS_PATH_MAX]; - if (sysdir == NULL) { + if (!dev || !name) { errno = EINVAL; - return -1; - } - dir = opendir(sysdir->path); - if (dir == NULL) { - dprintf("Error opening directory %s\n", sysdir->path); - return -1; + return NULL; } - while(((dirent = readdir(dir)) != NULL) && retval == 0) { - if (0 == strcmp(dirent->d_name, ".")) - continue; - if (0 == strcmp(dirent->d_name, "..")) - continue; - memset(file_path, 0, SYSFS_PATH_MAX); - safestrcpy(file_path, sysdir->path); - safestrcat(file_path, "/"); - safestrcat(file_path, dirent->d_name); - if ((sysfs_path_is_file(file_path)) == 0) - retval = add_attribute(sysdir, file_path); + + if (((struct sysfs_device *)dev)->attrlist) { + /* check if attr is already in the list */ + cur = (struct sysfs_attribute *)dlist_find_custom + ((((struct sysfs_device *)dev)->attrlist), + (void *)name, attr_name_equal); + if (cur) + return cur; } - closedir(dir); - if (!retval) - errno = 0; - return(retval); + safestrcpymax(path, ((struct sysfs_device *)dev)->path, + SYSFS_PATH_MAX); + safestrcatmax(path, "/", SYSFS_PATH_MAX); + safestrcatmax(path, name, SYSFS_PATH_MAX); + if (!(sysfs_path_is_file(path))) + cur = add_attribute((void *)dev, path); + return cur; } /** - * sysfs_read_dir_links: grabs links in a specific directory - * @sysdir: sysfs directory to read links - * returns 0 with success and -1 with error. + * read_dir_links: grabs links in a specific directory + * @sysdir: sysfs directory to read + * returns list of link names with success and NULL with error. */ -int sysfs_read_dir_links(struct sysfs_directory *sysdir) +struct dlist *read_dir_links(const char *path) { DIR *dir = NULL; struct dirent *dirent = NULL; - char file_path[SYSFS_PATH_MAX]; - int retval = 0; + char file_path[SYSFS_PATH_MAX], *linkname; + struct dlist *linklist = NULL; - if (sysdir == NULL) { + if (!path) { errno = EINVAL; - return -1; + return NULL; } - dir = opendir(sysdir->path); - if (dir == NULL) { - dprintf("Error opening directory %s\n", sysdir->path); - return -1; + dir = opendir(path); + if (!dir) { + dprintf("Error opening directory %s\n", path); + return NULL; } - while(((dirent = readdir(dir)) != NULL) && retval == 0) { + while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); - safestrcpy(file_path, sysdir->path); + safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); if ((sysfs_path_is_link(file_path)) == 0) { - retval = add_link(sysdir, file_path); - if (retval != 0) - break; + if (!linklist) { + linklist = dlist_new_with_delete + (SYSFS_NAME_LEN, sysfs_del_name); + if (!linklist) { + dprintf("Error creating list\n"); + return NULL; + } + } + linkname = (char *)calloc(1, SYSFS_NAME_LEN); + safestrcpymax(linkname, dirent->d_name, SYSFS_NAME_LEN); + dlist_unshift_sorted(linklist, linkname, sort_char); } } closedir(dir); - if (!retval) - errno = 0; - return(retval); + return linklist; } /** - * sysfs_read_dir_subdirs: grabs subdirs in a specific directory - * @sysdir: sysfs directory to read links - * returns 0 with success and -1 with error. + * read_dir_subdirs: grabs subdirs in a specific directory + * @sysdir: sysfs directory to read + * returns list of directory names with success and NULL with error. */ -int sysfs_read_dir_subdirs(struct sysfs_directory *sysdir) +struct dlist *read_dir_subdirs(const char *path) { DIR *dir = NULL; struct dirent *dirent = NULL; - char file_path[SYSFS_PATH_MAX]; - int retval = 0; + char file_path[SYSFS_PATH_MAX], *dir_name; + struct dlist *dirlist = NULL; - if (sysdir == NULL) { + if (!path) { errno = EINVAL; - return -1; + return NULL; } - dir = opendir(sysdir->path); - if (dir == NULL) { - dprintf("Error opening directory %s\n", sysdir->path); - return -1; + dir = opendir(path); + if (!dir) { + dprintf("Error opening directory %s\n", path); + return NULL; } - while(((dirent = readdir(dir)) != NULL) && retval == 0) { + while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); - safestrcpy(file_path, sysdir->path); + safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); - if ((sysfs_path_is_dir(file_path)) == 0) - retval = add_subdirectory(sysdir, file_path); + if ((sysfs_path_is_dir(file_path)) == 0) { + if (!dirlist) { + dirlist = dlist_new_with_delete + (SYSFS_NAME_LEN, sysfs_del_name); + if (!dirlist) { + dprintf("Error creating list\n"); + return NULL; + } + } + dir_name = (char *)calloc(1, SYSFS_NAME_LEN); + safestrcpymax(dir_name, dirent->d_name, SYSFS_NAME_LEN); + dlist_unshift_sorted(dirlist, dir_name, sort_char); + } } closedir(dir); - if (!retval) - errno = 0; - return(retval); + return dirlist; } /** - * sysfs_read_directory: grabs attributes, links, and subdirectories - * @sysdir: sysfs directory to open - * returns 0 with success and -1 with error. + * get_attributes_list: build a list of attributes for the given device + * @dev: devices whose attributes list is required + * returns dlist of attributes on success and NULL on failure */ -int sysfs_read_directory(struct sysfs_directory *sysdir) +struct dlist *get_attributes_list(void *dev) { DIR *dir = NULL; struct dirent *dirent = NULL; - struct stat astats; - char file_path[SYSFS_PATH_MAX]; - int retval = 0; + struct sysfs_attribute *attr = NULL; + char file_path[SYSFS_PATH_MAX], path[SYSFS_PATH_MAX]; - if (sysdir == NULL) { + if (!dev) { errno = EINVAL; - return -1; + return NULL; } - dir = opendir(sysdir->path); - if (dir == NULL) { - dprintf("Error opening directory %s\n", sysdir->path); - return -1; + memset(path, 0, SYSFS_PATH_MAX); + safestrcpy(path, ((struct sysfs_device *)dev)->path); + dir = opendir(path); + if (!dir) { + dprintf("Error opening directory %s\n", path); + return NULL; } - while(((dirent = readdir(dir)) != NULL) && retval == 0) { + while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); - safestrcpy(file_path, sysdir->path); + safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); - if ((lstat(file_path, &astats)) != 0) { - dprintf("stat failed\n"); - continue; - } - if (S_ISDIR(astats.st_mode)) - retval = add_subdirectory(sysdir, file_path); - - else if (S_ISLNK(astats.st_mode)) - retval = add_link(sysdir, file_path); - - else if (S_ISREG(astats.st_mode)) - retval = add_attribute(sysdir, file_path); - } - closedir(dir); - if (!retval) - errno = 0; - 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; - } - errno = 0; - 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; - } - errno = 0; - 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; - } - errno = 0; - return 0; -} - -/** - * sysfs_get_directory_attribute: retrieves attribute attrname from current - * directory only - * @dir: directory to retrieve attribute from - * @attrname: name of attribute to look for - * - * NOTE: Since we know the attribute to look for, this routine looks for the - * attribute if it was created _after_ the attrlist was read initially. - * - * returns sysfs_attribute if found and NULL if not found - */ -struct sysfs_attribute *sysfs_get_directory_attribute - (struct sysfs_directory *dir, char *attrname) -{ - struct sysfs_attribute *attr = NULL; - char new_path[SYSFS_PATH_MAX]; - - if (dir == NULL || attrname == NULL) { - errno = EINVAL; - return NULL; - } - - if (dir->attributes == NULL) - if ((sysfs_read_dir_attributes(dir) != 0) - || (dir->attributes == NULL)) - return NULL; - - attr = (struct sysfs_attribute *)dlist_find_custom - (dir->attributes, attrname, dir_attribute_name_equal); - if (attr != NULL) { - if ((attr->method & SYSFS_METHOD_SHOW) && - (sysfs_read_attribute(attr)) != 0) { - dprintf("Error reading attribute %s\n", attr->name); - return NULL; - } - } else { - memset(new_path, 0, SYSFS_PATH_MAX); - safestrcpy(new_path, dir->path); - safestrcat(new_path, "/"); - safestrcat(new_path, attrname); - if ((sysfs_path_is_file(new_path)) == 0) { - if ((add_attribute(dir, new_path)) == 0) { + if ((sysfs_path_is_file(file_path)) == 0) { + if (((struct sysfs_device *)dev)->attrlist) { + /* check if attr is already in the list */ attr = (struct sysfs_attribute *) - dlist_find_custom(dir->attributes, - attrname, dir_attribute_name_equal); - } - } - } - - return attr; -} - -/** - * sysfs_get_directory_link: retrieves link from one directory list - * @dir: directory to retrieve link from - * @linkname: name of link to look for - * returns reference to sysfs_link if found and NULL if not found - */ -struct sysfs_link *sysfs_get_directory_link - (struct sysfs_directory *dir, char *linkname) -{ - if (dir == NULL || linkname == NULL) { - errno = EINVAL; - return NULL; - } - if (dir->links == NULL) { - if ((sysfs_read_dir_links(dir) != 0) || (dir->links == NULL)) - return NULL; - } else { - if ((sysfs_refresh_dir_links(dir)) != 0) - return NULL; - } - - return (struct sysfs_link *)dlist_find_custom(dir->links, - linkname, dir_link_name_equal); -} - -/** - * sysfs_get_subdirectory: retrieves subdirectory by name. - * @dir: directory to search for subdirectory. - * @subname: subdirectory name to get. - * returns reference to subdirectory or NULL if not found - */ -struct sysfs_directory *sysfs_get_subdirectory(struct sysfs_directory *dir, - char *subname) -{ - struct sysfs_directory *sub = NULL, *cursub = NULL; - - if (dir == NULL || subname == NULL) { - errno = EINVAL; - return NULL; - } - - if (dir->subdirs == NULL) - if (sysfs_read_dir_subdirs(dir) != 0) - return NULL; - - sub = (struct sysfs_directory *)dlist_find_custom(dir->subdirs, - subname, dir_subdir_name_equal); - if (sub != NULL) - return sub; - - if (dir->subdirs != NULL) { - dlist_for_each_data(dir->subdirs, cursub, - struct sysfs_directory) { - if (cursub->subdirs == NULL) { - if (sysfs_read_dir_subdirs(cursub) != 0) - continue; - if (cursub->subdirs == NULL) + dlist_find_custom + ((((struct sysfs_device *)dev)->attrlist), + (void *)dirent->d_name, attr_name_equal); + if (attr) continue; - } - sub = sysfs_get_subdirectory(cursub, subname); - if (sub != NULL) - return sub; - } - } - return NULL; -} - -/** - * sysfs_get_subdirectory_link: looks through all subdirs for specific link. - * @dir: directory and subdirectories to search for link. - * @linkname: link name to get. - * returns reference to link or NULL if not found - */ -struct sysfs_link *sysfs_get_subdirectory_link(struct sysfs_directory *dir, - char *linkname) -{ - struct sysfs_directory *cursub = NULL; - struct sysfs_link *ln = NULL; - - if (dir == NULL || linkname == NULL) { - errno = EINVAL; - return NULL; - } - - ln = sysfs_get_directory_link(dir, linkname); - if (ln != NULL) - return ln; - - if (dir->subdirs == NULL) - if (sysfs_read_dir_subdirs(dir) != 0) - return NULL; - - if (dir->subdirs != NULL) { - dlist_for_each_data(dir->subdirs, cursub, - struct sysfs_directory) { - ln = sysfs_get_subdirectory_link(cursub, linkname); - if (ln != NULL) - return ln; + else + add_attribute(dev, file_path); + } else + attr = add_attribute(dev, file_path); } } - 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); + closedir(dir); + return ((struct sysfs_device *)dev)->attrlist; } -- cgit v1.2.3-54-g00ecf