2003-07-19 07:08:00 +04:00
/*
2003-12-20 05:29:10 +03:00
* sysfs_dir . c
2003-07-19 07:08:00 +04:00
*
* Directory utility functions for libsysfs
*
2003-10-21 12:19:14 +04:00
* Copyright ( C ) IBM Corp . 2003
2003-07-19 07:08:00 +04:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
2004-10-20 15:15:26 +04:00
# include "libsysfs.h"
2003-07-19 07:08:00 +04:00
# include "sysfs.h"
2003-10-21 12:19:14 +04:00
/**
* sysfs_del_attribute : routine for dlist integration
*/
static void sysfs_del_attribute ( void * attr )
{
sysfs_close_attribute ( ( struct sysfs_attribute * ) attr ) ;
}
/**
* sysfs_del_link : routine for dlist integration
*/
static void sysfs_del_link ( void * ln )
{
sysfs_close_link ( ( struct sysfs_link * ) ln ) ;
}
/**
* sysfs_del_dir : routine for dlist integration
*/
static void sysfs_del_directory ( void * dir )
{
sysfs_close_directory ( ( struct sysfs_directory * ) dir ) ;
}
/**
* dir_attribute_name_equal : compares dir 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 )
{
if ( a = = NULL | | b = = NULL )
return 0 ;
2004-03-12 11:57:30 +03:00
if ( strcmp ( ( ( char * ) a ) , ( ( struct sysfs_attribute * ) b ) - > name ) = = 0 )
2003-10-21 12:19:14 +04:00
return 1 ;
2004-03-12 11:57:30 +03:00
2003-10-21 12:19:14 +04:00
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 ;
2004-03-12 11:57:30 +03:00
if ( strcmp ( ( ( char * ) a ) , ( ( struct sysfs_link * ) b ) - > name ) = = 0 )
2003-10-21 12:19:14 +04:00
return 1 ;
2004-03-12 11:57:30 +03:00
2003-10-21 12:19:14 +04:00
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 ;
2004-03-12 11:57:30 +03:00
if ( strcmp ( ( ( char * ) a ) , ( ( struct sysfs_directory * ) b ) - > name ) = = 0 )
2003-10-21 12:19:14 +04:00
return 1 ;
2004-03-12 11:57:30 +03:00
2003-10-21 12:19:14 +04:00
return 0 ;
}
2003-07-19 07:08:00 +04:00
/**
* 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 )
free ( sysattr - > value ) ;
free ( sysattr ) ;
}
}
/**
* alloc_attribute : allocates and initializes attribute structure
* returns struct sysfs_attribute with success and NULL with error .
*/
static struct sysfs_attribute * alloc_attribute ( void )
{
return ( struct sysfs_attribute * )
calloc ( 1 , sizeof ( struct sysfs_attribute ) ) ;
}
/**
* sysfs_open_attribute : creates sysfs_attribute structure
* @ path : path to attribute .
* returns sysfs_attribute struct with success and NULL with error .
*/
2004-03-12 11:57:30 +03:00
struct sysfs_attribute * sysfs_open_attribute ( const char * path )
2003-07-19 07:08:00 +04:00
{
struct sysfs_attribute * sysattr = NULL ;
struct stat fileinfo ;
if ( path = = NULL ) {
errno = EINVAL ;
return NULL ;
}
sysattr = alloc_attribute ( ) ;
if ( sysattr = = NULL ) {
2003-10-21 12:19:14 +04:00
dprintf ( " Error allocating attribute at %s \n " , path ) ;
return NULL ;
}
2004-03-12 11:57:30 +03:00
if ( sysfs_get_name_from_path ( path , sysattr - > name ,
SYSFS_NAME_LEN ) ! = 0 ) {
dprintf ( " Error retrieving attrib name from path: %s \n " , path ) ;
2003-10-21 12:19:14 +04:00
sysfs_close_attribute ( sysattr ) ;
2003-07-19 07:08:00 +04:00
return NULL ;
}
2004-03-12 11:57:30 +03:00
safestrcpy ( sysattr - > path , path ) ;
2003-07-19 07:08:00 +04:00
if ( ( stat ( sysattr - > path , & fileinfo ) ) ! = 0 ) {
2003-10-21 12:19:14 +04:00
dprintf ( " Stat failed: No such attribute? \n " ) ;
2003-07-19 07:08:00 +04:00
sysattr - > method = 0 ;
2003-10-21 12:19:14 +04:00
free ( sysattr ) ;
sysattr = NULL ;
2003-07-19 07:08:00 +04:00
} else {
if ( fileinfo . st_mode & S_IRUSR )
sysattr - > method | = SYSFS_METHOD_SHOW ;
if ( fileinfo . st_mode & S_IWUSR )
sysattr - > method | = SYSFS_METHOD_STORE ;
}
return sysattr ;
}
2003-10-21 12:19:14 +04:00
/**
* 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 ,
2004-03-12 11:57:30 +03:00
const char * new_value , size_t len )
2003-10-21 12:19:14 +04:00
{
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 ) ;
2004-03-12 11:57:30 +03:00
errno = EACCES ;
2003-10-21 12:19:14 +04:00
return - 1 ;
}
if ( sysattr - > method & SYSFS_METHOD_SHOW ) {
2003-12-16 08:53:28 +03:00
/*
* 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 ;
}
2003-10-21 12:19:14 +04:00
if ( ( strncmp ( sysattr - > value , new_value , sysattr - > len ) ) = = 0 ) {
2004-01-15 09:21:38 +03:00
dprintf ( " Attr %s already has the requested value %s \n " ,
2003-10-21 12:19:14 +04:00
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 ;
2004-03-12 11:57:30 +03:00
} else if ( ( unsigned int ) length ! = len ) {
2003-10-21 12:19:14 +04:00
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 ) {
2004-03-12 11:57:30 +03:00
sysattr - > value = ( char * ) realloc
( sysattr - > value , length ) ;
2003-10-21 12:19:14 +04:00
sysattr - > len = length ;
[PATCH] more Libsysfs updates
On Thu, Mar 11, 2004 at 02:36:23PM +0100, Kay Sievers wrote:
> On Thu, 2004-03-11 at 15:02, Ananth N Mavinakayanahalli wrote:
> > On Thu, Mar 11, 2004 at 02:04:36PM +0100, Kay Sievers wrote:
> > > On Thu, Mar 11, 2004 at 11:53:50AM +0500, Ananth N Mavinakayanahalli wrote:
> > >
> > > > +#define safestrcpy(to, from) strncpy(to, from, sizeof(to)-1)
> > > > +#define safestrcat(to, from) strncat(to, from, sizeof(to) - strlen(to)-1)
> > >
> > > These strings are not terminated with '\0' if from is longer than
> > > the sizeof to.
> >
> > Did not do it on purpose as the "to" elements are either calloc'd or memset to
> > '0' explicitly in the library. Thats the reason I mentioned "scaled down" :)
>
> Ahh, sounds good.
>
> > > > +#define safestrncpy(to, from, maxsize) \
> > > > +do { \
> > > > + to[maxsize-1] = '\0'; \
> > > > + strncpy(to, from, maxsize-1); \
> > > > +} while (0)
> > > > +
> > > > +#define safestrncat(to, from, maxsize) \
> > > > +do { \
> > > > + to[maxsize-1] = '\0'; \
> > > > + strncat(to, from, maxsize - strlen(to)-1); \
> > > > +} while (0)
> > >
> > > We all expect a similar behavior like strncat/strncpy according to the
> > > names, but these macros are limiting by the target size and do not limit
> > > the count of chars copied.
> > > This is confusing I think and suggest using a different name like
> > > 'safestrcopymax()' or something.
> >
> > Good point.. will make the change
>
> Nice. I've had these *n* names too and I forgot about the logic and only
> 10 days later I introduced a ugly bug cause I can't limit the count of
> copied chars :)
Inlined is the patch for this... applies on the earlier _BIG_ patch.
2004-03-12 11:57:36 +03:00
safestrcpymax ( sysattr - > value , new_value , length ) ;
2003-10-21 12:19:14 +04:00
} else {
/*"length" of the new value is same as old one */
[PATCH] more Libsysfs updates
On Thu, Mar 11, 2004 at 02:36:23PM +0100, Kay Sievers wrote:
> On Thu, 2004-03-11 at 15:02, Ananth N Mavinakayanahalli wrote:
> > On Thu, Mar 11, 2004 at 02:04:36PM +0100, Kay Sievers wrote:
> > > On Thu, Mar 11, 2004 at 11:53:50AM +0500, Ananth N Mavinakayanahalli wrote:
> > >
> > > > +#define safestrcpy(to, from) strncpy(to, from, sizeof(to)-1)
> > > > +#define safestrcat(to, from) strncat(to, from, sizeof(to) - strlen(to)-1)
> > >
> > > These strings are not terminated with '\0' if from is longer than
> > > the sizeof to.
> >
> > Did not do it on purpose as the "to" elements are either calloc'd or memset to
> > '0' explicitly in the library. Thats the reason I mentioned "scaled down" :)
>
> Ahh, sounds good.
>
> > > > +#define safestrncpy(to, from, maxsize) \
> > > > +do { \
> > > > + to[maxsize-1] = '\0'; \
> > > > + strncpy(to, from, maxsize-1); \
> > > > +} while (0)
> > > > +
> > > > +#define safestrncat(to, from, maxsize) \
> > > > +do { \
> > > > + to[maxsize-1] = '\0'; \
> > > > + strncat(to, from, maxsize - strlen(to)-1); \
> > > > +} while (0)
> > >
> > > We all expect a similar behavior like strncat/strncpy according to the
> > > names, but these macros are limiting by the target size and do not limit
> > > the count of chars copied.
> > > This is confusing I think and suggest using a different name like
> > > 'safestrcopymax()' or something.
> >
> > Good point.. will make the change
>
> Nice. I've had these *n* names too and I forgot about the logic and only
> 10 days later I introduced a ugly bug cause I can't limit the count of
> copied chars :)
Inlined is the patch for this... applies on the earlier _BIG_ patch.
2004-03-12 11:57:36 +03:00
safestrcpymax ( sysattr - > value , new_value , length ) ;
2003-10-21 12:19:14 +04:00
}
}
close ( fd ) ;
return 0 ;
}
2003-07-19 07:08:00 +04:00
/**
* sysfs_read_attribute : reads value from attribute
* @ sysattr : attribute to read
* returns 0 with success and - 1 with error .
*/
int sysfs_read_attribute ( struct sysfs_attribute * sysattr )
{
2004-03-12 11:57:30 +03:00
char * fbuf = NULL ;
char * vbuf = NULL ;
2003-12-20 05:29:10 +03:00
ssize_t length = 0 ;
2003-12-16 08:53:28 +03:00
long pgsize = 0 ;
2003-07-19 07:08:00 +04:00
int fd ;
if ( sysattr = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
if ( ! ( sysattr - > method & SYSFS_METHOD_SHOW ) ) {
2003-10-21 12:19:14 +04:00
dprintf ( " Show method not supported for attribute %s \n " ,
2003-07-19 07:08:00 +04:00
sysattr - > path ) ;
2004-03-12 11:57:30 +03:00
errno = EACCES ;
2003-07-19 07:08:00 +04:00
return - 1 ;
}
2004-10-20 15:15:26 +04:00
pgsize = sysconf ( _SC_PAGESIZE ) ;
2004-03-12 11:57:30 +03:00
fbuf = ( char * ) calloc ( 1 , pgsize + 1 ) ;
2003-07-19 07:08:00 +04:00
if ( fbuf = = NULL ) {
2003-10-21 12:19:14 +04:00
dprintf ( " calloc failed \n " ) ;
2003-07-19 07:08:00 +04:00
return - 1 ;
}
if ( ( fd = open ( sysattr - > path , O_RDONLY ) ) < 0 ) {
2003-10-21 12:19:14 +04:00
dprintf ( " Error reading attribute %s \n " , sysattr - > path ) ;
2003-07-19 07:08:00 +04:00
free ( fbuf ) ;
return - 1 ;
}
length = read ( fd , fbuf , pgsize ) ;
if ( length < 0 ) {
2003-10-21 12:19:14 +04:00
dprintf ( " Error reading from attribute %s \n " , sysattr - > path ) ;
2003-07-19 07:08:00 +04:00
close ( fd ) ;
free ( fbuf ) ;
return - 1 ;
}
2003-12-16 08:53:28 +03:00
if ( sysattr - > len > 0 ) {
if ( ( sysattr - > len = = length ) & &
( ! ( strncmp ( sysattr - > value , fbuf , length ) ) ) ) {
close ( fd ) ;
2004-03-12 11:57:30 +03:00
free ( fbuf ) ;
2003-12-16 08:53:28 +03:00
return 0 ;
}
free ( sysattr - > value ) ;
}
2003-07-19 07:08:00 +04:00
sysattr - > len = length ;
close ( fd ) ;
2004-03-12 11:57:30 +03:00
vbuf = ( char * ) realloc ( fbuf , length + 1 ) ;
2003-07-19 07:08:00 +04:00
if ( vbuf = = NULL ) {
2003-10-21 12:19:14 +04:00
dprintf ( " realloc failed \n " ) ;
2003-07-19 07:08:00 +04:00
free ( fbuf ) ;
return - 1 ;
}
sysattr - > value = vbuf ;
return 0 ;
}
/**
* 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
* returns 0 with success and - 1 with error .
*/
2004-03-12 11:57:30 +03:00
int sysfs_read_attribute_value ( const char * attrpath ,
char * value , size_t vsize )
2003-07-19 07:08:00 +04:00
{
struct sysfs_attribute * attr = NULL ;
size_t length = 0 ;
2004-03-12 11:57:30 +03:00
if ( attrpath = = NULL | | value = = NULL | | vsize = = 0 ) {
2003-07-19 07:08:00 +04:00
errno = EINVAL ;
return - 1 ;
}
attr = sysfs_open_attribute ( attrpath ) ;
if ( attr = = NULL ) {
2003-10-21 12:19:14 +04:00
dprintf ( " Invalid attribute path %s \n " , attrpath ) ;
2003-07-19 07:08:00 +04:00
errno = EINVAL ;
return - 1 ;
}
if ( ( sysfs_read_attribute ( attr ) ) ! = 0 | | attr - > value = = NULL ) {
2003-10-21 12:19:14 +04:00
dprintf ( " Error reading from attribute %s \n " , attrpath ) ;
2003-07-19 07:08:00 +04:00
sysfs_close_attribute ( attr ) ;
return - 1 ;
}
length = strlen ( attr - > value ) ;
if ( length > vsize )
2003-10-21 12:19:14 +04:00
dprintf ( " Value length %d is larger than supplied buffer %d \n " ,
2003-07-19 07:08:00 +04:00
length , vsize ) ;
[PATCH] more Libsysfs updates
On Thu, Mar 11, 2004 at 02:36:23PM +0100, Kay Sievers wrote:
> On Thu, 2004-03-11 at 15:02, Ananth N Mavinakayanahalli wrote:
> > On Thu, Mar 11, 2004 at 02:04:36PM +0100, Kay Sievers wrote:
> > > On Thu, Mar 11, 2004 at 11:53:50AM +0500, Ananth N Mavinakayanahalli wrote:
> > >
> > > > +#define safestrcpy(to, from) strncpy(to, from, sizeof(to)-1)
> > > > +#define safestrcat(to, from) strncat(to, from, sizeof(to) - strlen(to)-1)
> > >
> > > These strings are not terminated with '\0' if from is longer than
> > > the sizeof to.
> >
> > Did not do it on purpose as the "to" elements are either calloc'd or memset to
> > '0' explicitly in the library. Thats the reason I mentioned "scaled down" :)
>
> Ahh, sounds good.
>
> > > > +#define safestrncpy(to, from, maxsize) \
> > > > +do { \
> > > > + to[maxsize-1] = '\0'; \
> > > > + strncpy(to, from, maxsize-1); \
> > > > +} while (0)
> > > > +
> > > > +#define safestrncat(to, from, maxsize) \
> > > > +do { \
> > > > + to[maxsize-1] = '\0'; \
> > > > + strncat(to, from, maxsize - strlen(to)-1); \
> > > > +} while (0)
> > >
> > > We all expect a similar behavior like strncat/strncpy according to the
> > > names, but these macros are limiting by the target size and do not limit
> > > the count of chars copied.
> > > This is confusing I think and suggest using a different name like
> > > 'safestrcopymax()' or something.
> >
> > Good point.. will make the change
>
> Nice. I've had these *n* names too and I forgot about the logic and only
> 10 days later I introduced a ugly bug cause I can't limit the count of
> copied chars :)
Inlined is the patch for this... applies on the earlier _BIG_ patch.
2004-03-12 11:57:36 +03:00
safestrcpymax ( value , attr - > value , vsize ) ;
2003-07-19 07:08:00 +04:00
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
2004-03-12 11:57:30 +03:00
* returns char * value - could be NULL
2003-07-19 07:08:00 +04:00
*/
2004-03-12 11:57:30 +03:00
char * sysfs_get_value_from_attributes ( struct dlist * attr , const char * name )
2003-07-19 07:08:00 +04:00
{
struct sysfs_attribute * cur = NULL ;
if ( attr = = NULL | | name = = NULL ) {
errno = EINVAL ;
return NULL ;
2003-10-21 12:19:14 +04:00
}
dlist_for_each_data ( attr , cur , struct sysfs_attribute ) {
if ( strcmp ( cur - > name , name ) = = 0 )
2003-07-19 07:08:00 +04:00
return cur - > value ;
}
return NULL ;
}
/**
2003-10-21 12:19:14 +04:00
* sysfs_close_link : closes and cleans up link .
* @ ln : link to close .
2003-07-19 07:08:00 +04:00
*/
2003-10-21 12:19:14 +04:00
void sysfs_close_link ( struct sysfs_link * ln )
2003-07-19 07:08:00 +04:00
{
2003-10-21 12:19:14 +04:00
if ( ln ! = NULL )
free ( ln ) ;
2003-07-19 07:08:00 +04:00
}
/**
* 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 ) {
2003-10-21 12:19:14 +04:00
if ( sysdir - > subdirs ! = NULL )
dlist_destroy ( sysdir - > subdirs ) ;
if ( sysdir - > links ! = NULL )
dlist_destroy ( sysdir - > links ) ;
if ( sysdir - > attributes ! = NULL )
dlist_destroy ( sysdir - > attributes ) ;
2003-07-19 07:08:00 +04:00
free ( sysdir ) ;
2003-12-16 08:53:28 +03:00
sysdir = NULL ;
2003-07-19 07:08:00 +04:00
}
}
/**
* 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 ) ) ;
}
/**
2003-10-21 12:19:14 +04:00
* 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 .
2003-07-19 07:08:00 +04:00
*/
2003-10-21 12:19:14 +04:00
int sysfs_read_all_subdirs ( struct sysfs_directory * sysdir )
2003-07-19 07:08:00 +04:00
{
2003-10-21 12:19:14 +04:00
struct sysfs_directory * cursub = NULL ;
2004-03-12 11:57:30 +03:00
int retval = 0 ;
2003-10-21 12:19:14 +04:00
if ( sysdir = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
2003-12-16 08:53:28 +03:00
if ( sysdir - > subdirs = = NULL )
2003-12-20 05:29:10 +03:00
if ( ( sysfs_read_dir_subdirs ( sysdir ) ) ! = 0 )
2003-12-16 08:53:28 +03:00
return 0 ;
2003-12-20 05:29:10 +03:00
if ( sysdir - > subdirs ! = NULL ) {
dlist_for_each_data ( sysdir - > subdirs , cursub ,
struct sysfs_directory ) {
2004-03-12 11:57:30 +03:00
if ( ( sysfs_read_dir_subdirs ( cursub ) ) ! = 0 ) {
2003-12-20 05:29:10 +03:00
dprintf ( " Error reading subdirectory %s \n " ,
cursub - > name ) ;
2004-03-12 11:57:30 +03:00
retval = - 1 ;
}
2003-12-20 05:29:10 +03:00
}
2003-10-21 12:19:14 +04:00
}
2004-03-12 11:57:30 +03:00
if ( ! retval )
errno = 0 ;
return retval ;
2003-07-19 07:08:00 +04:00
}
/**
* 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 .
*/
2004-03-12 11:57:30 +03:00
struct sysfs_directory * sysfs_open_directory ( const char * path )
2003-07-19 07:08:00 +04:00
{
struct sysfs_directory * sdir = NULL ;
if ( path = = NULL ) {
errno = EINVAL ;
return NULL ;
}
2004-01-15 09:21:38 +03:00
if ( sysfs_path_is_dir ( path ) ! = 0 ) {
2004-03-12 11:57:30 +03:00
dprintf ( " Invalid path to directory %s \n " , path ) ;
2004-01-15 09:21:38 +03:00
errno = EINVAL ;
return NULL ;
}
2003-07-19 07:08:00 +04:00
sdir = alloc_directory ( ) ;
if ( sdir = = NULL ) {
2003-10-21 12:19:14 +04:00
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 ) ;
2003-07-19 07:08:00 +04:00
return NULL ;
}
2004-03-12 11:57:30 +03:00
safestrcpy ( sdir - > path , path ) ;
2003-07-19 07:08:00 +04:00
return sdir ;
}
/**
2003-10-21 12:19:14 +04:00
* sysfs_open_link : opens a sysfs link , creates struct , and returns
2003-07-19 07:08:00 +04:00
* @ path : path of link to open .
2003-10-21 12:19:14 +04:00
* returns : struct sysfs_link * with success and NULL on error .
2003-07-19 07:08:00 +04:00
*/
2004-03-12 11:57:30 +03:00
struct sysfs_link * sysfs_open_link ( const char * linkpath )
2003-07-19 07:08:00 +04:00
{
2003-10-21 12:19:14 +04:00
struct sysfs_link * ln = NULL ;
2003-07-19 07:08:00 +04:00
2003-10-21 12:19:14 +04:00
if ( linkpath = = NULL | | strlen ( linkpath ) > SYSFS_PATH_MAX ) {
2003-07-19 07:08:00 +04:00
errno = EINVAL ;
return NULL ;
}
2003-10-21 12:19:14 +04:00
ln = alloc_link ( ) ;
if ( ln = = NULL ) {
dprintf ( " Error allocating link %s \n " , linkpath ) ;
2003-07-19 07:08:00 +04:00
return NULL ;
}
2004-03-12 11:57:30 +03:00
safestrcpy ( ln - > path , linkpath ) ;
2003-10-21 12:19:14 +04:00
if ( ( sysfs_get_name_from_path ( linkpath , ln - > name , SYSFS_NAME_LEN ) ) ! = 0
| | ( sysfs_get_link ( linkpath , ln - > target , SYSFS_PATH_MAX ) ) ! = 0 ) {
2004-10-20 15:15:26 +04:00
sysfs_close_link ( ln ) ;
2003-10-21 12:19:14 +04:00
errno = EINVAL ;
dprintf ( " Invalid link path %s \n " , linkpath ) ;
2003-07-19 07:08:00 +04:00
return NULL ;
}
2003-10-21 12:19:14 +04:00
return ln ;
2003-07-19 07:08:00 +04:00
}
2003-12-16 08:53:28 +03:00
/**
* add_attribute : open and add attribute at path to given directory
* @ sysdir : directory to add attribute to
* @ path : path to attribute
* returns 0 with success and - 1 with error .
*/
2004-03-12 11:57:30 +03:00
static int add_attribute ( struct sysfs_directory * sysdir , const char * path )
2003-12-16 08:53:28 +03:00
{
struct sysfs_attribute * attr = NULL ;
attr = sysfs_open_attribute ( path ) ;
if ( attr = = NULL ) {
dprintf ( " Error opening attribute %s \n " , path ) ;
return - 1 ;
}
if ( attr - > method & SYSFS_METHOD_SHOW ) {
if ( ( sysfs_read_attribute ( attr ) ) ! = 0 ) {
dprintf ( " Error reading attribute %s \n " , path ) ;
sysfs_close_attribute ( attr ) ;
return 0 ;
}
}
if ( sysdir - > attributes = = NULL ) {
sysdir - > attributes = dlist_new_with_delete
( sizeof ( struct sysfs_attribute ) , sysfs_del_attribute ) ;
}
2004-03-12 11:57:30 +03:00
dlist_unshift_sorted ( sysdir - > attributes , attr , sort_list ) ;
2003-12-16 08:53:28 +03:00
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 .
*/
2004-03-12 11:57:30 +03:00
static int add_subdirectory ( struct sysfs_directory * sysdir , const char * path )
2003-12-16 08:53:28 +03:00
{
struct sysfs_directory * subdir = NULL ;
subdir = sysfs_open_directory ( path ) ;
if ( subdir = = NULL ) {
dprintf ( " Error opening directory %s \n " , path ) ;
return - 1 ;
}
if ( sysdir - > subdirs = = NULL )
sysdir - > subdirs = dlist_new_with_delete
( sizeof ( struct sysfs_directory ) , sysfs_del_directory ) ;
2004-03-12 11:57:30 +03:00
dlist_unshift_sorted ( sysdir - > subdirs , subdir , sort_list ) ;
2003-12-16 08:53:28 +03:00
return 0 ;
}
/**
* 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 .
*/
2004-03-12 11:57:30 +03:00
static int add_link ( struct sysfs_directory * sysdir , const char * path )
2003-12-16 08:53:28 +03:00
{
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 ) ;
2004-03-12 11:57:30 +03:00
dlist_unshift_sorted ( sysdir - > links , ln , sort_list ) ;
2003-12-16 08:53:28 +03:00
return 0 ;
}
/**
* sysfs_read_dir_attributes : grabs attributes for the given directory
2003-07-19 07:08:00 +04:00
* @ sysdir : sysfs directory to open
* returns 0 with success and - 1 with error .
*/
2003-12-16 08:53:28 +03:00
int sysfs_read_dir_attributes ( struct sysfs_directory * sysdir )
2003-07-19 07:08:00 +04:00
{
DIR * dir = NULL ;
struct dirent * dirent = NULL ;
2004-03-12 11:57:30 +03:00
char file_path [ SYSFS_PATH_MAX ] ;
2003-07-19 07:08:00 +04:00
int retval = 0 ;
if ( sysdir = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
dir = opendir ( sysdir - > path ) ;
if ( dir = = NULL ) {
2003-10-21 12:19:14 +04:00
dprintf ( " Error opening directory %s \n " , sysdir - > path ) ;
2003-07-19 07:08:00 +04:00
return - 1 ;
}
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 ) ;
2004-03-12 11:57:30 +03:00
safestrcpy ( file_path , sysdir - > path ) ;
safestrcat ( file_path , " / " ) ;
safestrcat ( file_path , dirent - > d_name ) ;
2004-01-15 09:21:38 +03:00
if ( ( sysfs_path_is_file ( file_path ) ) = = 0 )
2003-12-16 08:53:28 +03:00
retval = add_attribute ( sysdir , file_path ) ;
}
closedir ( dir ) ;
2004-03-12 11:57:30 +03:00
if ( ! retval )
errno = 0 ;
2003-12-16 08:53:28 +03:00
return ( retval ) ;
}
/**
* sysfs_read_dir_links : grabs links in a specific directory
* @ sysdir : sysfs directory to read links
* returns 0 with success and - 1 with error .
*/
int sysfs_read_dir_links ( struct sysfs_directory * sysdir )
{
DIR * dir = NULL ;
struct dirent * dirent = NULL ;
2004-03-12 11:57:30 +03:00
char file_path [ SYSFS_PATH_MAX ] ;
2003-12-16 08:53:28 +03:00
int retval = 0 ;
if ( sysdir = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
dir = opendir ( sysdir - > path ) ;
if ( dir = = NULL ) {
dprintf ( " Error opening directory %s \n " , sysdir - > path ) ;
return - 1 ;
}
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 ) ;
2004-03-12 11:57:30 +03:00
safestrcpy ( file_path , sysdir - > path ) ;
safestrcat ( file_path , " / " ) ;
safestrcat ( file_path , dirent - > d_name ) ;
2004-01-15 09:21:38 +03:00
if ( ( sysfs_path_is_link ( file_path ) ) = = 0 ) {
2003-12-16 08:53:28 +03:00
retval = add_link ( sysdir , file_path ) ;
if ( retval ! = 0 )
2003-07-19 07:08:00 +04:00
break ;
}
}
closedir ( dir ) ;
2004-03-12 11:57:30 +03:00
if ( ! retval )
errno = 0 ;
2003-07-19 07:08:00 +04:00
return ( retval ) ;
}
/**
2003-12-16 08:53:28 +03:00
* sysfs_read_dir_subdirs : grabs subdirs in a specific directory
* @ sysdir : sysfs directory to read links
* returns 0 with success and - 1 with error .
*/
int sysfs_read_dir_subdirs ( struct sysfs_directory * sysdir )
{
DIR * dir = NULL ;
struct dirent * dirent = NULL ;
2004-03-12 11:57:30 +03:00
char file_path [ SYSFS_PATH_MAX ] ;
2003-12-16 08:53:28 +03:00
int retval = 0 ;
if ( sysdir = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
dir = opendir ( sysdir - > path ) ;
if ( dir = = NULL ) {
dprintf ( " Error opening directory %s \n " , sysdir - > path ) ;
return - 1 ;
}
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 ) ;
2004-03-12 11:57:30 +03:00
safestrcpy ( file_path , sysdir - > path ) ;
safestrcat ( file_path , " / " ) ;
safestrcat ( file_path , dirent - > d_name ) ;
2004-01-15 09:21:38 +03:00
if ( ( sysfs_path_is_dir ( file_path ) ) = = 0 )
2003-12-16 08:53:28 +03:00
retval = add_subdirectory ( sysdir , file_path ) ;
}
closedir ( dir ) ;
2004-03-12 11:57:30 +03:00
if ( ! retval )
errno = 0 ;
2003-12-16 08:53:28 +03:00
return ( retval ) ;
}
/**
* sysfs_read_directory : grabs attributes , links , and subdirectories
* @ sysdir : sysfs directory to open
* returns 0 with success and - 1 with error .
*/
int sysfs_read_directory ( struct sysfs_directory * sysdir )
{
DIR * dir = NULL ;
struct dirent * dirent = NULL ;
struct stat astats ;
2004-03-12 11:57:30 +03:00
char file_path [ SYSFS_PATH_MAX ] ;
2003-12-16 08:53:28 +03:00
int retval = 0 ;
if ( sysdir = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
dir = opendir ( sysdir - > path ) ;
if ( dir = = NULL ) {
dprintf ( " Error opening directory %s \n " , sysdir - > path ) ;
return - 1 ;
}
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 ) ;
2004-03-12 11:57:30 +03:00
safestrcpy ( file_path , sysdir - > path ) ;
safestrcat ( file_path , " / " ) ;
safestrcat ( file_path , dirent - > d_name ) ;
2003-12-16 08:53:28 +03:00
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 ) ;
2004-03-12 11:57:30 +03:00
if ( ! retval )
errno = 0 ;
2003-12-16 08:53:28 +03:00
return ( retval ) ;
}
2004-01-15 09:21:38 +03:00
/**
* 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 ;
}
2004-03-12 11:57:30 +03:00
errno = 0 ;
2004-01-15 09:21:38 +03:00
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 ;
}
2004-03-12 11:57:30 +03:00
errno = 0 ;
2004-01-15 09:21:38 +03:00
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 ;
}
2004-03-12 11:57:30 +03:00
errno = 0 ;
2004-01-15 09:21:38 +03:00
return 0 ;
}
2003-12-16 08:53:28 +03:00
/**
* sysfs_get_directory_attribute : retrieves attribute attrname from current
* directory only
2003-10-21 12:19:14 +04:00
* @ dir : directory to retrieve attribute from
* @ attrname : name of attribute to look for
2004-03-12 11:57:30 +03:00
*
* 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 .
*
2003-10-21 12:19:14 +04:00
* returns sysfs_attribute if found and NULL if not found
2003-07-19 07:08:00 +04:00
*/
2003-10-21 12:19:14 +04:00
struct sysfs_attribute * sysfs_get_directory_attribute
2004-03-12 11:57:30 +03:00
( struct sysfs_directory * dir , char * attrname )
2003-07-19 07:08:00 +04:00
{
2003-10-21 12:19:14 +04:00
struct sysfs_attribute * attr = NULL ;
2004-03-12 11:57:30 +03:00
char new_path [ SYSFS_PATH_MAX ] ;
2003-10-21 12:19:14 +04:00
if ( dir = = NULL | | attrname = = NULL ) {
errno = EINVAL ;
return NULL ;
}
2003-12-16 08:53:28 +03:00
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 ) ;
2004-01-15 09:21:38 +03:00
if ( attr ! = NULL ) {
2004-10-20 15:15:26 +04:00
if ( ( attr - > method & SYSFS_METHOD_SHOW ) & &
( sysfs_read_attribute ( attr ) ) ! = 0 ) {
2004-01-15 09:21:38 +03:00
dprintf ( " Error reading attribute %s \n " , attr - > name ) ;
return NULL ;
}
} else {
2003-12-16 08:53:28 +03:00
memset ( new_path , 0 , SYSFS_PATH_MAX ) ;
2004-03-12 11:57:30 +03:00
safestrcpy ( new_path , dir - > path ) ;
safestrcat ( new_path , " / " ) ;
safestrcat ( new_path , attrname ) ;
2003-12-16 08:53:28 +03:00
if ( ( sysfs_path_is_file ( new_path ) ) = = 0 ) {
2004-01-15 09:21:38 +03:00
if ( ( add_attribute ( dir , new_path ) ) = = 0 ) {
2003-12-20 05:29:10 +03:00
attr = ( struct sysfs_attribute * )
2004-01-15 09:21:38 +03:00
dlist_find_custom ( dir - > attributes ,
2003-12-20 05:29:10 +03:00
attrname , dir_attribute_name_equal ) ;
2003-12-16 08:53:28 +03:00
}
2003-10-21 12:19:14 +04:00
}
}
2004-01-15 09:21:38 +03:00
2003-12-20 05:29:10 +03:00
return attr ;
2003-10-21 12:19:14 +04:00
}
2003-07-19 07:08:00 +04:00
2003-10-21 12:19:14 +04:00
/**
* 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
2004-03-12 11:57:30 +03:00
( struct sysfs_directory * dir , char * linkname )
2003-10-21 12:19:14 +04:00
{
if ( dir = = NULL | | linkname = = NULL ) {
2003-07-19 07:08:00 +04:00
errno = EINVAL ;
2003-10-21 12:19:14 +04:00
return NULL ;
2003-07-19 07:08:00 +04:00
}
2004-01-15 09:21:38 +03:00
if ( dir - > links = = NULL ) {
2003-12-16 08:53:28 +03:00
if ( ( sysfs_read_dir_links ( dir ) ! = 0 ) | | ( dir - > links = = NULL ) )
return NULL ;
2004-01-15 09:21:38 +03:00
} else {
if ( ( sysfs_refresh_dir_links ( dir ) ) ! = 0 )
return NULL ;
}
2003-12-16 08:53:28 +03:00
2003-10-21 12:19:14 +04:00
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 ,
2004-03-12 11:57:30 +03:00
char * subname )
2003-10-21 12:19:14 +04:00
{
struct sysfs_directory * sub = NULL , * cursub = NULL ;
2003-12-16 08:53:28 +03:00
if ( dir = = NULL | | subname = = NULL ) {
2003-10-21 12:19:14 +04:00
errno = EINVAL ;
return NULL ;
}
2003-12-16 08:53:28 +03:00
if ( dir - > subdirs = = NULL )
if ( sysfs_read_dir_subdirs ( dir ) ! = 0 )
return NULL ;
2003-10-21 12:19:14 +04:00
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 ) {
2003-12-16 08:53:28 +03:00
if ( cursub - > subdirs = = NULL ) {
if ( sysfs_read_dir_subdirs ( cursub ) ! = 0 )
continue ;
if ( cursub - > subdirs = = NULL )
continue ;
}
2003-10-21 12:19:14 +04:00
sub = sysfs_get_subdirectory ( cursub , subname ) ;
if ( sub ! = NULL )
return sub ;
2003-07-19 07:08:00 +04:00
}
}
2003-10-21 12:19:14 +04:00
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 ,
2004-03-12 11:57:30 +03:00
char * linkname )
2003-10-21 12:19:14 +04:00
{
struct sysfs_directory * cursub = NULL ;
struct sysfs_link * ln = NULL ;
2003-12-16 08:53:28 +03:00
if ( dir = = NULL | | linkname = = NULL ) {
2003-10-21 12:19:14 +04:00
errno = EINVAL ;
return NULL ;
}
ln = sysfs_get_directory_link ( dir , linkname ) ;
if ( ln ! = NULL )
return ln ;
2003-12-16 08:53:28 +03:00
if ( dir - > subdirs = = NULL )
if ( sysfs_read_dir_subdirs ( dir ) ! = 0 )
return NULL ;
2003-10-21 12:19:14 +04:00
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 ;
}
}
return NULL ;
2003-07-19 07:08:00 +04:00
}
2004-01-15 09:21:38 +03:00
/**
* 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 ) ;
}