blob: 375de1a55b75d6a02b9c5acbe44c5a35cc20eb4c [file] [log] [blame]
/*
* sysfs_module.c
*
* Generic module utility functions for libsysfs
*
* 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
* 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
*
*/
#include "libsysfs.h"
#include "sysfs.h"
/**
* mod_name_equal: compares modules' name
* @a: module_name looking for
* @b: sysfs_module being compared
*/
static int mod_name_equal(void *a, void *b)
{
if (a == NULL || b == NULL)
return 0;
if (strcmp(((char *)a), ((struct sysfs_module *)b)->name) == 0)
return 1;
return 0;
}
/**
* sysfs_close_module: closes a module.
* @module: sysfs_module device to close.
*/
void sysfs_close_module(struct sysfs_module *module)
{
/*
* since both parms and sections are attribs _under_ the
* subdir of module->directory, they will get closed by
* this single call
*/
if (module != NULL) {
if (module->attrlist != NULL)
dlist_destroy(module->attrlist);
if (module->parmlist != NULL)
dlist_destroy(module->parmlist);
if (module->sections != NULL)
dlist_destroy(module->sections);
free(module);
}
}
/**
* alloc_module: callocs and initializes new module struct.
* returns sysfs_module or NULL.
*/
static struct sysfs_module *alloc_module(void)
{
return (struct sysfs_module *)calloc(1, sizeof(struct sysfs_module));
}
/**
* sysfs_open_module_path: Opens and populates the module struct
* @path: path to module.
* returns struct sysfs_module with success and NULL with error.
*/
struct sysfs_module *sysfs_open_module_path(const char *path)
{
struct sysfs_module *mod = NULL;
if (path == NULL) {
errno = EINVAL;
return NULL;
}
if ((sysfs_path_is_dir(path)) != 0) {
dprintf("%s is not a valid path to a module\n", path);
return NULL;
}
mod = alloc_module();
if (mod == NULL) {
dprintf("calloc failed\n");
return NULL;
}
if ((sysfs_get_name_from_path(path, mod->name, SYSFS_NAME_LEN)) != 0) {
errno = EINVAL;
dprintf("Error getting module name\n");
sysfs_close_module(mod);
return NULL;
}
safestrcpy(mod->path, path);
if ((sysfs_remove_trailing_slash(mod->path)) != 0) {
dprintf("Invalid path to module %s\n", mod->path);
sysfs_close_module(mod);
return NULL;
}
return mod;
}
/**
* sysfs_open_module: opens specific module on a system
* returns sysfs_module structure with success or NULL with error.
*/
struct sysfs_module *sysfs_open_module(const char *name)
{
struct sysfs_module *mod = NULL;
char modpath[SYSFS_PATH_MAX];
if (name == NULL) {
errno = EINVAL;
return NULL;
}
memset(modpath, 0, SYSFS_PATH_MAX);
if ((sysfs_get_mnt_path(modpath, SYSFS_PATH_MAX)) != 0) {
dprintf("Sysfs not supported on this system\n");
return NULL;
}
safestrcat(modpath, "/");
safestrcat(modpath, SYSFS_MODULE_NAME);
safestrcat(modpath, "/");
safestrcat(modpath, name);
if ((sysfs_path_is_dir(modpath)) != 0) {
dprintf("Module %s not found on the system\n", name);
return NULL;
}
mod = alloc_module();
if (mod == NULL) {
dprintf("calloc failed\n");
return NULL;
}
safestrcpy(mod->name, name);
safestrcpy(mod->path, modpath);
if ((sysfs_remove_trailing_slash(mod->path)) != 0) {
dprintf("Invalid path to module %s\n", mod->path);
sysfs_close_module(mod);
return NULL;
}
return mod;
}
/**
* sysfs_get_module_attributes: returns a dlist of attributes for
* the requested sysfs_module
* @cdev: sysfs_module for which attributes are needed
* returns a dlist of attributes if exists, NULL otherwise
*/
struct dlist *sysfs_get_module_attributes(struct sysfs_module *module)
{
if (module == NULL) {
errno = EINVAL;
return NULL;
}
return get_dev_attributes_list(module);
}
/**
* sysfs_get_module_attr: searches module's attributes by name
* @module: module to look through
* @name: attribute name to get
* returns sysfs_attribute reference with success or NULL with error
*/
struct sysfs_attribute *sysfs_get_module_attr
(struct sysfs_module *module, const char *name)
{
if (module == NULL || name == NULL) {
errno = EINVAL;
return NULL;
}
return get_attribute(module, (char *)name);
}
/**
* sysfs_get_module_parms: Get modules list of parameters
* @module: sysfs_module whose parmameter list is required
* Returns dlist of parameters on SUCCESS and NULL on error
*/
struct dlist *sysfs_get_module_parms(struct sysfs_module *module)
{
char ppath[SYSFS_PATH_MAX];
if (module == NULL) {
errno = EINVAL;
return NULL;
}
memset(ppath, 0, SYSFS_PATH_MAX);
safestrcpy(ppath, module->path);
safestrcat(ppath,"/");
safestrcat(ppath, SYSFS_MOD_PARM_NAME);
return (get_attributes_list(module->parmlist, ppath));
}
/**
* sysfs_get_module_sections: Get the set of sections for this module
* @module: sysfs_module whose list of sections is required
* Returns dlist of sections on SUCCESS and NULL on error
*/
struct dlist *sysfs_get_module_sections(struct sysfs_module *module)
{
char ppath[SYSFS_PATH_MAX];
if (module == NULL) {
errno = EINVAL;
return NULL;
}
memset(ppath, 0, SYSFS_PATH_MAX);
safestrcpy(ppath, module->path);
safestrcat(ppath,"/");
safestrcat(ppath, SYSFS_MOD_SECT_NAME);
return (get_attributes_list(module->sections, ppath));
}
/**
* sysfs_get_module_parm:
* @module: sysfs_module to look through
* @parm: name of the parameter to look for
* Returns sysfs_attribute * on SUCCESS and NULL on error
*/
struct sysfs_attribute *sysfs_get_module_parm
(struct sysfs_module *module, const char *parm)
{
struct dlist *parm_list = NULL;
if (module == NULL || parm == NULL) {
errno = EINVAL;
return NULL;
}
parm_list = sysfs_get_module_parms(module);
if (parm_list == NULL)
return NULL;
return (struct sysfs_attribute *)dlist_find_custom(parm_list,
(void *)parm, mod_name_equal);
}
/**
* sysfs_get_module_section
* @module: sysfs_module to look through
* @section: name of the section to look for
* Returns sysfs_attribute * on SUCCESS and NULL on error
*/
struct sysfs_attribute *sysfs_get_module_section
(struct sysfs_module *module, const char *section)
{
struct dlist *sect_list = NULL;
if (module == NULL || section == NULL) {
errno = EINVAL;
return NULL;
}
sect_list = sysfs_get_module_sections(module);
if (sect_list == NULL)
return NULL;
return (struct sysfs_attribute *)dlist_find_custom(sect_list,
(void *)section, mod_name_equal);
}