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