1 /*
2  * sysfs_module.c
3  *
4  * Generic module utility functions for libsysfs
5  *
6  * Copyright (C) IBM Corp. 2003-2005
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  */
23 #include "libsysfs.h"
24 #include "sysfs.h"
25 
26 /**
27  * mod_name_equal: compares modules' name
28  * @a: module_name looking for
29  * @b: sysfs_module being compared
30  */
mod_name_equal(void * a,void * b)31 static int mod_name_equal(void *a, void *b)
32 {
33 	if (a == NULL || b == NULL)
34 		return 0;
35 
36 	if (strcmp(((char *)a), ((struct sysfs_module *)b)->name) == 0)
37 		return 1;
38 
39 	return 0;
40 }
41 
42 /**
43  * sysfs_close_module: closes a module.
44  * @module: sysfs_module device to close.
45  */
sysfs_close_module(struct sysfs_module * module)46 void sysfs_close_module(struct sysfs_module *module)
47 {
48 	/*
49 	 * since both parms and sections are attribs _under_ the
50 	 * subdir of module->directory, they will get closed by
51 	 * this single call
52 	 */
53 	if (module != NULL) {
54 		if (module->attrlist != NULL)
55 			dlist_destroy(module->attrlist);
56 		if (module->parmlist != NULL)
57 			dlist_destroy(module->parmlist);
58 		if (module->sections != NULL)
59 			dlist_destroy(module->sections);
60 		free(module);
61 	}
62 }
63 
64 /**
65  * alloc_module: callocs and initializes new module struct.
66  * returns sysfs_module or NULL.
67  */
alloc_module(void)68 static struct sysfs_module *alloc_module(void)
69 {
70 	return (struct sysfs_module *)calloc(1, sizeof(struct sysfs_module));
71 }
72 
73 /**
74  * sysfs_open_module_path: Opens and populates the module struct
75  * @path: path to module.
76  * returns struct sysfs_module with success and NULL with error.
77  */
sysfs_open_module_path(const char * path)78 struct sysfs_module *sysfs_open_module_path(const char *path)
79 {
80 	struct sysfs_module *mod = NULL;
81 
82 	if (path == NULL) {
83 		errno = EINVAL;
84 		return NULL;
85 	}
86 	if ((sysfs_path_is_dir(path)) != 0) {
87 		dprintf("%s is not a valid path to a module\n", path);
88 		return NULL;
89 	}
90 	mod = alloc_module();
91 	if (mod == NULL) {
92 		dprintf("calloc failed\n");
93 		return NULL;
94 	}
95 	if ((sysfs_get_name_from_path(path, mod->name, SYSFS_NAME_LEN)) != 0) {
96 		errno = EINVAL;
97 		dprintf("Error getting module name\n");
98 		sysfs_close_module(mod);
99 		return NULL;
100 	}
101 
102 	safestrcpy(mod->path, path);
103 	if ((sysfs_remove_trailing_slash(mod->path)) != 0) {
104 		dprintf("Invalid path to module %s\n", mod->path);
105 		sysfs_close_module(mod);
106 		return NULL;
107 	}
108 
109 	return mod;
110 }
111 
112 /**
113  * sysfs_open_module: opens specific module on a system
114  * returns sysfs_module structure with success or NULL with error.
115  */
sysfs_open_module(const char * name)116 struct sysfs_module *sysfs_open_module(const char *name)
117 {
118 	struct sysfs_module *mod = NULL;
119 	char modpath[SYSFS_PATH_MAX];
120 
121 	if (name == NULL) {
122 		errno = EINVAL;
123 		return NULL;
124 	}
125 
126 	memset(modpath, 0, SYSFS_PATH_MAX);
127 	if ((sysfs_get_mnt_path(modpath, SYSFS_PATH_MAX)) != 0) {
128 		dprintf("Sysfs not supported on this system\n");
129 		return NULL;
130 	}
131 
132 	safestrcat(modpath, "/");
133 	safestrcat(modpath, SYSFS_MODULE_NAME);
134 	safestrcat(modpath, "/");
135 	safestrcat(modpath, name);
136 
137 	if ((sysfs_path_is_dir(modpath)) != 0) {
138 		dprintf("Module %s not found on the system\n", name);
139 		return NULL;
140 	}
141 
142 	mod = alloc_module();
143 	if (mod == NULL) {
144 		dprintf("calloc failed\n");
145 		return NULL;
146 	}
147 	safestrcpy(mod->name, name);
148 	safestrcpy(mod->path, modpath);
149 	if ((sysfs_remove_trailing_slash(mod->path)) != 0) {
150 		dprintf("Invalid path to module %s\n", mod->path);
151 		sysfs_close_module(mod);
152 		return NULL;
153 	}
154 
155 	return mod;
156 }
157 
158 /**
159  * sysfs_get_module_attributes: returns a dlist of attributes for
160  *     the requested sysfs_module
161  * @cdev: sysfs_module for which attributes are needed
162  * returns a dlist of attributes if exists, NULL otherwise
163  */
sysfs_get_module_attributes(struct sysfs_module * module)164 struct dlist *sysfs_get_module_attributes(struct sysfs_module *module)
165 {
166 	if (module == NULL) {
167 		errno = EINVAL;
168 		return NULL;
169 	}
170 	return get_dev_attributes_list(module);
171 }
172 
173 /**
174  * sysfs_get_module_attr: searches module's attributes by name
175  * @module: module to look through
176  * @name: attribute name to get
177  * returns sysfs_attribute reference with success or NULL with error
178  */
sysfs_get_module_attr(struct sysfs_module * module,const char * name)179 struct sysfs_attribute *sysfs_get_module_attr
180 		(struct sysfs_module *module, const char *name)
181 {
182 	if (module == NULL || name == NULL) {
183 		errno = EINVAL;
184 		return NULL;
185 	}
186 
187 	return get_attribute(module, (char *)name);
188 }
189 
190 /**
191  * sysfs_get_module_parms: Get modules list of parameters
192  * @module: sysfs_module whose parmameter list is required
193  * Returns dlist of parameters on SUCCESS and NULL on error
194  */
sysfs_get_module_parms(struct sysfs_module * module)195 struct dlist *sysfs_get_module_parms(struct sysfs_module *module)
196 {
197 	char ppath[SYSFS_PATH_MAX];
198 
199 	if (module == NULL) {
200 		errno = EINVAL;
201 		return NULL;
202 	}
203 	memset(ppath, 0, SYSFS_PATH_MAX);
204 	safestrcpy(ppath, module->path);
205 	safestrcat(ppath,"/");
206 	safestrcat(ppath, SYSFS_MOD_PARM_NAME);
207 
208 	return (get_attributes_list(module->parmlist, ppath));
209 }
210 
211 /**
212  * sysfs_get_module_sections: Get the set of sections for this module
213  * @module: sysfs_module whose list of sections is required
214  * Returns dlist of sections on SUCCESS and NULL on error
215  */
sysfs_get_module_sections(struct sysfs_module * module)216 struct dlist *sysfs_get_module_sections(struct sysfs_module *module)
217 {
218 	char ppath[SYSFS_PATH_MAX];
219 
220 	if (module == NULL) {
221 		errno = EINVAL;
222 		return NULL;
223 	}
224 
225 	memset(ppath, 0, SYSFS_PATH_MAX);
226 	safestrcpy(ppath, module->path);
227 	safestrcat(ppath,"/");
228 	safestrcat(ppath, SYSFS_MOD_SECT_NAME);
229 
230 	return (get_attributes_list(module->sections, ppath));
231 }
232 
233 /**
234  * sysfs_get_module_parm:
235  * @module: sysfs_module to look through
236  * @parm: name of the parameter to look for
237  * Returns sysfs_attribute * on SUCCESS and NULL on error
238  */
sysfs_get_module_parm(struct sysfs_module * module,const char * parm)239 struct sysfs_attribute *sysfs_get_module_parm
240 		(struct sysfs_module *module, const char *parm)
241 {
242 	struct dlist *parm_list = NULL;
243 
244 	if (module == NULL || parm == NULL) {
245 		errno = EINVAL;
246 		return NULL;
247 	}
248 
249 	parm_list = sysfs_get_module_parms(module);
250 	if (parm_list == NULL)
251 		return NULL;
252 
253 	return (struct sysfs_attribute *)dlist_find_custom(parm_list,
254 		(void *)parm, mod_name_equal);
255 }
256 
257 /**
258  * sysfs_get_module_section
259  * @module: sysfs_module to look through
260  * @section: name of the section to look for
261  * Returns sysfs_attribute * on SUCCESS and NULL on error
262  */
sysfs_get_module_section(struct sysfs_module * module,const char * section)263 struct sysfs_attribute *sysfs_get_module_section
264 		(struct sysfs_module *module, const char *section)
265 {
266 	struct dlist *sect_list = NULL;
267 
268 	if (module == NULL || section == NULL) {
269 		errno = EINVAL;
270 		return NULL;
271 	}
272 
273 	sect_list = sysfs_get_module_sections(module);
274 	if (sect_list == NULL)
275 		return NULL;
276 
277 	return (struct sysfs_attribute *)dlist_find_custom(sect_list,
278 		(void *)section, mod_name_equal);
279 }
280