├── .gitignore ├── .travis.yml ├── AUTHORS ├── COPYING ├── CREDITS ├── Makefile.am ├── README ├── TODO ├── autogen ├── cmd ├── .gitignore ├── GPL ├── Makefile.am ├── names.c ├── names.h └── systool.c ├── configure.ac ├── docs └── libsysfs.txt ├── include ├── dlist.h └── libsysfs.h ├── lib ├── LGPL ├── Makefile.am ├── dlist.c ├── libsysfs.map ├── libsysfs.pc.in ├── sysfs.h ├── sysfs_attr.c ├── sysfs_bus.c ├── sysfs_class.c ├── sysfs_device.c ├── sysfs_driver.c ├── sysfs_module.c └── sysfs_utils.c ├── m4 ├── .gitignore └── klibc.m4 ├── systool.1 └── test ├── .gitignore ├── GPL ├── Makefile.am ├── create-test ├── dlist_test.c ├── get_device.c ├── get_driver.c ├── get_module.c ├── libsysfs.conf ├── libsysfs.conf-suse ├── test-defs.h ├── test.c ├── test_attr.c ├── test_bus.c ├── test_class.c ├── test_device.c ├── test_driver.c ├── test_module.c ├── test_utils.c └── testout.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.la 2 | *.lo 3 | *.o 4 | *.pc 5 | *~ 6 | .deps 7 | .libs 8 | INSTALL 9 | Makefile 10 | Makefile.in 11 | aclocal.m4 12 | autom4te.cache 13 | compile 14 | config.* 15 | configure 16 | cscope.* 17 | depcomp 18 | install-sh 19 | libtool 20 | ltmain.sh 21 | missing 22 | stamp-h1 23 | tags 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | dist: xenial 3 | arch: 4 | - amd64 5 | - ppc64le 6 | 7 | script: 8 | - ./autogen 9 | - ./configure 10 | - make 11 | - sudo make install 12 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Ananth Mavinakayanahalli 2 | Daniel Stekloff 3 | Mohan Kumar 4 | Nitin Vashisth 5 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | The commands and utilities are licensed under the GNU General Public License 3 | (GPL) Version 2, June 1991. The full text of the GPL is located at: 4 | 5 | sysfsutils/cmd/GPL 6 | 7 | The sysfs library is licensed under the GNU Lesser Public License (LGPL) 8 | Version 2.1, February 1999. The full text of the LGPL is located at: 9 | 10 | sysfsutils/lib/LGPL 11 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | 2 | The authors of sysfsutils would like to thank the following people who 3 | have made contributions: 4 | 5 | o Lev Makhlis : 6 | - Supplied libsysfs code cleanup including code 7 | simplification, read-only strings, and 8 | C++ compatibility. 9 | o Eric J Bohm : 10 | - Supplied dlist generic linked list implementation. 11 | - Added dlist_for_each* functionality. 12 | o Guo Min : 13 | - Supplied sysfs_write_attribute patch 14 | o Martin Mares 15 | - Author of pciutils. Reused the pci name decoding 16 | from Martin's library. 17 | o Martin Pitt 18 | - Supplied initial makefiles for lsbus and systool 19 | o Martin Hicks 20 | - Supplied patch to fix class_device functions 21 | o Brian King 22 | - Supplied patch to fix a memory leak in sysfs_dir.c 23 | o Martin Schlemmer 24 | - Supplied patch to prevent checks for installed 25 | headers, while building. 26 | o Lev Makhlis 27 | - Supplied patch to make library C++ compatible. 28 | o Dr. Hannes Reinecke 29 | - Supplied patch to fix SEGV in dlist.c 30 | o Arun Bhanu 31 | - Supplied patch to fix docs/libsysfs.txt 32 | o Kay Sievers 33 | - Supplied patch to fix sysfs_get_classdir_attr when 34 | the directory vanishes from under us. 35 | - Updates for building with udev and klibc. 36 | - Numerous other updates, cleanups and general guidelines 37 | o Dominik Brodowski 38 | - Fix feature in sysfs_write_attribute(), will now 39 | write new value to attribute if attribute 40 | is a show method and previously had nothing 41 | to be read. 42 | o Martin Schlemmer 43 | - KLIBC updates 44 | o Pavel Roskin 45 | - Use buildroot for rpmbuilds 46 | o Lee Duncan 47 | - Supplied patches to fix compilation bugs/warnings 48 | with GCC 7/10. 49 | - Improved the build scripts to work latest autotools 50 | and work with git repository. 51 | - Numerous other patches to fix various bugs. 52 | - Updated the README info on how to file issues. 53 | - Supplied patch to add SUSE-specific libsysfs.conf 54 | o Christopher Engelhard 55 | - Supplied patch to fix adjusting COPYING file to 56 | reflect set of directories covered under GPLv2. 57 | - Supplied patch to fix address in the licensing files 58 | cmd/GPL and lib/LGPL. 59 | - Numerous other patches to fix various bugs. 60 | o Aurelien Jarno 61 | - Supplied patch to fix missing m4 macro directory. 62 | o Guillem Jover 63 | - Modernized the build system to use the latest autotools. 64 | - Cleaned up the build scripts to remove obsolete files, 65 | hooks and improved the build scripts to work with git. 66 | - Supplied patch to convert bash to POSIX portable syntax. 67 | - Supplied patch to introduce pkg-confile to replace 68 | libtool for library detection and linking. 69 | - Supplied patch to add out-of-tree support. 70 | - Supplied patch to add make rule to move test program 71 | into check_PROGRAMS. 72 | o Martin Pitt 73 | - Supplied patch to valid mount point in 74 | sysfs_get_mnt_path(). 75 | o Timm Bäder 76 | - Supplied patch to rename dprintf() to debugprintf(), 77 | to avoid collision with glibc macros. 78 | 79 | Please visit pulls/issues page at https://github.com/linux-ras/sysfsutils 80 | for more information. 81 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | man_MANS = systool.1 4 | EXTRA_DIST = docs include $(man_MANS) CREDITS lib/LGPL cmd/GPL test/GPL 5 | SUBDIRS = lib cmd test 6 | includedir=@includedir@/sysfs 7 | include_HEADERS = include/libsysfs.h include/dlist.h 8 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | Sysfs Utilities Package - Includes Libsysfs (v. 2.1.1) 3 | ====================================================== 4 | 5 | Contents 6 | -------- 7 | 1. Introduction 8 | 2. How to Install 9 | 2.1 Caveats/Known issues 10 | 3. Licenses 11 | 4. Reporting Bugs 12 | 13 | 14 | 1. Introduction 15 | --------------- 16 | 17 | This package's purpose is to provide a set of utilities for interfacing 18 | with sysfs, a virtual filesystem in Linux kernel versions 2.5+ that 19 | provides a tree of system devices. While a filesystem is a very useful 20 | interface, we've decided to provide a stable programming interface 21 | that will hopefully make it easier for applications to query system devices 22 | and their attributes. 23 | 24 | This package currently includes: 25 | 26 | - libsysfs: a library for accessing system devices. 27 | - systool: an application to view system device information by bus, class, 28 | and topology. 29 | - A number of example usage routines in the "test" directory. 30 | - A comprehensive testsuite, also shipped as part of the "test" directory. This 31 | testsuite can be used to test _all_ the APIs exported by Libsysfs. 32 | Please refer the libsysfs.txt file in the "docs" directory for 33 | details as to how to use the testsuite. 34 | 35 | 36 | 2. How to Install 37 | ----------------- 38 | 39 | Run the "configure" script to generate Makefiles. Use "make" to build the 40 | library and utilities. 41 | 42 | For a successful install, run "make install" as super-user. "make uninstall" 43 | will clean up all installed files. 44 | 45 | 46 | 3. Licenses 47 | ----------- 48 | 49 | The commands and tests are licensed under the GNU Public License (GPL) 50 | Version 2, June 1991. The full text of the GPL is located in this package's 51 | "cmd" directory: 52 | 53 | sysfsutils/cmd/GPL 54 | 55 | The library is licensed under the GNU Lesser Public License (LGPL) 56 | Version 2.1, February 1999. The full text of the LGPL is located in 57 | this package's "lib" directory: 58 | 59 | sysfsutils/lib/LGPL 60 | 61 | 62 | 4. Reporting Bugs 63 | ----------------- 64 | 65 | Feel free to report bugs by opening an issue in the GitHub Issue Tracker. 66 | 67 | 5. Contributions 68 | ---------------- 69 | 70 | For submitting patches, open a GitHub pull request. Please make sure that they 71 | are rebased on top of the current master. Code submission guidelines are the 72 | same as the Linux Kernel contribution guidelines. 73 | 74 | You probably want to read the through Linux kernel Documentation/SubmittingPatches 75 | for guidance. 76 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Library: 2 | -------- 3 | - Rework debugging error messages and look into better logging on error. 4 | 5 | Commands: 6 | --------- 7 | - Add topology tree view. 8 | 9 | Documentation: 10 | -------------- 11 | - Update/improve documentation. 12 | -------------------------------------------------------------------------------- /autogen: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | autoreconf -f -i 6 | -------------------------------------------------------------------------------- /cmd/.gitignore: -------------------------------------------------------------------------------- 1 | systool 2 | -------------------------------------------------------------------------------- /cmd/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = systool 2 | systool_SOURCES = systool.c names.c names.h 3 | LDADD = $(top_builddir)/lib/libsysfs.la 4 | AM_CPPFLAGS = -I$(top_srcdir)/include 5 | AM_CFLAGS = -Wall -W -Wextra -Wstrict-prototypes $(EXTRA_CFLAGS) 6 | 7 | -------------------------------------------------------------------------------- /cmd/names.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The PCI Library -- ID to Name Translation 3 | * 4 | * Copyright (c) 1997--2002 Martin Mares 5 | * 6 | * Can be freely distributed and used under the terms of the GNU GPL. 7 | */ 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "names.h" 20 | 21 | struct nl_entry { 22 | struct nl_entry *next; 23 | unsigned short id1, id2, id3, id4; 24 | int cat; 25 | char *name; 26 | }; 27 | 28 | #define NL_VENDOR 0 29 | #define NL_DEVICE 1 30 | #define NL_SUBSYSTEM 2 31 | #define NL_CLASS 3 32 | #define NL_SUBCLASS 4 33 | #define NL_PROGIF 5 34 | 35 | #define HASH_SIZE 1024 36 | 37 | static inline unsigned int nl_calc_hash(int cat, int id1, int id2, int id3, int id4) 38 | { 39 | unsigned int h; 40 | 41 | h = id1 ^ id2 ^ id3 ^ id4 ^ (cat << 5); 42 | h += (h >> 6); 43 | return h & (HASH_SIZE-1); 44 | } 45 | 46 | static struct nl_entry *nl_lookup(struct pci_access *a, int num, int cat, int id1, int id2, int id3, int id4) 47 | { 48 | unsigned int h; 49 | struct nl_entry *n; 50 | 51 | if (num) 52 | return NULL; 53 | h = nl_calc_hash(cat, id1, id2, id3, id4); 54 | n = a->nl_hash[h]; 55 | while (n && (n->id1 != id1 || n->id2 != id2 || n->id3 != id3 || n->id4 != id4 || n->cat != cat)) 56 | n = n->next; 57 | 58 | return n; 59 | } 60 | 61 | static int nl_add(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, char *text) 62 | { 63 | unsigned int h = nl_calc_hash(cat, id1, id2, id3, id4); 64 | struct nl_entry *n = a->nl_hash[h]; 65 | 66 | while (n && (n->id1 != id1 || n->id2 != id2 || n->id3 != id3 || n->id4 != id4 || n->cat != cat)) 67 | n = n->next; 68 | if (n) 69 | return 1; 70 | n = malloc(sizeof(struct nl_entry)); 71 | bzero(n, sizeof(struct nl_entry)); 72 | n->id1 = id1; 73 | n->id2 = id2; 74 | n->id3 = id3; 75 | n->id4 = id4; 76 | n->cat = cat; 77 | n->name = text; 78 | n->next = a->nl_hash[h]; 79 | a->nl_hash[h] = n; 80 | return 0; 81 | } 82 | 83 | static void 84 | err_name_list(struct pci_access *a, char *msg) 85 | { 86 | fprintf(stderr, "%s: %s: %s\n", a->pci_id_file_name, msg, strerror(errno)); 87 | } 88 | 89 | static void 90 | parse_name_list(struct pci_access *a) 91 | { 92 | char *p = (char *)a->nl_list; 93 | char *q, *r; 94 | int lino = 0; 95 | unsigned int id1=0, id2=0, id3=0, id4=0; 96 | int cat = -1; 97 | 98 | while (*p) 99 | { 100 | lino++; 101 | q = p; 102 | while (*p && *p != '\n') 103 | p++; 104 | if (*p == '\n') 105 | *p++ = 0; 106 | if (!*q || *q == '#') 107 | continue; 108 | r = p; 109 | while (r > q && r[-1] == ' ') 110 | *--r = 0; 111 | r = q; 112 | while (*q == '\t') 113 | q++; 114 | if (q == r) 115 | { 116 | if (q[0] == 'C' && q[1] == ' ') 117 | { 118 | if (strlen(q+2) < 3 || 119 | q[4] != ' ' || 120 | sscanf(q+2, "%x", &id1) != 1) 121 | goto parserr; 122 | cat = NL_CLASS; 123 | } 124 | else 125 | { 126 | if (strlen(q) < 5 || 127 | q[4] != ' ' || 128 | sscanf(q, "%x", &id1) != 1) 129 | goto parserr; 130 | cat = NL_VENDOR; 131 | } 132 | id2 = id3 = id4 = 0; 133 | q += 4; 134 | } 135 | else if (q == r+1) 136 | switch (cat) 137 | { 138 | case NL_VENDOR: 139 | case NL_DEVICE: 140 | case NL_SUBSYSTEM: 141 | if (sscanf(q, "%x", &id2) != 1 || q[4] != ' ') 142 | goto parserr; 143 | q += 5; 144 | cat = NL_DEVICE; 145 | id3 = id4 = 0; 146 | break; 147 | case NL_CLASS: 148 | case NL_SUBCLASS: 149 | case NL_PROGIF: 150 | if (sscanf(q, "%x", &id2) != 1 || q[2] != ' ') 151 | goto parserr; 152 | q += 3; 153 | cat = NL_SUBCLASS; 154 | id3 = id4 = 0; 155 | break; 156 | default: 157 | goto parserr; 158 | } 159 | else if (q == r+2) 160 | switch (cat) 161 | { 162 | case NL_DEVICE: 163 | case NL_SUBSYSTEM: 164 | if (sscanf(q, "%x%x", &id3, &id4) != 2 || q[9] != ' ') 165 | goto parserr; 166 | q += 10; 167 | cat = NL_SUBSYSTEM; 168 | break; 169 | case NL_CLASS: 170 | case NL_SUBCLASS: 171 | case NL_PROGIF: 172 | if (sscanf(q, "%x", &id3) != 1 || q[2] != ' ') 173 | goto parserr; 174 | q += 3; 175 | cat = NL_PROGIF; 176 | id4 = 0; 177 | break; 178 | default: 179 | goto parserr; 180 | } 181 | else 182 | goto parserr; 183 | while (*q == ' ') 184 | q++; 185 | if (!*q) 186 | goto parserr; 187 | if (nl_add(a, cat, id1, id2, id3, id4, q)) 188 | fprintf(stderr, "%s, line %d: duplicate entry", a->pci_id_file_name, lino); 189 | } 190 | return; 191 | 192 | parserr: 193 | fprintf(stderr, "%s, line %d: parse error", a->pci_id_file_name, lino); 194 | } 195 | 196 | static void 197 | load_name_list(struct pci_access *a) 198 | { 199 | int fd; 200 | struct stat st; 201 | 202 | fd = open(a->pci_id_file_name, O_RDONLY); 203 | if (fd < 0) 204 | { 205 | a->numeric_ids = 1; 206 | return; 207 | } 208 | if (fstat(fd, &st) < 0) 209 | err_name_list(a, "stat"); 210 | a->nl_list = malloc(st.st_size + 1); 211 | if (read(fd, a->nl_list, st.st_size) != st.st_size) 212 | err_name_list(a, "read"); 213 | a->nl_list[st.st_size] = 0; 214 | a->nl_hash = malloc(sizeof(struct nl_entry *) * HASH_SIZE); 215 | bzero(a->nl_hash, sizeof(struct nl_entry *) * HASH_SIZE); 216 | parse_name_list(a); 217 | close(fd); 218 | } 219 | 220 | void 221 | pci_free_name_list(struct pci_access *a) 222 | { 223 | int i = 0; 224 | struct nl_entry *n = NULL, *temp = NULL; 225 | 226 | free(a->nl_list); 227 | a->nl_list = NULL; 228 | if (a->nl_hash != NULL) { 229 | for (i = 0; i < HASH_SIZE; i++) { 230 | if (a->nl_hash[i] != NULL) { 231 | n = a->nl_hash[i]; 232 | do { 233 | temp = n->next; 234 | free (n); 235 | n = temp; 236 | } while (temp != NULL); 237 | } 238 | } 239 | } 240 | free(a->nl_hash); 241 | a->nl_hash = NULL; 242 | } 243 | 244 | char * 245 | pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4) 246 | { 247 | int num = a->numeric_ids; 248 | int res; 249 | struct nl_entry *n; 250 | 251 | if (flags & PCI_LOOKUP_NUMERIC) 252 | { 253 | flags &= PCI_LOOKUP_NUMERIC; 254 | num = 1; 255 | } 256 | if (!a->nl_hash && !num) 257 | { 258 | load_name_list(a); 259 | num = a->numeric_ids; 260 | } 261 | switch (flags) 262 | { 263 | case PCI_LOOKUP_VENDOR: 264 | if ((n = nl_lookup(a, num, NL_VENDOR, arg1, 0, 0, 0))) 265 | return n->name; 266 | else 267 | res = snprintf(buf, size, "%04x", arg1); 268 | break; 269 | case PCI_LOOKUP_DEVICE: 270 | if ((n = nl_lookup(a, num, NL_DEVICE, arg1, arg2, 0, 0))) 271 | return n->name; 272 | else 273 | res = snprintf(buf, size, "%04x", arg2); 274 | break; 275 | case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE: 276 | if (!num) 277 | { 278 | struct nl_entry *e, *e2; 279 | e = nl_lookup(a, 0, NL_VENDOR, arg1, 0, 0, 0); 280 | e2 = nl_lookup(a, 0, NL_DEVICE, arg1, arg2, 0, 0); 281 | if (!e) 282 | res = snprintf(buf, size, "Unknown device %04x:%04x", arg1, arg2); 283 | else if (!e2) 284 | res = snprintf(buf, size, "%s: Unknown device %04x", e->name, arg2); 285 | else 286 | res = snprintf(buf, size, "%s %s", e->name, e2->name); 287 | } 288 | else 289 | res = snprintf(buf, size, "%04x:%04x", arg1, arg2); 290 | break; 291 | case PCI_LOOKUP_VENDOR | PCI_LOOKUP_SUBSYSTEM: 292 | if ((n = nl_lookup(a, num, NL_VENDOR, arg3, 0, 0, 0))) 293 | return n->name; 294 | else 295 | res = snprintf(buf, size, "%04x", arg2); 296 | break; 297 | case PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM: 298 | if ((n = nl_lookup(a, num, NL_SUBSYSTEM, arg1, arg2, arg3, arg4))) 299 | return n->name; 300 | else if (arg1 == arg3 && arg2 == arg4 && (n = nl_lookup(a, num, NL_DEVICE, arg1, arg2, 0, 0))) 301 | return n->name; 302 | else 303 | res = snprintf(buf, size, "%04x", arg4); 304 | break; 305 | case PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM: 306 | if (!num) 307 | { 308 | struct nl_entry *e, *e2; 309 | e = nl_lookup(a, 0, NL_VENDOR, arg3, 0, 0, 0); 310 | e2 = nl_lookup(a, 0, NL_SUBSYSTEM, arg1, arg2, arg3, arg4); 311 | if (!e2 && arg1 == arg3 && arg2 == arg4) 312 | /* Cheat for vendors blindly setting subsystem ID same as device ID */ 313 | e2 = nl_lookup(a, 0, NL_DEVICE, arg1, arg2, 0, 0); 314 | if (!e) 315 | res = snprintf(buf, size, "Unknown device %04x:%04x", arg3, arg4); 316 | else if (!e2) 317 | res = snprintf(buf, size, "%s: Unknown device %04x", e->name, arg4); 318 | else 319 | res = snprintf(buf, size, "%s %s", e->name, e2->name); 320 | } 321 | else 322 | res = snprintf(buf, size, "%04x:%04x", arg3, arg4); 323 | break; 324 | case PCI_LOOKUP_CLASS: 325 | if ((n = nl_lookup(a, num, NL_SUBCLASS, arg1 >> 8, arg1 & 0xff, 0, 0))) 326 | return n->name; 327 | else if ((n = nl_lookup(a, num, NL_CLASS, arg1, 0, 0, 0))) 328 | res = snprintf(buf, size, "%s [%04x]", n->name, arg1); 329 | else 330 | res = snprintf(buf, size, "Class %04x", arg1); 331 | break; 332 | case PCI_LOOKUP_PROGIF: 333 | if ((n = nl_lookup(a, num, NL_PROGIF, arg1 >> 8, arg1 & 0xff, arg2, 0))) 334 | return n->name; 335 | if (arg1 == 0x0101) 336 | { 337 | /* IDE controllers have complex prog-if semantics */ 338 | if (arg2 & 0x70) 339 | return NULL; 340 | res = snprintf(buf, size, "%s%s%s%s%s", 341 | (arg2 & 0x80) ? "Master " : "", 342 | (arg2 & 0x08) ? "SecP " : "", 343 | (arg2 & 0x04) ? "SecO " : "", 344 | (arg2 & 0x02) ? "PriP " : "", 345 | (arg2 & 0x01) ? "PriO " : ""); 346 | if (res) 347 | buf[--res] = 0; 348 | break; 349 | } 350 | return NULL; 351 | default: 352 | return ""; 353 | } 354 | if (res == size) 355 | return ""; 356 | else 357 | return buf; 358 | } 359 | -------------------------------------------------------------------------------- /cmd/names.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The PCI Library 3 | * 4 | * Copyright (c) 1997--2002 Martin Mares 5 | * 6 | * Can be freely distributed and used under the terms of the GNU GPL. 7 | */ 8 | 9 | #ifndef _NAMES_H_ 10 | #define _NAMES_H_ 11 | 12 | #define PCI_LOOKUP_VENDOR 1 13 | #define PCI_LOOKUP_DEVICE 2 14 | #define PCI_LOOKUP_CLASS 4 15 | #define PCI_LOOKUP_SUBSYSTEM 8 16 | #define PCI_LOOKUP_PROGIF 16 17 | #define PCI_LOOKUP_NUMERIC 0x10000 18 | 19 | #define PCI_VENDOR_ID 0x00 20 | #define PCI_DEVICE_ID 0x02 21 | 22 | struct pci_access { 23 | unsigned int numeric_ids; 24 | char *pci_id_file_name; 25 | char *nl_list; 26 | struct nl_entry **nl_hash; 27 | }; 28 | 29 | extern char *pci_lookup_name(struct pci_access *a, char *buf, 30 | int size, int flags, unsigned int arg1, unsigned int arg2, 31 | unsigned int arg3, unsigned int arg4); 32 | extern void pci_free_name_list(struct pci_access *a); 33 | 34 | #endif /* _NAMES_H_ */ 35 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # Process this file with autoconf to produce a configure script. 2 | AC_INIT([sysfsutils], [2.1.1], [https://github.com/linux-ras/sysfsutils/issues]) 3 | AC_CONFIG_SRCDIR([cmd/systool.c]) 4 | AC_CONFIG_MACRO_DIR([m4]) 5 | 6 | AM_INIT_AUTOMAKE([1.11 foreign]) 7 | AM_SILENT_RULES([yes]) 8 | 9 | # Checks for KLIBC support (should be before LT_INIT and AC_PROG_CC) 10 | AC_CHECK_KLIBC 11 | 12 | if test "X$KLIBC" = Xyes; then 13 | # Should disable/enable building of shared libraries ... I am open to better 14 | # suggestions though (AC_DISABLE_SHARED and co do not do the right thing in 15 | # a situation like this that its runtime dependent) ... 16 | enable_shared="no" 17 | EXTRA_CFLAGS= 18 | else 19 | # These ones make KLIBC compiles very loud 20 | EXTRA_CFLAGS="-Wshadow -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs" 21 | fi 22 | AM_CONDITIONAL([KLIBC], [test "X$KLIBC" = Xyes]) 23 | AC_SUBST([EXTRA_CFLAGS]) 24 | 25 | AC_ARG_WITH([pci.ids], 26 | [AS_HELP_STRING([--with-pci.ids=PATHNAME], 27 | [specify the pci.ids database PATHNAME])], 28 | [PCI_IDS_PATHNAME=$with_pci_ids], 29 | [PCI_IDS_PATHNAME="/usr/share/misc/pci.ids"]) 30 | AC_DEFINE_UNQUOTED([PCI_IDS_PATHNAME], ["$PCI_IDS_PATHNAME"], 31 | [pci.ids database pathname]) 32 | 33 | # Checks for library support. 34 | LT_INIT 35 | AC_CACHE_CHECK([for --version-script linker flag], [sysfs_cv_version_script], [ 36 | echo "{ global: symbol; local: *; };" >conftest.map 37 | save_LDFLAGS=$LDFLAGS 38 | LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map" 39 | AC_LINK_IFELSE([ 40 | AC_LANG_PROGRAM([], []) 41 | ], [ 42 | sysfs_cv_version_script=yes 43 | ], [ 44 | sysfs_cv_version_script=no 45 | ]) 46 | LDFLAGS="$save_LDFLAGS" 47 | rm -f conftest.map 48 | ]) 49 | AM_CONDITIONAL([HAVE_LINKER_VERSION_SCRIPT], 50 | [test "x$sysfs_cv_version_script" = "xyes"]) 51 | 52 | # Checks for programs. 53 | AC_PROG_CC 54 | AC_PROG_INSTALL 55 | AC_PROG_MAKE_SET 56 | 57 | # Checks for header files. 58 | AC_HEADER_DIRENT 59 | AC_CHECK_HEADERS([fcntl.h malloc.h stdlib.h string.h unistd.h]) 60 | 61 | # Checks for typedefs, structures, and compiler characteristics. 62 | AC_C_CONST 63 | AC_C_INLINE 64 | AC_TYPE_SIZE_T 65 | 66 | # Checks for library functions. 67 | AC_FUNC_LSTAT 68 | AC_FUNC_MALLOC 69 | AC_FUNC_STAT 70 | AC_CHECK_FUNCS([bzero isascii memset strchr strerror strrchr strstr strtol]) 71 | 72 | AC_CONFIG_FILES([Makefile 73 | lib/Makefile 74 | lib/libsysfs.pc 75 | cmd/Makefile 76 | test/Makefile]) 77 | AC_CONFIG_HEADERS([config.h]) 78 | AC_OUTPUT 79 | -------------------------------------------------------------------------------- /include/dlist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dlist.h 3 | * 4 | * Copyright (C) 2003 Eric J Bohm 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | * 20 | */ 21 | #ifndef _DLIST_H_ 22 | #define _DLIST_H_ 23 | 24 | /* Double linked list header. 25 | 26 | * navigate your list with DLIST_PREV and DLIST_NEXT. These are macros 27 | * so function call overhead is minimized. 28 | 29 | * Supports perl style push, pop, shift, unshift list semantics. 30 | 31 | * You allocate the data and give dlist the pointer. If your data is 32 | * complex set the dlist->del_func to a an appropriate delete using 33 | * dlist_new_with_delete. Your delete function must match 34 | (void * )(del(void *) 35 | *Otherwise dlist will just use free. 36 | 37 | * NOTE: The small amount of pain involved in doing that allows us to 38 | * avoid copy in copy out semantics. 39 | 40 | * Dlist uses an internal mark pointer to keep track of where you are 41 | * in the list. 42 | 43 | * insert and delete take a directional parameter. Where direction 44 | * corresponds to the direction in which you want the list to go. 45 | * true direction corresponded to progressing forward in the last 46 | * false to regressing in the list. 47 | * so a dlist_insert(yourlist,item,1) will insert it after the mark 48 | * so a dlist_insert(yourlist,item,0) will insert it before the mark 49 | * any insert will move the mark to the new node regardless of the direction. 50 | 51 | * Just use the dlist_(insert|delete)_(before|after) macros if you do not want 52 | * to think about it. 53 | 54 | */ 55 | 56 | #include 57 | 58 | typedef struct dl_node { 59 | struct dl_node *prev; 60 | struct dl_node *next; 61 | void *data; 62 | } DL_node; 63 | 64 | typedef struct dlist { 65 | DL_node *marker; 66 | unsigned long count; 67 | size_t data_size; 68 | void (*del_func)(void *); 69 | DL_node headnode; 70 | DL_node *head; 71 | } Dlist; 72 | 73 | #ifdef __cplusplus 74 | extern "C" { 75 | #endif 76 | 77 | Dlist *dlist_new(size_t datasize); 78 | Dlist *dlist_new_with_delete(size_t datasize,void (*del_func)(void*)); 79 | void *_dlist_mark_move(Dlist *list,int direction); 80 | void *dlist_mark(Dlist *); 81 | void dlist_start(Dlist *); 82 | void dlist_end(Dlist *); 83 | void dlist_move(struct dlist *source, struct dlist *dest, struct dl_node *target,int direction); 84 | void *dlist_insert(Dlist *,void *,int) ; 85 | 86 | void *dlist_insert_sorted(struct dlist *list, void *new_elem, int (*sorter)(void *, void *)); 87 | 88 | void dlist_delete(Dlist *,int); 89 | 90 | void dlist_push(Dlist *,void *); 91 | 92 | void dlist_unshift(Dlist *,void *); 93 | void dlist_unshift_sorted(Dlist *,void *,int (*sorter)(void *, void *)); 94 | 95 | void *dlist_pop(Dlist *); 96 | 97 | void *dlist_shift(Dlist *); 98 | 99 | void dlist_destroy(Dlist *); 100 | 101 | int _dlist_merge(struct dlist *listsource, struct dlist *listdest, unsigned int passcount, int (*compare)(void *, void *)); 102 | 103 | void *dlist_find_custom(struct dlist *list, void *target, int (*comp)(void *, void *)); 104 | 105 | void dlist_sort_custom(struct dlist *list, int (*compare)(void *, void *)); 106 | 107 | void dlist_filter_sort(struct dlist *list, int (*filter) (void *), 108 | int (*compare) (void *, void *)); 109 | 110 | void _dlist_swap(struct dlist *list, struct dl_node *a, struct dl_node *b); 111 | 112 | void dlist_transform(struct dlist *list, void (*node_operation)(void *)); 113 | 114 | 115 | /* 116 | * _dlist_remove is for internal use only 117 | * _dlist_mark_move is for internal use only 118 | */ 119 | void *_dlist_remove(struct dlist *,struct dl_node *,int ); 120 | void *_dlist_insert_dlnode(struct dlist *list,struct dl_node *new_node,int direction); 121 | 122 | #define dlist_prev(A) _dlist_mark_move((A),0) 123 | #define dlist_next(A) _dlist_mark_move((A),1) 124 | 125 | #define dlist_insert_before(A,B) dlist_insert((A),(B),0) 126 | #define dlist_insert_after(A,B) dlist_insert((A),(B),1) 127 | 128 | #define dlist_delete_before(A) dlist_delete((A),0) 129 | #define dlist_delete_after(A) dlist_delete((A),1) 130 | 131 | /** 132 | * provide for loop header which iterates the mark from start to end 133 | * list: the dlist pointer, use dlist_mark(list) to get iterator 134 | */ 135 | #define dlist_for_each(list) \ 136 | for(dlist_start(list),dlist_next(list); \ 137 | (list)->marker!=(list)->head;dlist_next(list)) 138 | 139 | /** 140 | * provide for loop header which iterates the mark from end to start 141 | * list: the dlist pointer, use dlist_mark(list) to get iterator 142 | */ 143 | #define dlist_for_each_rev(list) \ 144 | for(dlist_end(list),dlist_prev(list); \ 145 | (list)->marker!=(list)->head;dlist_prev(list)) 146 | 147 | /** 148 | * provide for loop header which iterates through the list without moving mark 149 | * list: the dlist_pointer 150 | * iterator: dl_node pointer to iterate 151 | */ 152 | #define dlist_for_each_nomark(list,iterator) \ 153 | for((iterator)=(list)->head->next; (iterator)!=(list)->head; \ 154 | (iterator)=(iterator)->next) 155 | 156 | /** 157 | * provide for loop header which iterates through the list without moving mark 158 | * in reverse 159 | * list: the dlist_pointer 160 | * iterator: dl_node pointer to iterate 161 | */ 162 | #define dlist_for_each_nomark_rev(list,iterator) \ 163 | for((iterator)=(list)->head->prev; (iterator)!=(list)->head; \ 164 | (iterator)=(iterator)->prev) 165 | /** 166 | * provide for loop header which iterates through the list providing a 167 | * data iterator 168 | * list: the dlist pointer 169 | * data_iterator: the pointer of type datatype to iterate 170 | * datatype: actual type of the contents in the dl_node->data 171 | */ 172 | 173 | #define dlist_for_each_data(list,data_iterator,datatype) \ 174 | for(dlist_start(list), (data_iterator)=(datatype *) dlist_next(list); \ 175 | (list)->marker!=(list)->head;(data_iterator)=(datatype *) dlist_next(list)) 176 | 177 | /** 178 | * provide for loop header which iterates through the list providing a 179 | * data iterator in reverse 180 | * list: the dlist pointer 181 | * data_iterator: the pointer of type datatype to iterate 182 | * datatype: actual type of the contents in the dl_node->data 183 | */ 184 | #define dlist_for_each_data_rev(list,data_iterator,datatype) \ 185 | for(dlist_end(list), (data_iterator)=(datatype *) dlist_prev(list); \ 186 | (list)->marker!=(list)->head;(data_iterator)=(datatype *) dlist_prev(list)) 187 | 188 | /** 189 | * provide for loop header which iterates through the list providing a 190 | * data iterator without moving the mark 191 | * list: the dlist pointer 192 | * iterator: the dl_node pointer to iterate 193 | * data_iterator: the pointer of type datatype to iterate 194 | * datatype: actual type of the contents in the dl_node->data 195 | */ 196 | 197 | #define dlist_for_each_data_nomark(list,iterator,data_iterator,datatype) \ 198 | for((iterator)=(list)->head->next, (data_iterator)=(datatype *) (iterator)->data; \ 199 | (iterator)!=(list)->head;(iterator)=(iterator)->next,(data_iterator)=(datatype *) (iterator)) 200 | 201 | /** 202 | * provide for loop header which iterates through the list providing a 203 | * data iterator in reverse without moving the mark 204 | * list: the dlist pointer 205 | * iterator: the dl_node pointer to iterate 206 | * data_iterator: the pointer of type datatype to iterate 207 | * datatype: actual type of the contents in the dl_node->data 208 | */ 209 | #define dlist_for_each_data_nomark_rev(list,iterator, data_iterator,datatype) \ 210 | for((iterator)=(list)->head->prev, (data_iterator)=(datatype *) (iterator)->data; \ 211 | (iterator)!=(list)->head;(iterator)=(iterator)->prev,(data_iterator)=(datatype *) (iterator)) 212 | 213 | 214 | #ifdef __cplusplus 215 | } 216 | #endif 217 | 218 | #endif /* _DLIST_H_ */ 219 | -------------------------------------------------------------------------------- /include/libsysfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libsysfs.h 3 | * 4 | * Header Definitions for libsysfs 5 | * 6 | * Copyright (C) IBM Corp. 2004-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 | #ifndef _LIBSYSFS_H_ 24 | #define _LIBSYSFS_H_ 25 | 26 | #include 27 | #include 28 | #include "dlist.h" 29 | 30 | #define SYSFS_FSTYPE_NAME "sysfs" 31 | #define SYSFS_PROC_MNTS "/proc/mounts" 32 | #define SYSFS_BUS_NAME "bus" 33 | #define SYSFS_CLASS_NAME "class" 34 | #define SYSFS_BLOCK_NAME "block" 35 | #define SYSFS_DEVICES_NAME "devices" 36 | #define SYSFS_DRIVERS_NAME "drivers" 37 | #define SYSFS_MODULE_NAME "module" 38 | #define SYSFS_NAME_ATTRIBUTE "name" 39 | #define SYSFS_MOD_PARM_NAME "parameters" 40 | #define SYSFS_MOD_SECT_NAME "sections" 41 | #define SYSFS_UNKNOWN "unknown" 42 | #define SYSFS_PATH_ENV "SYSFS_PATH" 43 | 44 | #define SYSFS_PATH_MAX 256 45 | #define SYSFS_NAME_LEN 64 46 | #define SYSFS_BUS_ID_SIZE 32 47 | 48 | /* mount path for sysfs, can be overridden by exporting SYSFS_PATH */ 49 | #define SYSFS_MNT_PATH "/sys" 50 | 51 | enum sysfs_attribute_method { 52 | SYSFS_METHOD_SHOW = 0x01, /* attr can be read by user */ 53 | SYSFS_METHOD_STORE = 0x02, /* attr can be changed by user */ 54 | }; 55 | 56 | /* 57 | * NOTE: 58 | * 1. We have the statically allocated "name" as the first element of all 59 | * the structures. This feature is used in the "sorter" function for dlists 60 | * 2. As is the case with attrlist 61 | * 3. As is the case with path 62 | */ 63 | struct sysfs_attribute { 64 | char name[SYSFS_NAME_LEN]; 65 | char path[SYSFS_PATH_MAX]; 66 | char *value; 67 | unsigned short len; /* value length */ 68 | enum sysfs_attribute_method method; /* show and store */ 69 | }; 70 | 71 | struct sysfs_driver { 72 | char name[SYSFS_NAME_LEN]; 73 | char path[SYSFS_PATH_MAX]; 74 | struct dlist *attrlist; 75 | char bus[SYSFS_NAME_LEN]; 76 | 77 | /* Private: for internal use only */ 78 | struct sysfs_module *module; 79 | struct dlist *devices; 80 | }; 81 | 82 | struct sysfs_device { 83 | char name[SYSFS_NAME_LEN]; 84 | char path[SYSFS_PATH_MAX]; 85 | struct dlist *attrlist; 86 | char bus_id[SYSFS_NAME_LEN]; 87 | char bus[SYSFS_NAME_LEN]; 88 | char driver_name[SYSFS_NAME_LEN]; 89 | char subsystem[SYSFS_NAME_LEN]; 90 | 91 | /* Private: for internal use only */ 92 | struct sysfs_device *parent; 93 | /* NOTE - we still don't populate this */ 94 | struct dlist *children; 95 | }; 96 | 97 | struct sysfs_bus { 98 | char name[SYSFS_NAME_LEN]; 99 | char path[SYSFS_PATH_MAX]; 100 | struct dlist *attrlist; 101 | 102 | /* Private: for internal use only */ 103 | struct dlist *drivers; 104 | struct dlist *devices; 105 | }; 106 | 107 | struct sysfs_class_device { 108 | char name[SYSFS_NAME_LEN]; 109 | char path[SYSFS_PATH_MAX]; 110 | struct dlist *attrlist; 111 | char classname[SYSFS_NAME_LEN]; 112 | 113 | /* Private: for internal use only */ 114 | struct sysfs_class_device *parent; 115 | struct sysfs_device *sysdevice; /* NULL if virtual */ 116 | }; 117 | 118 | struct sysfs_class { 119 | char name[SYSFS_NAME_LEN]; 120 | char path[SYSFS_PATH_MAX]; 121 | struct dlist *attrlist; 122 | 123 | /* Private: for internal use only */ 124 | struct dlist *devices; 125 | }; 126 | 127 | struct sysfs_module { 128 | char name[SYSFS_NAME_LEN]; 129 | char path[SYSFS_PATH_MAX]; 130 | struct dlist *attrlist; 131 | struct dlist *parmlist; 132 | struct dlist *sections; 133 | }; 134 | 135 | #ifdef __cplusplus 136 | extern "C" { 137 | #endif 138 | 139 | /* 140 | * Function Prototypes 141 | */ 142 | extern int sysfs_get_mnt_path(char *mnt_path, size_t len); 143 | extern int sysfs_remove_trailing_slash(char *path); 144 | extern int sysfs_get_name_from_path(const char *path, char *name, size_t len); 145 | extern int sysfs_path_is_dir(const char *path); 146 | extern int sysfs_path_is_link(const char *path); 147 | extern int sysfs_path_is_file(const char *path); 148 | extern int sysfs_get_link(const char *path, char *target, size_t len); 149 | extern struct dlist *sysfs_open_directory_list(const char *path); 150 | extern struct dlist *sysfs_open_link_list(const char *path); 151 | extern void sysfs_close_list(struct dlist *list); 152 | 153 | /* sysfs directory and file access */ 154 | extern void sysfs_close_attribute(struct sysfs_attribute *sysattr); 155 | extern struct sysfs_attribute *sysfs_open_attribute(const char *path); 156 | extern int sysfs_read_attribute(struct sysfs_attribute *sysattr); 157 | extern int sysfs_write_attribute(struct sysfs_attribute *sysattr, 158 | const char *new_value, size_t len); 159 | extern struct sysfs_device *sysfs_read_dir_subdirs(const char *path); 160 | /* sysfs driver access */ 161 | extern void sysfs_close_driver(struct sysfs_driver *driver); 162 | extern struct sysfs_driver *sysfs_open_driver 163 | (const char *bus_name, const char *drv_name); 164 | extern struct sysfs_driver *sysfs_open_driver_path(const char *path); 165 | extern struct sysfs_attribute *sysfs_get_driver_attr 166 | (struct sysfs_driver *drv, const char *name); 167 | extern struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *drv); 168 | extern struct dlist *sysfs_get_driver_devices(struct sysfs_driver *drv); 169 | extern struct sysfs_module *sysfs_get_driver_module(struct sysfs_driver *drv); 170 | 171 | /* generic sysfs device access */ 172 | extern void sysfs_close_device_tree(struct sysfs_device *device); 173 | extern struct sysfs_device *sysfs_open_device_tree(const char *path); 174 | extern void sysfs_close_device(struct sysfs_device *dev); 175 | extern struct sysfs_device *sysfs_open_device 176 | (const char *bus, const char *bus_id); 177 | extern struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev); 178 | extern struct sysfs_device *sysfs_open_device_path(const char *path); 179 | extern int sysfs_get_device_bus(struct sysfs_device *dev); 180 | extern struct sysfs_attribute *sysfs_get_device_attr 181 | (struct sysfs_device *dev, const char *name); 182 | extern struct dlist *sysfs_get_device_attributes 183 | (struct sysfs_device *dev); 184 | 185 | /* generic sysfs class access */ 186 | extern void sysfs_close_class_device(struct sysfs_class_device *dev); 187 | extern struct sysfs_class_device *sysfs_open_class_device_path 188 | (const char *path); 189 | extern struct sysfs_class_device *sysfs_open_class_device 190 | (const char *classname, const char *name); 191 | extern struct sysfs_class_device *sysfs_get_classdev_parent 192 | (struct sysfs_class_device *clsdev); 193 | extern struct sysfs_attribute *sysfs_get_classdev_attr 194 | (struct sysfs_class_device *clsdev, const char *name); 195 | extern struct dlist *sysfs_get_classdev_attributes 196 | (struct sysfs_class_device *clsdev); 197 | extern struct sysfs_device *sysfs_get_classdev_device 198 | (struct sysfs_class_device *clsdev); 199 | extern void sysfs_close_class(struct sysfs_class *cls); 200 | extern struct sysfs_class *sysfs_open_class(const char *name); 201 | extern struct sysfs_class_device *sysfs_get_class_device 202 | (struct sysfs_class *cls, const char *name); 203 | extern struct dlist *sysfs_get_class_devices(struct sysfs_class *cls); 204 | 205 | /* generic sysfs bus access */ 206 | extern void sysfs_close_bus(struct sysfs_bus *bus); 207 | extern struct sysfs_bus *sysfs_open_bus(const char *name); 208 | extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus); 209 | extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus); 210 | extern struct sysfs_device *sysfs_get_bus_device 211 | (struct sysfs_bus *bus, const char *id); 212 | extern struct sysfs_driver *sysfs_get_bus_driver 213 | (struct sysfs_bus *bus, const char *drvname); 214 | 215 | /* generic sysfs module access */ 216 | extern void sysfs_close_module(struct sysfs_module *module); 217 | extern struct sysfs_module *sysfs_open_module_path(const char *path); 218 | extern struct sysfs_module *sysfs_open_module(const char *name); 219 | extern struct dlist *sysfs_get_module_parms(struct sysfs_module *module); 220 | extern struct dlist *sysfs_get_module_sections(struct sysfs_module *module); 221 | extern struct dlist *sysfs_get_module_attributes(struct sysfs_module *module); 222 | extern struct sysfs_attribute *sysfs_get_module_attr 223 | (struct sysfs_module *module, const char *name); 224 | extern struct sysfs_attribute *sysfs_get_module_parm 225 | (struct sysfs_module *module, const char *parm); 226 | extern struct sysfs_attribute *sysfs_get_module_section 227 | (struct sysfs_module *module, const char *section); 228 | 229 | /** 230 | * sort_list: sorter function to keep list elements sorted in alphabetical 231 | * order. Just does a strncmp as you can see :) 232 | * 233 | * Returns 1 if less than 0 otherwise 234 | * 235 | * NOTE: We take care to have a statically allocated "name" as the first 236 | * lement of all libsysfs structures. Hence, this function will work 237 | * AS IS for _ALL_ the lists that have to be sorted. 238 | */ 239 | static inline int sort_list(void *new_elem, void *old_elem) 240 | { 241 | return ((strncmp(((struct sysfs_attribute *)new_elem)->name, 242 | ((struct sysfs_attribute *)old_elem)->name, 243 | strlen(((struct sysfs_attribute *)new_elem)->name))) < 0 ? 1 : 0); 244 | } 245 | 246 | 247 | #ifdef __cplusplus 248 | } 249 | #endif 250 | 251 | #endif /* _LIBSYSFS_H_ */ 252 | -------------------------------------------------------------------------------- /lib/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = libsysfs.pc.in libsysfs.map 2 | 3 | pkgconfigdir = $(libdir)/pkgconfig 4 | pkgconfig_DATA = libsysfs.pc 5 | 6 | lib_LTLIBRARIES = libsysfs.la 7 | libsysfs_la_SOURCES = sysfs_utils.c sysfs_attr.c sysfs_class.c dlist.c \ 8 | sysfs_device.c sysfs_driver.c sysfs_bus.c sysfs_module.c sysfs.h 9 | libsysfs_la_CPPFLAGS = -I$(top_srcdir)/include 10 | libsysfs_la_LDFLAGS = -version-info 2:1:0 11 | if HAVE_LINKER_VERSION_SCRIPT 12 | libsysfs_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libsysfs.map 13 | EXTRA_libsysfs_la_DEPENDENCIES = libsysfs.map 14 | endif 15 | libsysfs_la_CFLAGS = -Wall -W -Wextra -Wstrict-prototypes $(EXTRA_CFLAGS) 16 | -------------------------------------------------------------------------------- /lib/libsysfs.map: -------------------------------------------------------------------------------- 1 | LIBSYSFS_PRIVATE { 2 | global: 3 | /* 4 | * The following symbols are used by systool, but are not intended for 5 | * public use. 6 | */ 7 | my_strncat; 8 | my_strncpy; 9 | 10 | local: 11 | *; 12 | }; 13 | 14 | LIBSYSFS_2.0.0 { 15 | global: 16 | /* 17 | * The header exposes these via macros, so they need to be marked as 18 | * public, even though the underscore prefix would indicate otherwise. 19 | */ 20 | _dlist_insert_dlnode; 21 | _dlist_mark_move; 22 | _dlist_merge; 23 | _dlist_remove; 24 | _dlist_swap; 25 | 26 | dlist_delete; 27 | dlist_destroy; 28 | dlist_end; 29 | dlist_filter_sort; 30 | dlist_find_custom; 31 | dlist_insert; 32 | dlist_insert_sorted; 33 | dlist_mark; 34 | dlist_move; 35 | dlist_new; 36 | dlist_new_with_delete; 37 | dlist_pop; 38 | dlist_push; 39 | dlist_shift; 40 | dlist_sort_custom; 41 | dlist_start; 42 | dlist_transform; 43 | dlist_unshift; 44 | dlist_unshift_sorted; 45 | 46 | sysfs_close_attribute; 47 | sysfs_close_bus; 48 | sysfs_close_class; 49 | sysfs_close_class_device; 50 | sysfs_close_device; 51 | sysfs_close_device_tree; 52 | sysfs_close_driver; 53 | sysfs_close_list; 54 | sysfs_close_module; 55 | sysfs_get_bus_device; 56 | sysfs_get_bus_devices; 57 | sysfs_get_bus_driver; 58 | sysfs_get_bus_drivers; 59 | sysfs_get_class_device; 60 | sysfs_get_class_devices; 61 | sysfs_get_classdev_attr; 62 | sysfs_get_classdev_attributes; 63 | sysfs_get_classdev_device; 64 | sysfs_get_classdev_parent; 65 | sysfs_get_device_attr; 66 | sysfs_get_device_attributes; 67 | sysfs_get_device_bus; 68 | sysfs_get_device_parent; 69 | sysfs_get_driver_attr; 70 | sysfs_get_driver_attributes; 71 | sysfs_get_driver_devices; 72 | sysfs_get_driver_module; 73 | sysfs_get_link; 74 | sysfs_get_mnt_path; 75 | sysfs_get_module_attr; 76 | sysfs_get_module_attributes; 77 | sysfs_get_module_parm; 78 | sysfs_get_module_parms; 79 | sysfs_get_module_section; 80 | sysfs_get_module_sections; 81 | sysfs_get_name_from_path; 82 | sysfs_open_attribute; 83 | sysfs_open_bus; 84 | sysfs_open_class; 85 | sysfs_open_class_device; 86 | sysfs_open_class_device_path; 87 | sysfs_open_device; 88 | sysfs_open_device_path; 89 | sysfs_open_directory_list; 90 | sysfs_open_driver; 91 | sysfs_open_driver_path; 92 | sysfs_open_module; 93 | sysfs_open_module_path; 94 | sysfs_path_is_dir; 95 | sysfs_path_is_file; 96 | sysfs_path_is_link; 97 | sysfs_read_attribute; 98 | sysfs_remove_trailing_slash; 99 | sysfs_write_attribute; 100 | } LIBSYSFS_PRIVATE; 101 | 102 | LIBSYSFS_2.1.0 { 103 | global: 104 | sysfs_open_device_tree; 105 | sysfs_open_link_list; 106 | sysfs_read_dir_subdirs; 107 | } LIBSYSFS_2.0.0; 108 | -------------------------------------------------------------------------------- /lib/libsysfs.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libsysfs 7 | Description: interface to Linux sysfs 8 | Version: @VERSION@ 9 | URL: https://github.com/linux-ras/sysfsutils 10 | Libs: -L${libdir} -lsysfs 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /lib/sysfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sysfs.h 3 | * 4 | * Internal Header Definitions 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 | #ifndef _SYSFS_H_ 24 | #define _SYSFS_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | extern char *my_strncpy(char *to, const char *from, size_t max); 37 | #define safestrcpy(to, from) my_strncpy(to, from, sizeof(to)) 38 | #define safestrcpymax(to, from, max) my_strncpy(to, from, max) 39 | 40 | extern char *my_strncat(char *to, const char *from, size_t max); 41 | #define safestrcat(to, from) my_strncat(to, from, sizeof(to) - strlen(to) - 1) 42 | 43 | #define safestrcatmax(to, from, max) \ 44 | do { \ 45 | to[max-1] = '\0'; \ 46 | strncat(to, from, max - strlen(to)-1); \ 47 | } while (0) 48 | 49 | /* Private routine for dlist integration. */ 50 | extern void sysfs_close_dev_tree(void *dev); 51 | 52 | extern struct sysfs_attribute *get_attribute(void *dev, const char *name); 53 | extern struct dlist *read_dir_subdirs(const char *path); 54 | extern struct dlist *read_dir_links(const char *path); 55 | extern struct dlist *get_dev_attributes_list(void *dev); 56 | extern struct dlist *get_attributes_list(struct dlist *alist, const char *path); 57 | 58 | /* Debugging */ 59 | #ifdef DEBUG 60 | #define dbg_printf(format, arg...) fprintf(stderr, format, ## arg) 61 | #else 62 | #define dbg_printf(format, arg...) do { } while (0) 63 | #endif 64 | 65 | #endif /* _SYSFS_H_ */ 66 | -------------------------------------------------------------------------------- /lib/sysfs_bus.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sysfs_bus.c 3 | * 4 | * Generic bus 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 | 24 | #include "config.h" 25 | 26 | #include "libsysfs.h" 27 | #include "sysfs.h" 28 | 29 | static void sysfs_close_dev(void *dev) 30 | { 31 | sysfs_close_device((struct sysfs_device *)dev); 32 | } 33 | 34 | static void sysfs_close_drv(void *drv) 35 | { 36 | sysfs_close_driver((struct sysfs_driver *)drv); 37 | } 38 | 39 | /* 40 | * compares names. 41 | * @a: name looked for 42 | * @b: sysfs_device comparing being compared 43 | * returns 1 if a==b->name or 0 not equal 44 | */ 45 | static int name_equal(void *a, void *b) 46 | { 47 | if (!a || !b) 48 | return 0; 49 | 50 | if (strcmp(((char *)a), ((struct sysfs_device *)b)->name) == 0) 51 | return 1; 52 | 53 | return 0; 54 | } 55 | 56 | /** 57 | * sysfs_close_bus: close single bus 58 | * @bus: bus structure 59 | */ 60 | void sysfs_close_bus(struct sysfs_bus *bus) 61 | { 62 | if (bus) { 63 | if (bus->attrlist) 64 | dlist_destroy(bus->attrlist); 65 | if (bus->devices) 66 | dlist_destroy(bus->devices); 67 | if (bus->drivers) 68 | dlist_destroy(bus->drivers); 69 | free(bus); 70 | } 71 | } 72 | 73 | /** 74 | * alloc_bus: mallocs new bus structure 75 | * returns sysfs_bus_bus struct or NULL 76 | */ 77 | static struct sysfs_bus *alloc_bus(void) 78 | { 79 | return (struct sysfs_bus *)calloc(1, sizeof(struct sysfs_bus)); 80 | } 81 | 82 | /** 83 | * sysfs_get_bus_devices: gets all devices for bus 84 | * @bus: bus to get devices for 85 | * returns dlist of devices with success and NULL with failure 86 | */ 87 | struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus) 88 | { 89 | struct sysfs_device *dev; 90 | struct dlist *linklist; 91 | char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; 92 | char target[SYSFS_PATH_MAX]; 93 | char *curlink; 94 | 95 | if (!bus) { 96 | errno = EINVAL; 97 | return NULL; 98 | } 99 | memset(path, 0, SYSFS_PATH_MAX); 100 | safestrcpy(path, bus->path); 101 | safestrcat(path, "/"); 102 | safestrcat(path, SYSFS_DEVICES_NAME); 103 | 104 | linklist = read_dir_links(path); 105 | if (linklist) { 106 | dlist_for_each_data(linklist, curlink, char) { 107 | if (bus->devices) { 108 | dev = (struct sysfs_device *) 109 | dlist_find_custom(bus->devices, 110 | (void *)curlink, name_equal); 111 | if (dev) 112 | continue; 113 | } 114 | safestrcpy(devpath, path); 115 | safestrcat(devpath, "/"); 116 | safestrcat(devpath, curlink); 117 | if (sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) { 118 | dbg_printf("Error getting link - %s\n", devpath); 119 | continue; 120 | } 121 | dev = sysfs_open_device_path(target); 122 | if (!dev) { 123 | dbg_printf("Error opening device at %s\n", 124 | target); 125 | continue; 126 | } 127 | if (!bus->devices) 128 | bus->devices = dlist_new_with_delete 129 | (sizeof(struct sysfs_device), 130 | sysfs_close_dev); 131 | dlist_unshift_sorted(bus->devices, dev, sort_list); 132 | } 133 | sysfs_close_list(linklist); 134 | } 135 | return (bus->devices); 136 | } 137 | 138 | /** 139 | * sysfs_get_bus_drivers: gets all drivers for bus 140 | * @bus: bus to get devices for 141 | * returns dlist of devices with success and NULL with failure 142 | */ 143 | struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus) 144 | { 145 | struct sysfs_driver *drv; 146 | struct dlist *dirlist; 147 | char path[SYSFS_PATH_MAX], drvpath[SYSFS_PATH_MAX]; 148 | char *curdir; 149 | 150 | if (!bus) { 151 | errno = EINVAL; 152 | return NULL; 153 | } 154 | memset(path, 0, SYSFS_PATH_MAX); 155 | safestrcpy(path, bus->path); 156 | safestrcat(path, "/"); 157 | safestrcat(path, SYSFS_DRIVERS_NAME); 158 | 159 | dirlist = read_dir_subdirs(path); 160 | if (dirlist) { 161 | dlist_for_each_data(dirlist, curdir, char) { 162 | if (bus->drivers) { 163 | drv = (struct sysfs_driver *) 164 | dlist_find_custom(bus->drivers, 165 | (void *)curdir, name_equal); 166 | if (drv) 167 | continue; 168 | } 169 | safestrcpy(drvpath, path); 170 | safestrcat(drvpath, "/"); 171 | safestrcat(drvpath, curdir); 172 | drv = sysfs_open_driver_path(drvpath); 173 | if (!drv) { 174 | dbg_printf("Error opening driver at %s\n", 175 | drvpath); 176 | continue; 177 | } 178 | if (!bus->drivers) 179 | bus->drivers = dlist_new_with_delete 180 | (sizeof(struct sysfs_driver), 181 | sysfs_close_drv); 182 | dlist_unshift_sorted(bus->drivers, drv, sort_list); 183 | } 184 | sysfs_close_list(dirlist); 185 | } 186 | return (bus->drivers); 187 | } 188 | 189 | /** 190 | * sysfs_open_bus: opens specific bus and all its devices on system 191 | * returns sysfs_bus structure with success or NULL with error. 192 | */ 193 | struct sysfs_bus *sysfs_open_bus(const char *name) 194 | { 195 | struct sysfs_bus *bus; 196 | char buspath[SYSFS_PATH_MAX]; 197 | 198 | if (!name) { 199 | errno = EINVAL; 200 | return NULL; 201 | } 202 | 203 | memset(buspath, 0, SYSFS_PATH_MAX); 204 | if (sysfs_get_mnt_path(buspath, SYSFS_PATH_MAX)) { 205 | dbg_printf("Sysfs not supported on this system\n"); 206 | return NULL; 207 | } 208 | 209 | safestrcat(buspath, "/"); 210 | safestrcat(buspath, SYSFS_BUS_NAME); 211 | safestrcat(buspath, "/"); 212 | safestrcat(buspath, name); 213 | if (sysfs_path_is_dir(buspath)) { 214 | dbg_printf("Invalid path to bus: %s\n", buspath); 215 | return NULL; 216 | } 217 | bus = alloc_bus(); 218 | if (!bus) { 219 | dbg_printf("calloc failed\n"); 220 | return NULL; 221 | } 222 | safestrcpy(bus->name, name); 223 | safestrcpy(bus->path, buspath); 224 | if (sysfs_remove_trailing_slash(bus->path)) { 225 | dbg_printf("Incorrect path to bus %s\n", bus->path); 226 | sysfs_close_bus(bus); 227 | return NULL; 228 | } 229 | 230 | return bus; 231 | } 232 | 233 | /** 234 | * sysfs_get_bus_device: Get specific device on bus using device's id 235 | * @bus: bus to find device on 236 | * @id: bus_id for device 237 | * returns struct sysfs_device reference or NULL if not found. 238 | */ 239 | struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, 240 | const char *id) 241 | { 242 | struct sysfs_device *dev = NULL; 243 | char devpath[SYSFS_PATH_MAX], target[SYSFS_PATH_MAX]; 244 | 245 | if (!bus || !id) { 246 | errno = EINVAL; 247 | return NULL; 248 | } 249 | 250 | if (bus->devices) { 251 | dev = (struct sysfs_device *)dlist_find_custom 252 | (bus->devices, (void *)id, name_equal); 253 | if (dev) 254 | return dev; 255 | } 256 | safestrcpy(devpath, bus->path); 257 | safestrcat(devpath, "/"); 258 | safestrcat(devpath, SYSFS_DEVICES_NAME); 259 | safestrcat(devpath, "/"); 260 | safestrcat(devpath, id); 261 | if (sysfs_path_is_link(devpath)) { 262 | dbg_printf("No such device %s on bus %s?\n", id, bus->name); 263 | return NULL; 264 | } 265 | if (!sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) { 266 | dev = sysfs_open_device_path(target); 267 | if (!dev) { 268 | dbg_printf("Error opening device at %s\n", target); 269 | return NULL; 270 | } 271 | if (!bus->devices) 272 | bus->devices = dlist_new_with_delete 273 | (sizeof(struct sysfs_device), 274 | sysfs_close_dev); 275 | dlist_unshift_sorted(bus->devices, dev, sort_list); 276 | } 277 | return dev; 278 | } 279 | 280 | /** 281 | * sysfs_get_bus_driver: Get specific driver on bus using driver name 282 | * @bus: bus to find driver on 283 | * @drvname: name of driver 284 | * returns struct sysfs_driver reference or NULL if not found. 285 | */ 286 | struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, 287 | const char *drvname) 288 | { 289 | struct sysfs_driver *drv; 290 | char drvpath[SYSFS_PATH_MAX]; 291 | 292 | if (!bus || !drvname) { 293 | errno = EINVAL; 294 | return NULL; 295 | } 296 | 297 | if (bus->drivers) { 298 | drv = (struct sysfs_driver *)dlist_find_custom 299 | (bus->drivers, (void *)drvname, name_equal); 300 | if (drv) 301 | return drv; 302 | } 303 | safestrcpy(drvpath, bus->path); 304 | safestrcat(drvpath, "/"); 305 | safestrcat(drvpath, SYSFS_DRIVERS_NAME); 306 | safestrcat(drvpath, "/"); 307 | safestrcat(drvpath, drvname); 308 | drv = sysfs_open_driver_path(drvpath); 309 | if (!drv) { 310 | dbg_printf("Error opening driver at %s\n", drvpath); 311 | return NULL; 312 | } 313 | if (!bus->drivers) 314 | bus->drivers = dlist_new_with_delete 315 | (sizeof(struct sysfs_driver), 316 | sysfs_close_drv); 317 | dlist_unshift_sorted(bus->drivers, drv, sort_list); 318 | return drv; 319 | } 320 | 321 | -------------------------------------------------------------------------------- /lib/sysfs_class.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sysfs_class.c 3 | * 4 | * Generic class 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 | 24 | #include "config.h" 25 | 26 | #include "libsysfs.h" 27 | #include "sysfs.h" 28 | 29 | /** 30 | * sysfs_close_class_device: closes a single class device. 31 | * @dev: class device to close. 32 | */ 33 | void sysfs_close_class_device(struct sysfs_class_device *dev) 34 | { 35 | if (dev) { 36 | if (dev->parent) 37 | sysfs_close_class_device(dev->parent); 38 | if (dev->sysdevice) 39 | sysfs_close_device(dev->sysdevice); 40 | if (dev->attrlist) 41 | dlist_destroy(dev->attrlist); 42 | free(dev); 43 | } 44 | } 45 | 46 | static void sysfs_close_cls_dev(void *dev) 47 | { 48 | sysfs_close_class_device((struct sysfs_class_device *)dev); 49 | } 50 | 51 | /** 52 | * sysfs_close_class: close the given class 53 | * @cls: sysfs_class to close 54 | */ 55 | void sysfs_close_class(struct sysfs_class *cls) 56 | { 57 | if (cls) { 58 | if (cls->devices) 59 | dlist_destroy(cls->devices); 60 | if (cls->attrlist) 61 | dlist_destroy(cls->attrlist); 62 | free(cls); 63 | } 64 | } 65 | 66 | /* 67 | * pass this function to dlist_find_custom() 68 | * so it can compare device names 69 | * 70 | * return 1 if pathnames are equal, else 0 71 | */ 72 | static int cdev_name_equal(void *a, void *b) 73 | { 74 | char *str_a, *str_b; 75 | 76 | if (!a || !b) 77 | return 0; 78 | 79 | str_a = (char *)a; 80 | str_b = ((struct sysfs_class_device *)b)->name; 81 | 82 | if (strncmp(str_a, str_b, SYSFS_NAME_LEN) == 0) 83 | return 1; 84 | 85 | return 0; 86 | } 87 | 88 | static struct sysfs_class *alloc_class(void) 89 | { 90 | return (struct sysfs_class *) calloc(1, sizeof(struct sysfs_class)); 91 | } 92 | 93 | /** 94 | * alloc_class_device: mallocs and initializes new class device struct. 95 | * returns sysfs_class_device or NULL. 96 | */ 97 | static struct sysfs_class_device *alloc_class_device(void) 98 | { 99 | struct sysfs_class_device *dev; 100 | 101 | dev = calloc(1, sizeof(struct sysfs_class_device)); 102 | return dev; 103 | } 104 | 105 | /** 106 | * set_classdev_classname: Grabs classname from path 107 | * @cdev: class device to set 108 | * Returns nothing 109 | */ 110 | static void set_classdev_classname(struct sysfs_class_device *cdev) 111 | { 112 | char *c, *e, name[SYSFS_PATH_MAX], link[SYSFS_PATH_MAX]; 113 | struct stat stats; 114 | int count = 0; 115 | 116 | /* 117 | * Newer driver core changes have a class:class_device representation. 118 | * Check if this cdev belongs to the newer style subsystem and 119 | * set the classname appropriately. 120 | */ 121 | memset(name, 0, SYSFS_PATH_MAX); 122 | safestrcpy(name, cdev->name); 123 | c = strchr(name, ':'); 124 | if (c) { 125 | safestrcpy(cdev->name, c+1); 126 | *c = '\0'; 127 | safestrcpy(cdev->classname, name); 128 | return; 129 | } 130 | 131 | c = strstr(cdev->path, SYSFS_CLASS_NAME); 132 | if (c == NULL) 133 | c = strstr(cdev->path, SYSFS_BLOCK_NAME); 134 | else 135 | c = strstr(c, "/"); 136 | 137 | if (c) { 138 | if (*c == '/') 139 | c++; 140 | e = c; 141 | while (e != NULL && *e != '/' && *e != '\0') { 142 | e++; 143 | count++; 144 | } 145 | strncpy(cdev->classname, c, count); 146 | } else { 147 | strcpy(link, cdev->path); 148 | strcat(link, "/subsystem"); 149 | sysfs_get_link(link, name, SYSFS_PATH_MAX); 150 | if (lstat(name, &stats)) 151 | safestrcpy(cdev->classname, SYSFS_UNKNOWN); 152 | else { 153 | c = strrchr(name, '/'); 154 | if (c) 155 | safestrcpy(cdev->classname, c+1); 156 | else 157 | safestrcpy(cdev->classname, SYSFS_UNKNOWN); 158 | } 159 | } 160 | } 161 | 162 | /** 163 | * sysfs_open_class_device_path: Opens and populates class device 164 | * @path: path to class device. 165 | * returns struct sysfs_class_device with success and NULL with error. 166 | */ 167 | struct sysfs_class_device *sysfs_open_class_device_path(const char *path) 168 | { 169 | struct sysfs_class_device *cdev; 170 | char temp_path[SYSFS_PATH_MAX]; 171 | 172 | if (!path) { 173 | errno = EINVAL; 174 | return NULL; 175 | } 176 | 177 | /* 178 | * Post linux-2.6.14 driver model supports nested classes with 179 | * links to the nested hierarchy at /sys/class/xxx/. Check for 180 | * a link to the actual class device if a directory isn't found 181 | */ 182 | if (sysfs_path_is_dir(path)) { 183 | dbg_printf("%s: Directory not found, checking for a link\n", path); 184 | if (!sysfs_path_is_link(path)) { 185 | if (sysfs_get_link(path, temp_path, SYSFS_PATH_MAX)) { 186 | dbg_printf("Error retrieving link at %s\n", path); 187 | return NULL; 188 | } 189 | } else { 190 | dbg_printf("%s is not a valid class device path\n", path); 191 | return NULL; 192 | } 193 | } else 194 | safestrcpy(temp_path, path); 195 | 196 | cdev = alloc_class_device(); 197 | if (!cdev) { 198 | dbg_printf("calloc failed\n"); 199 | return NULL; 200 | } 201 | if (sysfs_get_name_from_path(temp_path, cdev->name, SYSFS_NAME_LEN)) { 202 | errno = EINVAL; 203 | dbg_printf("Error getting class device name\n"); 204 | sysfs_close_class_device(cdev); 205 | return NULL; 206 | } 207 | 208 | safestrcpy(cdev->path, temp_path); 209 | if (sysfs_remove_trailing_slash(cdev->path)) { 210 | dbg_printf("Invalid path to class device %s\n", cdev->path); 211 | sysfs_close_class_device(cdev); 212 | return NULL; 213 | } 214 | set_classdev_classname(cdev); 215 | 216 | return cdev; 217 | } 218 | 219 | /** 220 | * sysfs_get_classdev_parent: Retrieves the parent of a class device. 221 | * eg., when working with hda1, this function can be used to retrieve the 222 | * sysfs_class_device for hda 223 | * 224 | * @clsdev: class device whose parent details are required. 225 | * Returns sysfs_class_device of the parent on success, NULL on failure 226 | */ 227 | struct sysfs_class_device *sysfs_get_classdev_parent 228 | (struct sysfs_class_device *clsdev) 229 | { 230 | char abs_path[SYSFS_PATH_MAX], tmp_path[SYSFS_PATH_MAX]; 231 | char *c; 232 | 233 | if (!clsdev) { 234 | errno = EINVAL; 235 | return NULL; 236 | } 237 | 238 | if (clsdev->parent) 239 | return (clsdev->parent); 240 | 241 | memset(abs_path, 0, SYSFS_PATH_MAX); 242 | memset(tmp_path, 0, SYSFS_PATH_MAX); 243 | 244 | safestrcpy(tmp_path, clsdev->path); 245 | c = strstr(tmp_path, clsdev->classname); 246 | c = strchr(c, '/'); 247 | *c = '\0'; 248 | 249 | safestrcpy(abs_path, clsdev->path); 250 | c = strrchr(abs_path, '/'); 251 | *c = '\0'; 252 | 253 | if ((strncmp(tmp_path, abs_path, strlen(abs_path))) == 0) { 254 | dbg_printf("Class device %s doesn't have a parent\n", 255 | clsdev->name); 256 | return NULL; 257 | } 258 | 259 | clsdev->parent = sysfs_open_class_device_path(abs_path); 260 | 261 | return clsdev->parent; 262 | } 263 | 264 | /** 265 | * get_classdev_path: given the class and a device in the class, return the 266 | * absolute path to the device 267 | * @classname: name of the class 268 | * @clsdev: the class device 269 | * @path: buffer to return path 270 | * @psize: size of "path" 271 | * Returns 0 on SUCCESS or -1 on error 272 | */ 273 | static int get_classdev_path(const char *classname, const char *clsdev, 274 | char *path, size_t len) 275 | { 276 | char *c; 277 | 278 | if (!classname || !clsdev || !path) { 279 | errno = EINVAL; 280 | return -1; 281 | } 282 | if (sysfs_get_mnt_path(path, len) != 0) { 283 | dbg_printf("Error getting sysfs mount path\n"); 284 | return -1; 285 | } 286 | safestrcatmax(path, "/", len); 287 | if (strncmp(classname, SYSFS_BLOCK_NAME, 288 | sizeof(SYSFS_BLOCK_NAME)) == 0) { 289 | safestrcatmax(path, SYSFS_BLOCK_NAME, len); 290 | if (!sysfs_path_is_dir(path)) 291 | goto done; 292 | c = strrchr(path, '/'); 293 | *(c+1) = '\0'; 294 | } 295 | safestrcatmax(path, SYSFS_CLASS_NAME, len); 296 | safestrcatmax(path, "/", len); 297 | safestrcatmax(path, classname, len); 298 | done: 299 | safestrcatmax(path, "/", len); 300 | safestrcatmax(path, clsdev, len); 301 | return 0; 302 | } 303 | 304 | /** 305 | * sysfs_open_class_device: Locates a specific class_device and returns it. 306 | * Class_device must be closed using sysfs_close_class_device 307 | * @classname: Class to search 308 | * @name: name of the class_device 309 | * 310 | * NOTE: 311 | * Call sysfs_close_class_device() to close the class device 312 | */ 313 | struct sysfs_class_device *sysfs_open_class_device 314 | (const char *classname, const char *name) 315 | { 316 | char devpath[SYSFS_PATH_MAX]; 317 | struct sysfs_class_device *cdev; 318 | 319 | if (!classname || !name) { 320 | errno = EINVAL; 321 | return NULL; 322 | } 323 | 324 | memset(devpath, 0, SYSFS_PATH_MAX); 325 | if ((get_classdev_path(classname, name, devpath, 326 | SYSFS_PATH_MAX)) != 0) { 327 | dbg_printf("Error getting to device %s on class %s\n", 328 | name, classname); 329 | return NULL; 330 | } 331 | 332 | cdev = sysfs_open_class_device_path(devpath); 333 | if (!cdev) { 334 | dbg_printf("Error getting class device %s from class %s\n", 335 | name, classname); 336 | return NULL; 337 | } 338 | return cdev; 339 | } 340 | 341 | /** 342 | * sysfs_get_classdev_attr: searches class device's attributes by name 343 | * @clsdev: class device to look through 344 | * @name: attribute name to get 345 | * returns sysfs_attribute reference with success or NULL with error 346 | */ 347 | struct sysfs_attribute *sysfs_get_classdev_attr 348 | (struct sysfs_class_device *clsdev, const char *name) 349 | { 350 | if (!clsdev || !name) { 351 | errno = EINVAL; 352 | return NULL; 353 | } 354 | return get_attribute(clsdev, (char *)name); 355 | } 356 | 357 | /** 358 | * sysfs_get_classdev_attributes: gets list of classdev attributes 359 | * @clsdev: class device whose attributes list is needed 360 | * returns dlist of attributes on success or NULL on error 361 | */ 362 | struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *clsdev) 363 | { 364 | if (!clsdev) { 365 | errno = EINVAL; 366 | return NULL; 367 | } 368 | return get_dev_attributes_list(clsdev); 369 | } 370 | 371 | /** 372 | * sysfs_get_classdev_device: gets the sysfs_device associated with the 373 | * given sysfs_class_device 374 | * @clsdev: class device whose associated sysfs_device is needed 375 | * returns struct sysfs_device * on success or NULL on error 376 | */ 377 | struct sysfs_device *sysfs_get_classdev_device 378 | (struct sysfs_class_device *clsdev) 379 | { 380 | char linkpath[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; 381 | 382 | if (!clsdev) { 383 | errno = EINVAL; 384 | return NULL; 385 | } 386 | 387 | if (clsdev->sysdevice) 388 | return clsdev->sysdevice; 389 | 390 | memset(linkpath, 0, SYSFS_PATH_MAX); 391 | safestrcpy(linkpath, clsdev->path); 392 | safestrcat(linkpath, "/device"); 393 | if (!sysfs_path_is_link(linkpath)) { 394 | memset(devpath, 0, SYSFS_PATH_MAX); 395 | if (!sysfs_get_link(linkpath, devpath, SYSFS_PATH_MAX)) 396 | clsdev->sysdevice = sysfs_open_device_path(devpath); 397 | } 398 | return clsdev->sysdevice; 399 | } 400 | 401 | /** 402 | * sysfs_open_class: opens specific class and all its devices on system 403 | * returns sysfs_class structure with success or NULL with error. 404 | */ 405 | struct sysfs_class *sysfs_open_class(const char *name) 406 | { 407 | struct sysfs_class *cls = NULL; 408 | char *c, classpath[SYSFS_PATH_MAX]; 409 | 410 | if (!name) { 411 | errno = EINVAL; 412 | return NULL; 413 | } 414 | 415 | memset(classpath, 0, SYSFS_PATH_MAX); 416 | if ((sysfs_get_mnt_path(classpath, SYSFS_PATH_MAX)) != 0) { 417 | dbg_printf("Sysfs not supported on this system\n"); 418 | return NULL; 419 | } 420 | 421 | safestrcat(classpath, "/"); 422 | if (strcmp(name, SYSFS_BLOCK_NAME) == 0) { 423 | safestrcat(classpath, SYSFS_BLOCK_NAME); 424 | if (!sysfs_path_is_dir(classpath)) 425 | goto done; 426 | c = strrchr(classpath, '/'); 427 | *(c+1) = '\0'; 428 | } 429 | safestrcat(classpath, SYSFS_CLASS_NAME); 430 | safestrcat(classpath, "/"); 431 | safestrcat(classpath, name); 432 | done: 433 | if (sysfs_path_is_dir(classpath)) { 434 | dbg_printf("Class %s not found on the system\n", name); 435 | return NULL; 436 | } 437 | 438 | cls = alloc_class(); 439 | if (cls == NULL) { 440 | dbg_printf("calloc failed\n"); 441 | return NULL; 442 | } 443 | safestrcpy(cls->name, name); 444 | safestrcpy(cls->path, classpath); 445 | if ((sysfs_remove_trailing_slash(cls->path)) != 0) { 446 | dbg_printf("Invalid path to class device %s\n", cls->path); 447 | sysfs_close_class(cls); 448 | return NULL; 449 | } 450 | 451 | return cls; 452 | } 453 | 454 | /** 455 | * sysfs_get_class_device: get specific class device using the device's id 456 | * @cls: sysfs_class to find the device on 457 | * @name: name of the class device to look for 458 | * 459 | * Returns sysfs_class_device * on success and NULL on failure 460 | */ 461 | struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *cls, 462 | const char *name) 463 | { 464 | char path[SYSFS_PATH_MAX]; 465 | struct sysfs_class_device *cdev = NULL; 466 | 467 | if (!cls || !name) { 468 | errno = EINVAL; 469 | return NULL; 470 | } 471 | 472 | if (cls->devices) { 473 | cdev = (struct sysfs_class_device *)dlist_find_custom 474 | (cls->devices, (void *)name, cdev_name_equal); 475 | if (cdev) 476 | return cdev; 477 | } 478 | 479 | safestrcpy(path, cls->path); 480 | safestrcat(path, "/"); 481 | safestrcat(path, name); 482 | cdev = sysfs_open_class_device_path(path); 483 | if (!cdev) { 484 | dbg_printf("Error opening class device at %s\n", path); 485 | return NULL; 486 | } 487 | if (!cls->devices) 488 | cls->devices = dlist_new_with_delete 489 | (sizeof(struct sysfs_class_device), 490 | sysfs_close_cls_dev); 491 | 492 | dlist_unshift_sorted(cls->devices, cdev, sort_list); 493 | return cdev; 494 | } 495 | 496 | /** 497 | * Add class devices to list 498 | */ 499 | static void add_cdevs_to_classlist(struct sysfs_class *cls, struct dlist *list) 500 | { 501 | char path[SYSFS_PATH_MAX], *cdev_name; 502 | struct sysfs_class_device *cdev = NULL; 503 | 504 | if (cls == NULL || list == NULL) 505 | return; 506 | 507 | dlist_for_each_data(list, cdev_name, char) { 508 | if (cls->devices) { 509 | cdev = (struct sysfs_class_device *) 510 | dlist_find_custom(cls->devices, 511 | (void *)cdev_name, cdev_name_equal); 512 | if (cdev) 513 | continue; 514 | } 515 | safestrcpy(path, cls->path); 516 | safestrcat(path, "/"); 517 | safestrcat(path, cdev_name); 518 | cdev = sysfs_open_class_device_path(path); 519 | if (cdev) { 520 | if (!cls->devices) 521 | cls->devices = dlist_new_with_delete 522 | (sizeof(struct sysfs_class_device), 523 | sysfs_close_cls_dev); 524 | dlist_unshift_sorted(cls->devices, cdev, 525 | sort_list); 526 | } 527 | } 528 | } 529 | 530 | /** 531 | * sysfs_get_class_devices: get all class devices in the given class 532 | * @cls: sysfs_class whose devices list is needed 533 | * 534 | * Returns a dlist of sysfs_class_device * on success and NULL on failure 535 | */ 536 | struct dlist *sysfs_get_class_devices(struct sysfs_class *cls) 537 | { 538 | char path[SYSFS_PATH_MAX]; 539 | struct dlist *dirlist, *linklist; 540 | 541 | if (!cls) { 542 | errno = EINVAL; 543 | return NULL; 544 | } 545 | 546 | /* 547 | * Post linux-2.6.14, we have nested classes and links under 548 | * /sys/class/xxx/. are also valid class devices 549 | */ 550 | safestrcpy(path, cls->path); 551 | dirlist = read_dir_subdirs(path); 552 | if (dirlist) { 553 | add_cdevs_to_classlist(cls, dirlist); 554 | sysfs_close_list(dirlist); 555 | } 556 | 557 | linklist = read_dir_links(path); 558 | if (linklist) { 559 | add_cdevs_to_classlist(cls, linklist); 560 | sysfs_close_list(linklist); 561 | } 562 | 563 | return cls->devices; 564 | } 565 | -------------------------------------------------------------------------------- /lib/sysfs_device.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sysfs_device.c 3 | * 4 | * Generic device 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 | 24 | #include "config.h" 25 | 26 | #include "libsysfs.h" 27 | #include "sysfs.h" 28 | 29 | /** 30 | * get_dev_driver: fills in the dev->driver_name field 31 | * Returns 0 on SUCCESS and -1 on error 32 | */ 33 | static int get_dev_driver(struct sysfs_device *dev) 34 | { 35 | char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; 36 | 37 | if (!dev) { 38 | errno = EINVAL; 39 | return -1; 40 | } 41 | memset(path, 0, SYSFS_PATH_MAX); 42 | memset(devpath, 0, SYSFS_PATH_MAX); 43 | safestrcpymax(path, dev->path, SYSFS_PATH_MAX); 44 | safestrcatmax(path, "/driver", SYSFS_PATH_MAX); 45 | if (!sysfs_path_is_link(path)) { 46 | if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) { 47 | if (!sysfs_get_name_from_path(devpath, 48 | dev->driver_name, SYSFS_NAME_LEN)) 49 | return 0; 50 | } 51 | } 52 | return -1; 53 | } 54 | 55 | /** 56 | * sysfs_get_device_bus: retrieves the bus name the device is on, checks path 57 | * to bus' link to make sure it has correct device. 58 | * @dev: device to get busname. 59 | * returns 0 with success and -1 with error. 60 | */ 61 | int sysfs_get_device_bus(struct sysfs_device *dev) 62 | { 63 | char devpath[SYSFS_PATH_MAX], path[SYSFS_PATH_MAX]; 64 | 65 | if (!dev) { 66 | errno = EINVAL; 67 | return -1; 68 | } 69 | 70 | memset(path, 0, SYSFS_PATH_MAX); 71 | memset(devpath, 0, SYSFS_PATH_MAX); 72 | safestrcpymax(path, dev->path, SYSFS_PATH_MAX); 73 | safestrcatmax(path, "/bus", SYSFS_PATH_MAX); 74 | if (!sysfs_path_is_link(path)) { 75 | if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) { 76 | if (!sysfs_get_name_from_path(devpath, 77 | dev->bus, SYSFS_NAME_LEN)) 78 | return 0; 79 | } 80 | } 81 | return -1; 82 | } 83 | 84 | /** 85 | * get_dev_subsystem: fills in the dev->subsystem field 86 | * Returns 0 on SUCCESS and -1 on error 87 | */ 88 | static int get_dev_subsystem(struct sysfs_device *dev) 89 | { 90 | char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; 91 | 92 | if (!dev) { 93 | errno = EINVAL; 94 | return -1; 95 | } 96 | memset(path, 0, SYSFS_PATH_MAX); 97 | memset(devpath, 0, SYSFS_PATH_MAX); 98 | safestrcpymax(path, dev->path, SYSFS_PATH_MAX); 99 | safestrcatmax(path, "/subsystem", SYSFS_PATH_MAX); 100 | if (!sysfs_path_is_link(path)) { 101 | if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) { 102 | if (!sysfs_get_name_from_path(devpath, 103 | dev->subsystem, SYSFS_NAME_LEN)) 104 | return 0; 105 | } 106 | } 107 | return -1; 108 | } 109 | /** 110 | * sysfs_close_dev_tree: routine for dlist integration 111 | */ 112 | void sysfs_close_dev_tree(void *dev) 113 | { 114 | sysfs_close_device_tree((struct sysfs_device *)dev); 115 | } 116 | 117 | /** 118 | * sysfs_close_device_tree: closes every device in the supplied tree, 119 | * closing children only. 120 | * @devroot: device root of tree. 121 | */ 122 | void sysfs_close_device_tree(struct sysfs_device *devroot) 123 | { 124 | if (devroot) { 125 | if (devroot->children) { 126 | struct sysfs_device *child = NULL; 127 | 128 | dlist_for_each_data(devroot->children, child, 129 | struct sysfs_device) 130 | sysfs_close_device_tree(child); 131 | } 132 | devroot->children = NULL; 133 | sysfs_close_device(devroot); 134 | } 135 | } 136 | 137 | /** 138 | * sysfs_close_device: closes and cleans up a device 139 | * @dev = device to clean up 140 | */ 141 | void sysfs_close_device(struct sysfs_device *dev) 142 | { 143 | if (dev) { 144 | if (dev->parent) 145 | sysfs_close_device(dev->parent); 146 | if (dev->children && dev->children->count) 147 | dlist_destroy(dev->children); 148 | if (dev->attrlist) 149 | dlist_destroy(dev->attrlist); 150 | free(dev); 151 | } 152 | } 153 | 154 | /** 155 | * alloc_device: allocates and initializes device structure 156 | * returns struct sysfs_device 157 | */ 158 | static struct sysfs_device *alloc_device(void) 159 | { 160 | return (struct sysfs_device *) calloc(1, sizeof(struct sysfs_device)); 161 | } 162 | 163 | /** 164 | * sysfs_open_device_path: opens and populates device structure 165 | * @path: path to device, this is the /sys/devices/ path 166 | * returns sysfs_device structure with success or NULL with error 167 | */ 168 | struct sysfs_device *sysfs_open_device_path(const char *path) 169 | { 170 | struct sysfs_device *dev; 171 | 172 | if (!path) { 173 | errno = EINVAL; 174 | return NULL; 175 | } 176 | if (sysfs_path_is_dir(path)) { 177 | dbg_printf("Incorrect path to device: %s\n", path); 178 | return NULL; 179 | } 180 | dev = alloc_device(); 181 | if (!dev) { 182 | dbg_printf("Error allocating device at %s\n", path); 183 | return NULL; 184 | } 185 | if (sysfs_get_name_from_path(path, dev->bus_id, SYSFS_NAME_LEN)) { 186 | errno = EINVAL; 187 | dbg_printf("Error getting device bus_id\n"); 188 | sysfs_close_device(dev); 189 | return NULL; 190 | } 191 | safestrcpy(dev->path, path); 192 | if (sysfs_remove_trailing_slash(dev->path)) { 193 | dbg_printf("Invalid path to device %s\n", dev->path); 194 | sysfs_close_device(dev); 195 | return NULL; 196 | } 197 | /* 198 | * The "name" attribute no longer exists... return the device's 199 | * sysfs representation instead, in the "dev->name" field, which 200 | * implies that the dev->name and dev->bus_id contain same data. 201 | */ 202 | safestrcpy(dev->name, dev->bus_id); 203 | 204 | if (sysfs_get_device_bus(dev)) 205 | dbg_printf("Could not get device bus\n"); 206 | 207 | if (get_dev_driver(dev)) { 208 | dbg_printf("Could not get device %s's driver\n", dev->bus_id); 209 | safestrcpy(dev->driver_name, SYSFS_UNKNOWN); 210 | } 211 | 212 | if (get_dev_subsystem(dev)) { 213 | dbg_printf("Could not get device %s's subsystem\n", dev->bus_id); 214 | safestrcpy(dev->subsystem, SYSFS_UNKNOWN); 215 | } 216 | return dev; 217 | } 218 | 219 | /** 220 | * sysfs_open_device_tree: opens root device and all of its children, 221 | * creating a tree of devices. Only opens children. 222 | * @path: sysfs path to devices 223 | * returns struct sysfs_device and its children with success or NULL with 224 | * error. 225 | */ 226 | struct sysfs_device *sysfs_open_device_tree(const char *path) 227 | { 228 | struct sysfs_device *rootdev = NULL, *new = NULL; 229 | struct sysfs_device *cur = NULL; 230 | struct sysfs_device *devlist; 231 | 232 | if (path == NULL) { 233 | errno = EINVAL; 234 | return NULL; 235 | } 236 | rootdev = sysfs_open_device_path(path); 237 | if (rootdev == NULL) { 238 | dbg_printf("Error opening root device at %s\n", path); 239 | return NULL; 240 | } 241 | 242 | devlist = sysfs_read_dir_subdirs(path); 243 | if (devlist->children) { 244 | dlist_for_each_data(devlist->children, cur, 245 | struct sysfs_device) { 246 | new = sysfs_open_device_tree(cur->path); 247 | if (new == NULL) { 248 | dbg_printf("Error opening device tree at %s\n", 249 | cur->path); 250 | sysfs_close_device(devlist); 251 | sysfs_close_device_tree(rootdev); 252 | return NULL; 253 | } 254 | if (rootdev->children == NULL) 255 | rootdev->children = dlist_new_with_delete 256 | (sizeof(struct sysfs_device), 257 | sysfs_close_dev_tree); 258 | dlist_unshift_sorted(rootdev->children, new, sort_list); 259 | } 260 | } 261 | sysfs_close_device(devlist); 262 | return rootdev; 263 | } 264 | 265 | /** 266 | * sysfs_get_device_attr: searches dev's attributes by name 267 | * @dev: device to look through 268 | * @name: attribute name to get 269 | * returns sysfs_attribute reference with success or NULL with error. 270 | */ 271 | struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, 272 | const char *name) 273 | { 274 | if (!dev || !name) { 275 | errno = EINVAL; 276 | return NULL; 277 | } 278 | return get_attribute(dev, (char *)name); 279 | } 280 | 281 | /** 282 | * sysfs_get_device_attributes: gets list of device attributes 283 | * @dev: device whose attributes list is needed 284 | * returns dlist of attributes on success or NULL on error 285 | */ 286 | struct dlist *sysfs_get_device_attributes(struct sysfs_device *dev) 287 | { 288 | if (!dev) { 289 | errno = EINVAL; 290 | return NULL; 291 | } 292 | return get_dev_attributes_list(dev); 293 | } 294 | 295 | /** 296 | * get_device_absolute_path: looks up the bus the device is on, gets 297 | * absolute path to the device 298 | * @device: device for which path is needed 299 | * @path: buffer to store absolute path 300 | * @psize: size of "path" 301 | * Returns 0 on success -1 on failure 302 | */ 303 | static int get_device_absolute_path(const char *device, const char *bus, 304 | char *path, size_t psize) 305 | { 306 | char bus_path[SYSFS_PATH_MAX]; 307 | 308 | if (!device || !path) { 309 | errno = EINVAL; 310 | return -1; 311 | } 312 | 313 | memset(bus_path, 0, SYSFS_PATH_MAX); 314 | if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX)) { 315 | dbg_printf ("Sysfs not supported on this system\n"); 316 | return -1; 317 | } 318 | safestrcat(bus_path, "/"); 319 | safestrcat(bus_path, SYSFS_BUS_NAME); 320 | safestrcat(bus_path, "/"); 321 | safestrcat(bus_path, bus); 322 | safestrcat(bus_path, "/"); 323 | safestrcat(bus_path, SYSFS_DEVICES_NAME); 324 | safestrcat(bus_path, "/"); 325 | safestrcat(bus_path, device); 326 | /* 327 | * We now are at /sys/bus/"bus_name"/devices/"device" which is a link. 328 | * Now read this link to reach to the device. 329 | */ 330 | if (sysfs_get_link(bus_path, path, psize)) { 331 | dbg_printf("Error getting to device %s\n", device); 332 | return -1; 333 | } 334 | return 0; 335 | } 336 | 337 | /** 338 | * sysfs_open_device: open a device by id (use the "bus" subsystem) 339 | * @bus: bus the device belongs to 340 | * @bus_id: bus_id of the device to open - has to be the "bus_id" in 341 | * /sys/bus/xxx/devices 342 | * returns struct sysfs_device if found, NULL otherwise 343 | * NOTE: 344 | * 1. Use sysfs_close_device to close the device 345 | * 2. Bus the device is on must be supplied 346 | * Use sysfs_find_device_bus to get the bus name 347 | */ 348 | struct sysfs_device *sysfs_open_device(const char *bus, const char *bus_id) 349 | { 350 | char sysfs_path[SYSFS_PATH_MAX]; 351 | struct sysfs_device *device; 352 | 353 | if (!bus_id || !bus) { 354 | errno = EINVAL; 355 | return NULL; 356 | } 357 | memset(sysfs_path, 0, SYSFS_PATH_MAX); 358 | if (get_device_absolute_path(bus_id, bus, sysfs_path, 359 | SYSFS_PATH_MAX)) { 360 | dbg_printf("Error getting to device %s\n", bus_id); 361 | return NULL; 362 | } 363 | 364 | device = sysfs_open_device_path(sysfs_path); 365 | if (!device) { 366 | dbg_printf("Error opening device %s\n", bus_id); 367 | return NULL; 368 | } 369 | return device; 370 | } 371 | 372 | /** 373 | * sysfs_get_device_parent: opens up given device's parent and returns a 374 | * reference to its sysfs_device 375 | * @dev: sysfs_device whose parent is requested 376 | * Returns sysfs_device of the parent on success and NULL on failure 377 | */ 378 | struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev) 379 | { 380 | char ppath[SYSFS_PATH_MAX], dpath[SYSFS_PATH_MAX], *tmp; 381 | 382 | if (!dev) { 383 | errno = EINVAL; 384 | return NULL; 385 | } 386 | 387 | if (dev->parent) 388 | return (dev->parent); 389 | 390 | memset(ppath, 0, SYSFS_PATH_MAX); 391 | memset(dpath, 0, SYSFS_PATH_MAX); 392 | safestrcpy(ppath, dev->path); 393 | tmp = strrchr(ppath, '/'); 394 | if (!tmp) { 395 | dbg_printf("Invalid path to device %s\n", ppath); 396 | return NULL; 397 | } 398 | if (*(tmp + 1) == '\0') { 399 | *tmp = '\0'; 400 | tmp = strrchr(tmp, '/'); 401 | if (tmp == NULL) { 402 | dbg_printf("Invalid path to device %s\n", ppath); 403 | return NULL; 404 | } 405 | } 406 | *tmp = '\0'; 407 | 408 | /* Make sure we're at the top of the device tree */ 409 | if (sysfs_get_mnt_path(dpath, SYSFS_PATH_MAX) != 0) { 410 | dbg_printf("Sysfs not supported on this system\n"); 411 | return NULL; 412 | } 413 | safestrcat(dpath, "/"); 414 | safestrcat(dpath, SYSFS_DEVICES_NAME); 415 | 416 | if (strcmp(dpath, ppath) == 0) { 417 | dbg_printf("Device at %s does not have a parent\n", dev->path); 418 | return NULL; 419 | } 420 | 421 | dev->parent = sysfs_open_device_path(ppath); 422 | if (!dev->parent) { 423 | dbg_printf("Error opening device %s's parent at %s\n", 424 | dev->bus_id, ppath); 425 | return NULL; 426 | } 427 | return (dev->parent); 428 | } 429 | -------------------------------------------------------------------------------- /lib/sysfs_driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sysfs_driver.c 3 | * 4 | * Driver 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 | 24 | #include "config.h" 25 | 26 | #include "libsysfs.h" 27 | #include "sysfs.h" 28 | 29 | static void sysfs_close_driver_device(void *device) 30 | { 31 | sysfs_close_device((struct sysfs_device *)device); 32 | } 33 | 34 | /** 35 | * sysfs_close_driver: closes driver and deletes device lists too 36 | * @driver: driver to close 37 | */ 38 | void sysfs_close_driver(struct sysfs_driver *driver) 39 | { 40 | if (driver) { 41 | if (driver->devices) 42 | dlist_destroy(driver->devices); 43 | if (driver->attrlist) 44 | dlist_destroy(driver->attrlist); 45 | if (driver->module) 46 | sysfs_close_module(driver->module); 47 | free(driver); 48 | } 49 | } 50 | 51 | /** 52 | * alloc_driver: allocates and initializes driver 53 | * returns struct sysfs_driver with success and NULL with error. 54 | */ 55 | static struct sysfs_driver *alloc_driver(void) 56 | { 57 | return (struct sysfs_driver *)calloc(1, sizeof(struct sysfs_driver)); 58 | } 59 | 60 | /** 61 | * get_driver_bus: gets bus the driver is on 62 | * Returns 0 on success and 1 on error 63 | */ 64 | static int get_driver_bus(struct sysfs_driver *drv) 65 | { 66 | char drvpath[SYSFS_PATH_MAX], *c = NULL; 67 | 68 | if (!drv) { 69 | errno = EINVAL; 70 | return 1; 71 | } 72 | 73 | safestrcpy(drvpath, drv->path); 74 | c = strstr(drvpath, SYSFS_DRIVERS_NAME); 75 | if (c == NULL) 76 | return 1; 77 | *--c = '\0'; 78 | c = strstr(drvpath, SYSFS_BUS_NAME); 79 | if (c == NULL) 80 | return 1; 81 | c = strstr(c, "/"); 82 | if (c == NULL) 83 | return 1; 84 | c++; 85 | safestrcpy(drv->bus, c); 86 | return 0; 87 | } 88 | 89 | /** 90 | * sysfs_get_driver_attr: searches drv's attributes by name 91 | * @drv: driver to look through 92 | * @name: attribute name to get 93 | * returns sysfs_attribute reference with success or NULL with error. 94 | */ 95 | struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv, 96 | const char *name) 97 | { 98 | if (!drv || !name) { 99 | errno = EINVAL; 100 | return NULL; 101 | } 102 | return get_attribute(drv, (char *)name); 103 | } 104 | 105 | /** 106 | * sysfs_get_driver_attributes: gets list of driver attributes 107 | * @dev: driver whose attributes list is needed 108 | * returns dlist of attributes on success or NULL on error 109 | */ 110 | struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *drv) 111 | { 112 | if (!drv) { 113 | errno = EINVAL; 114 | return NULL; 115 | } 116 | return get_dev_attributes_list(drv); 117 | } 118 | 119 | /** 120 | * sysfs_open_driver_path: opens and initializes driver structure 121 | * @path: path to driver directory 122 | * returns struct sysfs_driver with success and NULL with error 123 | */ 124 | struct sysfs_driver *sysfs_open_driver_path(const char *path) 125 | { 126 | struct sysfs_driver *driver = NULL; 127 | 128 | if (!path) { 129 | errno = EINVAL; 130 | return NULL; 131 | } 132 | if (sysfs_path_is_dir(path)) { 133 | dbg_printf("Invalid path to driver: %s\n", path); 134 | return NULL; 135 | } 136 | driver = alloc_driver(); 137 | if (!driver) { 138 | dbg_printf("Error allocating driver at %s\n", path); 139 | return NULL; 140 | } 141 | if (sysfs_get_name_from_path(path, driver->name, SYSFS_NAME_LEN)) { 142 | dbg_printf("Error getting driver name from path\n"); 143 | free(driver); 144 | return NULL; 145 | } 146 | safestrcpy(driver->path, path); 147 | if (sysfs_remove_trailing_slash(driver->path)) { 148 | dbg_printf("Invalid path to driver %s\n", driver->path); 149 | sysfs_close_driver(driver); 150 | return NULL; 151 | } 152 | if (get_driver_bus(driver)) { 153 | dbg_printf("Could not get the bus driver is on\n"); 154 | sysfs_close_driver(driver); 155 | return NULL; 156 | } 157 | 158 | return driver; 159 | } 160 | 161 | /** 162 | * get_driver_path: looks up the bus the driver is on and builds path to 163 | * the driver. 164 | * @bus: bus on which to search 165 | * @drv: driver to look for 166 | * @path: buffer to return path to driver 167 | * @psize: size of "path" 168 | * Returns 0 on success and -1 on error 169 | */ 170 | static int get_driver_path(const char *bus, const char *drv, 171 | char *path, size_t psize) 172 | { 173 | if (!bus || !drv || !path || psize == 0) { 174 | errno = EINVAL; 175 | return -1; 176 | } 177 | if (sysfs_get_mnt_path(path, psize)) { 178 | dbg_printf("Error getting sysfs mount path\n"); 179 | return -1; 180 | } 181 | safestrcatmax(path, "/", psize); 182 | safestrcatmax(path, SYSFS_BUS_NAME, psize); 183 | safestrcatmax(path, "/", psize); 184 | safestrcatmax(path, bus, psize); 185 | safestrcatmax(path, "/", psize); 186 | safestrcatmax(path, SYSFS_DRIVERS_NAME, psize); 187 | safestrcatmax(path, "/", psize); 188 | safestrcatmax(path, drv, psize); 189 | return 0; 190 | } 191 | 192 | /** 193 | * sysfs_open_driver: open driver by name, given its bus 194 | * @bus_name: Name of the bus 195 | * @drv_name: Name of the driver 196 | * Returns the sysfs_driver reference on success and NULL on failure 197 | */ 198 | struct sysfs_driver *sysfs_open_driver(const char *bus_name, 199 | const char *drv_name) 200 | { 201 | char path[SYSFS_PATH_MAX]; 202 | struct sysfs_driver *driver = NULL; 203 | 204 | if (!drv_name || !bus_name) { 205 | errno = EINVAL; 206 | return NULL; 207 | } 208 | 209 | memset(path, 0, SYSFS_PATH_MAX); 210 | if (get_driver_path(bus_name, drv_name, path, SYSFS_PATH_MAX)) { 211 | dbg_printf("Error getting to driver %s\n", drv_name); 212 | return NULL; 213 | } 214 | driver = sysfs_open_driver_path(path); 215 | if (!driver) { 216 | dbg_printf("Error opening driver at %s\n", path); 217 | return NULL; 218 | } 219 | return driver; 220 | } 221 | 222 | /** 223 | * sysfs_get_driver_devices: gets list of devices that use the driver 224 | * @drv: sysfs_driver whose device list is needed 225 | * Returns dlist of struct sysfs_device on success and NULL on failure 226 | */ 227 | struct dlist *sysfs_get_driver_devices(struct sysfs_driver *drv) 228 | { 229 | char *ln = NULL; 230 | struct dlist *linklist = NULL; 231 | struct sysfs_device *dev = NULL; 232 | 233 | if (!drv) { 234 | errno = EINVAL; 235 | return NULL; 236 | } 237 | 238 | linklist = read_dir_links(drv->path); 239 | if (linklist) { 240 | dlist_for_each_data(linklist, ln, char) { 241 | 242 | if (!strncmp(ln, SYSFS_MODULE_NAME, strlen(ln))) 243 | continue; 244 | 245 | dev = sysfs_open_device(drv->bus, ln); 246 | if (!dev) { 247 | dbg_printf("Error opening driver's device\n"); 248 | sysfs_close_list(linklist); 249 | return NULL; 250 | } 251 | if (!drv->devices) { 252 | drv->devices = dlist_new_with_delete 253 | (sizeof(struct sysfs_device), 254 | sysfs_close_driver_device); 255 | if (!drv->devices) { 256 | dbg_printf("Error creating device list\n"); 257 | sysfs_close_list(linklist); 258 | sysfs_close_device(dev); 259 | return NULL; 260 | } 261 | } 262 | dlist_unshift_sorted(drv->devices, dev, sort_list); 263 | } 264 | sysfs_close_list(linklist); 265 | } 266 | return drv->devices; 267 | } 268 | 269 | /** 270 | * sysfs_get_driver_module: gets the module being used by this driver 271 | * @drv: sysfs_driver whose "module" is needed 272 | * Returns sysfs_module on success and NULL on failure 273 | */ 274 | struct sysfs_module *sysfs_get_driver_module(struct sysfs_driver *drv) 275 | { 276 | char path[SYSFS_PATH_MAX], mod_path[SYSFS_PATH_MAX]; 277 | 278 | if (!drv) { 279 | errno = EINVAL; 280 | return NULL; 281 | } 282 | 283 | memset(path, 0, SYSFS_PATH_MAX); 284 | safestrcpy(path, drv->path); 285 | safestrcat(path, "/"); 286 | safestrcat(path, SYSFS_MODULE_NAME); 287 | if (!sysfs_path_is_link(path)) { 288 | memset(mod_path, 0, SYSFS_PATH_MAX); 289 | if (!sysfs_get_link(path, mod_path, SYSFS_PATH_MAX)) 290 | drv->module = sysfs_open_module_path(mod_path); 291 | } 292 | return drv->module; 293 | } 294 | -------------------------------------------------------------------------------- /lib/sysfs_module.c: -------------------------------------------------------------------------------- 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 | 24 | #include "config.h" 25 | 26 | #include "libsysfs.h" 27 | #include "sysfs.h" 28 | 29 | /** 30 | * mod_name_equal: compares modules' name 31 | * @a: module_name looking for 32 | * @b: sysfs_module being compared 33 | */ 34 | static int mod_name_equal(void *a, void *b) 35 | { 36 | if (a == NULL || b == NULL) 37 | return 0; 38 | 39 | if (strcmp(((char *)a), ((struct sysfs_module *)b)->name) == 0) 40 | return 1; 41 | 42 | return 0; 43 | } 44 | 45 | /** 46 | * sysfs_close_module: closes a module. 47 | * @module: sysfs_module device to close. 48 | */ 49 | void sysfs_close_module(struct sysfs_module *module) 50 | { 51 | /* 52 | * since both parms and sections are attribs _under_ the 53 | * subdir of module->directory, they will get closed by 54 | * this single call 55 | */ 56 | if (module != NULL) { 57 | if (module->attrlist != NULL) 58 | dlist_destroy(module->attrlist); 59 | if (module->parmlist != NULL) 60 | dlist_destroy(module->parmlist); 61 | if (module->sections != NULL) 62 | dlist_destroy(module->sections); 63 | free(module); 64 | } 65 | } 66 | 67 | /** 68 | * alloc_module: callocs and initializes new module struct. 69 | * returns sysfs_module or NULL. 70 | */ 71 | static struct sysfs_module *alloc_module(void) 72 | { 73 | return (struct sysfs_module *)calloc(1, sizeof(struct sysfs_module)); 74 | } 75 | 76 | /** 77 | * sysfs_open_module_path: Opens and populates the module struct 78 | * @path: path to module. 79 | * returns struct sysfs_module with success and NULL with error. 80 | */ 81 | struct sysfs_module *sysfs_open_module_path(const char *path) 82 | { 83 | struct sysfs_module *mod = NULL; 84 | 85 | if (path == NULL) { 86 | errno = EINVAL; 87 | return NULL; 88 | } 89 | if ((sysfs_path_is_dir(path)) != 0) { 90 | dbg_printf("%s is not a valid path to a module\n", path); 91 | return NULL; 92 | } 93 | mod = alloc_module(); 94 | if (mod == NULL) { 95 | dbg_printf("calloc failed\n"); 96 | return NULL; 97 | } 98 | if ((sysfs_get_name_from_path(path, mod->name, SYSFS_NAME_LEN)) != 0) { 99 | errno = EINVAL; 100 | dbg_printf("Error getting module name\n"); 101 | sysfs_close_module(mod); 102 | return NULL; 103 | } 104 | 105 | safestrcpy(mod->path, path); 106 | if ((sysfs_remove_trailing_slash(mod->path)) != 0) { 107 | dbg_printf("Invalid path to module %s\n", mod->path); 108 | sysfs_close_module(mod); 109 | return NULL; 110 | } 111 | 112 | return mod; 113 | } 114 | 115 | /** 116 | * sysfs_open_module: opens specific module on a system 117 | * returns sysfs_module structure with success or NULL with error. 118 | */ 119 | struct sysfs_module *sysfs_open_module(const char *name) 120 | { 121 | struct sysfs_module *mod = NULL; 122 | char modpath[SYSFS_PATH_MAX]; 123 | 124 | if (name == NULL) { 125 | errno = EINVAL; 126 | return NULL; 127 | } 128 | 129 | memset(modpath, 0, SYSFS_PATH_MAX); 130 | if ((sysfs_get_mnt_path(modpath, SYSFS_PATH_MAX)) != 0) { 131 | dbg_printf("Sysfs not supported on this system\n"); 132 | return NULL; 133 | } 134 | 135 | safestrcat(modpath, "/"); 136 | safestrcat(modpath, SYSFS_MODULE_NAME); 137 | safestrcat(modpath, "/"); 138 | safestrcat(modpath, name); 139 | 140 | if ((sysfs_path_is_dir(modpath)) != 0) { 141 | dbg_printf("Module %s not found on the system\n", name); 142 | return NULL; 143 | } 144 | 145 | mod = alloc_module(); 146 | if (mod == NULL) { 147 | dbg_printf("calloc failed\n"); 148 | return NULL; 149 | } 150 | safestrcpy(mod->name, name); 151 | safestrcpy(mod->path, modpath); 152 | if ((sysfs_remove_trailing_slash(mod->path)) != 0) { 153 | dbg_printf("Invalid path to module %s\n", mod->path); 154 | sysfs_close_module(mod); 155 | return NULL; 156 | } 157 | 158 | return mod; 159 | } 160 | 161 | /** 162 | * sysfs_get_module_attributes: returns a dlist of attributes for 163 | * the requested sysfs_module 164 | * @cdev: sysfs_module for which attributes are needed 165 | * returns a dlist of attributes if exists, NULL otherwise 166 | */ 167 | struct dlist *sysfs_get_module_attributes(struct sysfs_module *module) 168 | { 169 | if (module == NULL) { 170 | errno = EINVAL; 171 | return NULL; 172 | } 173 | return get_dev_attributes_list(module); 174 | } 175 | 176 | /** 177 | * sysfs_get_module_attr: searches module's attributes by name 178 | * @module: module to look through 179 | * @name: attribute name to get 180 | * returns sysfs_attribute reference with success or NULL with error 181 | */ 182 | struct sysfs_attribute *sysfs_get_module_attr 183 | (struct sysfs_module *module, const char *name) 184 | { 185 | if (module == NULL || name == NULL) { 186 | errno = EINVAL; 187 | return NULL; 188 | } 189 | 190 | return get_attribute(module, (char *)name); 191 | } 192 | 193 | /** 194 | * sysfs_get_module_parms: Get modules list of parameters 195 | * @module: sysfs_module whose parmameter list is required 196 | * Returns dlist of parameters on SUCCESS and NULL on error 197 | */ 198 | struct dlist *sysfs_get_module_parms(struct sysfs_module *module) 199 | { 200 | char ppath[SYSFS_PATH_MAX]; 201 | 202 | if (module == NULL) { 203 | errno = EINVAL; 204 | return NULL; 205 | } 206 | memset(ppath, 0, SYSFS_PATH_MAX); 207 | safestrcpy(ppath, module->path); 208 | safestrcat(ppath,"/"); 209 | safestrcat(ppath, SYSFS_MOD_PARM_NAME); 210 | 211 | return (get_attributes_list(module->parmlist, ppath)); 212 | } 213 | 214 | /** 215 | * sysfs_get_module_sections: Get the set of sections for this module 216 | * @module: sysfs_module whose list of sections is required 217 | * Returns dlist of sections on SUCCESS and NULL on error 218 | */ 219 | struct dlist *sysfs_get_module_sections(struct sysfs_module *module) 220 | { 221 | char ppath[SYSFS_PATH_MAX]; 222 | 223 | if (module == NULL) { 224 | errno = EINVAL; 225 | return NULL; 226 | } 227 | 228 | memset(ppath, 0, SYSFS_PATH_MAX); 229 | safestrcpy(ppath, module->path); 230 | safestrcat(ppath,"/"); 231 | safestrcat(ppath, SYSFS_MOD_SECT_NAME); 232 | 233 | return (get_attributes_list(module->sections, ppath)); 234 | } 235 | 236 | /** 237 | * sysfs_get_module_parm: 238 | * @module: sysfs_module to look through 239 | * @parm: name of the parameter to look for 240 | * Returns sysfs_attribute * on SUCCESS and NULL on error 241 | */ 242 | struct sysfs_attribute *sysfs_get_module_parm 243 | (struct sysfs_module *module, const char *parm) 244 | { 245 | struct dlist *parm_list = NULL; 246 | 247 | if (module == NULL || parm == NULL) { 248 | errno = EINVAL; 249 | return NULL; 250 | } 251 | 252 | parm_list = sysfs_get_module_parms(module); 253 | if (parm_list == NULL) 254 | return NULL; 255 | 256 | return (struct sysfs_attribute *)dlist_find_custom(parm_list, 257 | (void *)parm, mod_name_equal); 258 | } 259 | 260 | /** 261 | * sysfs_get_module_section 262 | * @module: sysfs_module to look through 263 | * @section: name of the section to look for 264 | * Returns sysfs_attribute * on SUCCESS and NULL on error 265 | */ 266 | struct sysfs_attribute *sysfs_get_module_section 267 | (struct sysfs_module *module, const char *section) 268 | { 269 | struct dlist *sect_list = NULL; 270 | 271 | if (module == NULL || section == NULL) { 272 | errno = EINVAL; 273 | return NULL; 274 | } 275 | 276 | sect_list = sysfs_get_module_sections(module); 277 | if (sect_list == NULL) 278 | return NULL; 279 | 280 | return (struct sysfs_attribute *)dlist_find_custom(sect_list, 281 | (void *)section, mod_name_equal); 282 | } 283 | -------------------------------------------------------------------------------- /lib/sysfs_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sysfs_utils.c 3 | * 4 | * System 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 | 24 | #include "config.h" 25 | 26 | #include "libsysfs.h" 27 | #include "sysfs.h" 28 | #include 29 | 30 | /** 31 | * sysfs_remove_trailing_slash: Removes any trailing '/' in the given path 32 | * @path: Path to look for the trailing '/' 33 | * Returns 0 on success 1 on error 34 | */ 35 | int sysfs_remove_trailing_slash(char *path) 36 | { 37 | size_t len; 38 | 39 | if (!path) { 40 | errno = EINVAL; 41 | return 1; 42 | } 43 | 44 | len = strlen(path); 45 | while (len > 0 && path[len-1] == '/') 46 | path[--len] = '\0'; 47 | return 0; 48 | } 49 | 50 | /* 51 | * sysfs_get_mnt_path: Gets the sysfs mount point. 52 | * @mnt_path: place to put "sysfs" mount point 53 | * @len: size of mnt_path 54 | * returns 0 with success and -1 with error. 55 | */ 56 | int sysfs_get_mnt_path(char *mnt_path, size_t len) 57 | { 58 | static char sysfs_path[SYSFS_PATH_MAX] = ""; 59 | const char *sysfs_path_env; 60 | FILE *mnt; 61 | struct mntent *mntent; 62 | int ret; 63 | 64 | if (len == 0 || mnt_path == NULL) 65 | return -1; 66 | 67 | /* evaluate only at the first call */ 68 | if (sysfs_path[0] == '\0') { 69 | /* possible overrride of real mount path */ 70 | sysfs_path_env = getenv(SYSFS_PATH_ENV); 71 | if (sysfs_path_env != NULL) { 72 | safestrcpymax(mnt_path, sysfs_path_env, len); 73 | sysfs_remove_trailing_slash(mnt_path); 74 | } else { 75 | safestrcpymax(mnt_path, SYSFS_MNT_PATH, len); 76 | } 77 | } 78 | 79 | /* check that mount point is indeed mounted */ 80 | ret = -1; 81 | mnt = setmntent(SYSFS_PROC_MNTS, "r"); 82 | if (mnt == NULL) { 83 | dbg_printf("Error getting mount information\n"); 84 | return -1; 85 | } 86 | while ((mntent = getmntent(mnt)) != NULL) { 87 | if (strcmp(mntent->mnt_type, SYSFS_FSTYPE_NAME) == 0 && 88 | strcmp(mntent->mnt_dir, mnt_path) == 0) { 89 | ret = 0; 90 | break; 91 | } 92 | } 93 | endmntent(mnt); 94 | 95 | if (ret < 0) 96 | errno = ENOENT; 97 | 98 | return ret; 99 | } 100 | 101 | /** 102 | * sysfs_get_name_from_path: returns last name from a "/" delimited path 103 | * @path: path to get name from 104 | * @name: where to put name 105 | * @len: size of name 106 | */ 107 | int sysfs_get_name_from_path(const char *path, char *name, size_t len) 108 | { 109 | char tmp[SYSFS_PATH_MAX]; 110 | char *n = NULL; 111 | 112 | if (!path || !name || len == 0) { 113 | errno = EINVAL; 114 | return -1; 115 | } 116 | memset(tmp, 0, SYSFS_PATH_MAX); 117 | safestrcpy(tmp, path); 118 | n = strrchr(tmp, '/'); 119 | if (n == NULL) { 120 | errno = EINVAL; 121 | return -1; 122 | } 123 | if (*(n+1) == '\0') { 124 | *n = '\0'; 125 | n = strrchr(tmp, '/'); 126 | if (n == NULL) { 127 | errno = EINVAL; 128 | return -1; 129 | } 130 | } 131 | n++; 132 | safestrcpymax(name, n, len); 133 | return 0; 134 | } 135 | 136 | /** 137 | * sysfs_get_link: returns link source 138 | * @path: symbolic link's path 139 | * @target: where to put name 140 | * @len: size of name 141 | */ 142 | int sysfs_get_link(const char *path, char *target, size_t len) 143 | { 144 | char devdir[SYSFS_PATH_MAX]; 145 | char linkpath[SYSFS_PATH_MAX]; 146 | char *d, *s; 147 | int count; 148 | 149 | if (!path || !target || len == 0) { 150 | errno = EINVAL; 151 | return -1; 152 | } 153 | 154 | count = readlink(path, linkpath, SYSFS_PATH_MAX); 155 | if (count < 0) 156 | return -1; 157 | else 158 | linkpath[count] = '\0'; 159 | /* 160 | * Three cases here: 161 | * 1. relative path => format ../.. 162 | * 2. absolute path => format /abcd/efgh 163 | * 3. relative path _from_ this dir => format abcd/efgh 164 | */ 165 | if (*linkpath == '/') { 166 | /* absolute path - copy as is */ 167 | safestrcpymax(target, linkpath, len); 168 | return 0; 169 | } 170 | 171 | safestrcpy(devdir, path); 172 | s = strrchr(devdir, '/'); 173 | if (s == NULL) 174 | s = devdir - 1; 175 | d = linkpath; 176 | while (*d == '.') { 177 | if (*(d+1) == '/') { 178 | /* 179 | * handle the case where link is of type ./abcd/xxx 180 | */ 181 | d += 2; 182 | while (*d == '/') 183 | d++; 184 | continue; 185 | } else if (*(d+1) != '.' || *(d+2) != '/') 186 | /* 187 | * relative path from this directory, starting 188 | * with a hidden directory 189 | */ 190 | break; 191 | 192 | /* 193 | * relative path, getting rid of leading "../.."; must 194 | * be careful here since any path component of devdir 195 | * could be a symlink again 196 | */ 197 | for (;;) { 198 | while (s > devdir && *s == '/') { 199 | s--; 200 | if (*s == '.' 201 | && (s == devdir || *(s-1) == '/')) 202 | s--; 203 | } 204 | *(s+1) = '\0'; 205 | if (*devdir == '\0' || sysfs_path_is_link(devdir)) 206 | /* 207 | * condition will be true eventually 208 | * because we already know that all 209 | * but the last component of path 210 | * resolve to a directory 211 | */ 212 | break; 213 | if (sysfs_get_link(devdir, devdir, SYSFS_PATH_MAX)) 214 | return -1; 215 | s = devdir + strlen(devdir) - 1; 216 | } 217 | while (s >= devdir) { 218 | if (*s == '/') { 219 | if (*(s+1) != '.' || *(s+2) != '.' 220 | || *(s+3) != '\0') { 221 | d += 3; 222 | while (*d == '/') 223 | d++; 224 | } else 225 | s += 2; 226 | break; 227 | } 228 | s--; 229 | } 230 | if (s < devdir || *(s+1) == '\0') 231 | break; 232 | } 233 | 234 | /* 235 | * appending to devdir a slash and the (possibly shortened) 236 | * relative path to the link source 237 | */ 238 | s++; 239 | if (s > devdir && *s == '\0') 240 | *s++ = '/'; 241 | *s = '\0'; 242 | safestrcpymax(s, d, SYSFS_PATH_MAX-(s-devdir)); 243 | safestrcpymax(target, devdir, len); 244 | return 0; 245 | } 246 | 247 | /** 248 | * sysfs_close_list: generic list free routine 249 | * @list: dlist to free 250 | * Returns nothing 251 | */ 252 | void sysfs_close_list(struct dlist *list) 253 | { 254 | if (list) 255 | dlist_destroy(list); 256 | } 257 | 258 | /** 259 | * sysfs_open_directory_list: gets a list of all directories under "path" 260 | * @path: path to read 261 | * Returns a dlist of supported names or NULL no directories (errno is set 262 | * in case of error 263 | */ 264 | struct dlist *sysfs_open_directory_list(const char *path) 265 | { 266 | if (!path) 267 | return NULL; 268 | 269 | return (read_dir_subdirs(path)); 270 | } 271 | 272 | /** 273 | * sysfs_open_link_list: gets a list of all links under "path" 274 | * @path: path to read 275 | * Returns a dlist of supported links or NULL no directories (errno is set 276 | * in case of error 277 | */ 278 | struct dlist *sysfs_open_link_list(const char *path) 279 | { 280 | if (!path) 281 | return NULL; 282 | 283 | return (read_dir_links(path)); 284 | } 285 | 286 | /** 287 | * sysfs_path_is_dir: Check if the path supplied points to a directory 288 | * @path: path to validate 289 | * Returns 0 if path points to dir, 1 otherwise 290 | */ 291 | int sysfs_path_is_dir(const char *path) 292 | { 293 | struct stat astats; 294 | 295 | if (!path) { 296 | errno = EINVAL; 297 | return 1; 298 | } 299 | if ((lstat(path, &astats)) != 0) { 300 | dbg_printf("stat() failed\n"); 301 | return 1; 302 | } 303 | if (S_ISDIR(astats.st_mode)) 304 | return 0; 305 | 306 | return 1; 307 | } 308 | 309 | /** 310 | * sysfs_path_is_link: Check if the path supplied points to a link 311 | * @path: path to validate 312 | * Returns 0 if path points to link, 1 otherwise 313 | */ 314 | int sysfs_path_is_link(const char *path) 315 | { 316 | struct stat astats; 317 | 318 | if (!path) { 319 | errno = EINVAL; 320 | return 1; 321 | } 322 | if ((lstat(path, &astats)) != 0) { 323 | dbg_printf("stat() failed\n"); 324 | return 1; 325 | } 326 | if (S_ISLNK(astats.st_mode)) 327 | return 0; 328 | 329 | return 1; 330 | } 331 | 332 | /** 333 | * sysfs_path_is_file: Check if the path supplied points to a file 334 | * @path: path to validate 335 | * Returns 0 if path points to file, 1 otherwise 336 | */ 337 | int sysfs_path_is_file(const char *path) 338 | { 339 | struct stat astats; 340 | 341 | if (!path) { 342 | errno = EINVAL; 343 | return 1; 344 | } 345 | if ((stat(path, &astats)) != 0) { 346 | dbg_printf("stat() failed\n"); 347 | return 1; 348 | } 349 | if (S_ISREG(astats.st_mode)) 350 | return 0; 351 | 352 | return 1; 353 | } 354 | 355 | /** 356 | * my_strncpy -- a safe strncpy 357 | */ 358 | char *my_strncpy(char *to, const char *from, size_t max) 359 | { 360 | size_t i; 361 | 362 | for (i = 0; i < max && from[i] != '\0'; i++) 363 | to[i] = from[i]; 364 | if (i < max) 365 | to[i] = '\0'; 366 | else 367 | to[max-1] = '\0'; 368 | return to; 369 | } 370 | 371 | /** 372 | * my_strncpy -- a safe strncpy 373 | */ 374 | char *my_strncat(char *to, const char *from, size_t max) 375 | { 376 | size_t i = 0; 377 | 378 | while (i < max && to[i] != '\0') 379 | i++; 380 | my_strncpy(to+i, from, max-i); 381 | return to; 382 | } 383 | -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | *.m4 2 | !klibc.m4 3 | -------------------------------------------------------------------------------- /m4/klibc.m4: -------------------------------------------------------------------------------- 1 | # klibc.m4 serial 99 2 | ## Copyright (C) 1995-2003 Free Software Foundation, Inc. 3 | ## This file is free software, distributed under the terms of the GNU 4 | ## General Public License. As a special exception to the GNU General 5 | ## Public License, this file may be distributed as part of a program 6 | ## that contains a configuration script generated by Autoconf, under 7 | ## the same distribution terms as the rest of that program. 8 | ## 9 | ## This file can can be used in projects which are not available under 10 | ## the GNU General Public License or the GNU Library General Public 11 | ## License but which still want to provide support for the GNU gettext 12 | ## functionality. 13 | ## Please note that the actual code of the KLIBC Library is partly covered 14 | ## by the GNU Library General Public License, and party copyrighted by the 15 | ## Regents of The University of California, and the rest is covered by a 16 | ## MIT style license. 17 | 18 | # Authors: 19 | # Martin Schlemmer , 2005. 20 | 21 | 22 | # AC_CHECK_KLIBC 23 | # -------------- 24 | # Check if the user wants KLIBC support enabled. If so, set KLIBC=yes and 25 | # fill in KLIBC_PREFIX, KLIBC_BINDIR, KLIBC_SBINDIR, KLIBC_LIBDIR and 26 | # KLIBC_INCLUDEDIR. CC is also set to the proper klcc executable. 27 | # NOTE: This should be called before AC_PROG_CC, and before header, function 28 | # or type checks. 29 | AC_DEFUN([AC_CHECK_KLIBC], 30 | [AC_BEFORE([$0], [AC_PROG_CC]) 31 | AC_REQUIRE([AC_CANONICAL_HOST]) 32 | AC_ARG_ENABLE([klibc], 33 | [AS_HELP_STRING([--enable-klibc], 34 | [Enable linking to klibc [no]. You need at 35 | least klibc-1.0 or later for this. Set KLCC 36 | to the absolute file name of klcc if not in 37 | the PATH])], 38 | [KLIBC=$enableval], [KLIBC=no]) 39 | AC_ARG_ENABLE([klibc-layout], 40 | [AS_HELP_STRING([--enable-klibc-layout], 41 | [Enable installing binaries, libraries and 42 | headers into the klibc prefix [yes] ])], 43 | [if test "X$KLIBC" != Xno; then 44 | KLIBC_LAYOUT=$enableval 45 | else 46 | KLIBC_LAYOUT=no 47 | fi], 48 | [if test "X$KLIBC" != Xno; then 49 | KLIBC_LAYOUT=yes 50 | else 51 | KLIBC_LAYOUT=no 52 | fi]) 53 | 54 | if test "X$KLIBC" != Xno; then 55 | # Basic cross compiling support. I do not think it is wise to use 56 | # AC_CHECK_TOOL, because if we are cross compiling, we do not want 57 | # just 'klcc' to be returned ... 58 | if test "${host_alias}" != "${build_alias}"; then 59 | AC_CHECK_PROGS([KLCC], [${host_alias}-klcc], [no]) 60 | else 61 | AC_CHECK_PROGS([KLCC], [klcc], [no]) 62 | fi 63 | if test "X$KLCC" = Xno; then 64 | AC_MSG_ERROR([cannot find klibc frontend 'klcc'!]) 65 | fi 66 | 67 | CC="$KLCC" 68 | CFLAGS="-Os" 69 | 70 | KLIBC_KCROSS="$($KLCC -print-klibc-kcross 2>/dev/null)" 71 | KLIBC_PREFIX="$($KLCC -print-klibc-prefix 2>/dev/null)" 72 | KLIBC_BIN_DIR="$($KLCC -print-klibc-bindir 2>/dev/null)" 73 | KLIBC_SBIN_DIR="${KLIBC_PREFIX}/${KLIBC_KCROSS}sbin" 74 | KLIBC_LIB_DIR="$($KLCC -print-klibc-libdir 2>/dev/null)" 75 | KLIBC_INCLUDE_DIR="$($KLCC -print-klibc-includedir 2>/dev/null)" 76 | 77 | if test "X$KLIBC_LAYOUT" != Xno; then 78 | prefix="$KLIBC_PREFIX" 79 | bindir="$KLIBC_BIN_DIR" 80 | sbindir="$KLIBC_SBIN_DIR" 81 | libdir="$KLIBC_LIB_DIR" 82 | includedir="$KLIBC_INCLUDE_DIR" 83 | fi 84 | 85 | # At least KLIBC_LIB_DIR should be valid, else klibc is too old or 86 | # something went wrong 87 | if test ! -d "$KLIBC_LIB_DIR"; then 88 | AC_MSG_ERROR([your klibc installation is too old or not functional!]) 89 | fi 90 | fi 91 | 92 | AC_SUBST(KLIBC) 93 | ])# AC_CHECK_KLIBC 94 | 95 | -------------------------------------------------------------------------------- /systool.1: -------------------------------------------------------------------------------- 1 | .TH SYSTOOL 1 "2019-11-16" "sysfsutils" 2 | .SH NAME 3 | systool \- view system device information by bus, class, and topology 4 | 5 | .SH SYNOPSIS 6 | .B systool 7 | [\fIoptions\fP [\fIdevice\fP]] 8 | 9 | .SH DESCRIPTION 10 | Calling 11 | .B systool 12 | without parameters will present all available bus types, device 13 | classes, and root devices. 14 | .P 15 | When 16 | .I device 17 | is supplied, the information requested by 18 | .I options 19 | is shown only for the specified device, otherwise all present devices 20 | are displayed. 21 | .P 22 | .B systool 23 | uses APIs provided by 24 | .B libsysfs 25 | to gather information. 26 | .B systool 27 | runs only on Linux systems running kernels 2.5 or later, with the sysfs 28 | filesystem mounted. 29 | 30 | .SH OPTIONS 31 | .TP 32 | .B \-a 33 | Show attributes of the requested resource. 34 | .TP 35 | .B \-b \fIbus\fP 36 | Show information for a specific bus. 37 | .TP 38 | .B \-c \fIclass\fP 39 | Show information for a specific class. 40 | .TP 41 | .B \-d 42 | Show only devices. 43 | .TP 44 | .B \-h 45 | Show usage. 46 | .TP 47 | .B \-m \fImodule_name\fP 48 | Show information for a specific module. 49 | .TP 50 | .B \-p 51 | Show absolute sysfs path to the resource. 52 | .TP 53 | .B \-v 54 | Show all attributes with values. 55 | .TP 56 | .B \-A \fIattribute\fP 57 | Show attribute value for the requested resource. 58 | .TP 59 | .B \-D 60 | Show only drivers. 61 | .TP 62 | .B \-P 63 | Show device's parent. 64 | 65 | .SH SEE ALSO 66 | .P 67 | The web page of 68 | .B libsysfs 69 | at . 70 | 71 | .SH AUTHOR 72 | .B systool 73 | was written by Ananth Mavinakayanahalli and 74 | Daniel Stekloff . 75 | .P 76 | This man page was contributed by Martin Pitt for 77 | the Debian system (but may be used by others). 78 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | dlist_test 2 | get_device 3 | get_driver 4 | get_module 5 | testlibsysfs 6 | test.h 7 | -------------------------------------------------------------------------------- /test/Makefile.am: -------------------------------------------------------------------------------- 1 | check_PROGRAMS = dlist_test get_device get_driver get_module testlibsysfs 2 | BUILT_SOURCES = test.h 3 | CLEANFILES = test.h 4 | test.h: libsysfs.conf create-test 5 | $(AM_V_GEN) $(srcdir)/create-test $(srcdir)/libsysfs.conf 6 | get_device_SOURCES = get_device.c 7 | get_driver_SOURCES = get_driver.c 8 | get_module_SOURCES = get_module.c 9 | testlibsysfs_SOURCES = test.c test_attr.c test_bus.c test_class.c \ 10 | test_device.c test_driver.c test_module.c test_utils.c \ 11 | testout.c test-defs.h libsysfs.conf create-test 12 | AM_CPPFLAGS = -I$(top_srcdir)/include 13 | LDADD = $(top_builddir)/lib/libsysfs.la 14 | AM_CFLAGS = -Wall -W -Wextra -Wstrict-prototypes $(EXTRA_CFLAGS) 15 | 16 | -------------------------------------------------------------------------------- /test/create-test: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | rm -f test.h 4 | 5 | conf_file=${1:-libsysfs.conf} 6 | 7 | . $conf_file 8 | 9 | echo "#define val_dir_path \"$VALID_DIRECTORY_PATH\"" > test.h 10 | echo "#define val_link_path \"$VALID_LINK_PATH\"" >> test.h 11 | echo "#define val_file_path \"$VALID_FILE_PATH\"" >> test.h 12 | echo "#define val_subdir_link_name \"$VALID_SUBDIR_LINK_NAME\"" >> test.h 13 | echo "#define val_subdir_name \"$VALID_SUBDIR_NAME\"" >> test.h 14 | echo "#define val_subsys \"$VALID_SUBSYSTEM\"" >> test.h 15 | echo "#define val_bus_name \"$VALID_BUS_NAME\"" >> test.h 16 | echo "#define val_bus_attr \"$VALID_BUS_ATTR\"" >> test.h 17 | echo "#define val_root_name \"$VALID_ROOT_NAME\"" >> test.h 18 | echo "#define val_root_dev_path \"$VALID_ROOT_PATH\"" >> test.h 19 | echo "#define val_bus_id \"$VALID_BUS_ID\"" >> test.h 20 | echo "#define val_dev_path \"$VALID_DEVICE_PATH\"" >> test.h 21 | echo "#define val_dev_attr \"$VALID_DEVICE_ATTR\"" >> test.h 22 | echo "#define val_class \"$VALID_CLASS\"" >> test.h 23 | echo "#define val_class_dev \"$VALID_CLASS_DEVICE\"" >> test.h 24 | echo "#define val_class_dev_path \"$VALID_CLASS_DEVICE_PATH\"" >> test.h 25 | echo "#define val_class_dev_attr \"$VALID_CLASS_DEV_ATTR\"" >> test.h 26 | echo "#define val_block_class_dev_path \"$VALID_BLOCK_DEV_PATH\"" >> test.h 27 | echo "#define val_drv_name \"$VALID_DRIVER\"" >> test.h 28 | echo "#define val_drv_path \"$VALID_DRIVER_PATH\"" >> test.h 29 | echo "#define val_drv_bus_name \"$VALID_DRIVER_BUS\"" >> test.h 30 | echo "#define val_drv_dev_name \"$VALID_DRIVER_DEVICE\"" >> test.h 31 | echo "#define val_drv_attr_name \"$VALID_DRIVER_ATTR\"" >> test.h 32 | echo "#define val_drv1_name \"$VALID_DRIVER1\"" >> test.h 33 | echo "#define val_drv1_path \"$VALID_DRIVER1_PATH\"" >> test.h 34 | echo "#define val_drv1_bus_name \"$VALID_DRIVER1_BUS\"" >> test.h 35 | echo "#define val_write_attr_path \"$VALID_WRITE_ATTR_PATH\"" >> test.h 36 | echo "#define val_mod_path \"$VALID_MODULE_PATH\"" >> test.h 37 | echo "#define val_mod_name \"$VALID_MODULE\"" >> test.h 38 | echo "#define val_mod_attr_name \"$VALID_MODULE_ATTRIBUTE\"" >> test.h 39 | echo "#define val_mod_param \"$VALID_MODULE_PARAM\"" >> test.h 40 | echo "#define val_mod_section \"$VALID_MODULE_SECTION\"" >> test.h 41 | 42 | 43 | -------------------------------------------------------------------------------- /test/dlist_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * dlist_test.c 3 | * 4 | * Copyright (C) 2003 Eric J Bohm 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | * 20 | */ 21 | 22 | 23 | /* Double linked list implementation tester. 24 | */ 25 | 26 | #include "config.h" 27 | 28 | #include "dlist.h" 29 | #include 30 | #include 31 | #include 32 | // create some dlists put nodes in and out 33 | // use dump 34 | // try list with del_func and without 35 | // use insert, unshift, push 36 | // use pop push mark 37 | // use prev next 38 | 39 | typedef struct simple { 40 | char label[80]; 41 | int number; 42 | } Simple; 43 | 44 | 45 | typedef struct complex { 46 | int cnumber; 47 | Simple *sthing; 48 | } Complex; 49 | 50 | void complex_silly_multiply_by_two( void *a); 51 | int complex_equal(void *a, void *b); 52 | int complex_less(void *a, void *b); 53 | int complex_greater(void *a, void *b); 54 | int complex_comp(void *a, void *b); 55 | void simple_dump(Dlist *); 56 | void simple_dump_rev(Dlist *); 57 | void complex_dump(Dlist *); 58 | void complex_dump_rev(Dlist *); 59 | void complex_out(void *); 60 | void complex_del(void *); 61 | Complex *complex_maker(int,int,char *); 62 | int complex_filter(void *a); 63 | 64 | Simple *simple_maker(int ,char *); 65 | 66 | int main (void) 67 | { 68 | Dlist *list; 69 | Simple *s1,*s2,*s3,*stemp; 70 | Complex *c1,*c2,*c3, *c4, *ctemp, *cfound; 71 | while(1) 72 | { 73 | s1=simple_maker(1,"one"); 74 | s2=simple_maker(2,"two"); 75 | s3=simple_maker(3,"three"); 76 | if((list=dlist_new(sizeof(Simple)))==NULL) 77 | { 78 | fprintf(stderr,"ERR dlist_new fail\n"); 79 | return(2); 80 | } 81 | dlist_push(list,s1); 82 | dlist_push(list,s2); 83 | dlist_push(list,s3); 84 | printf("count is %ld\n",list->count); 85 | simple_dump(list); 86 | simple_dump_rev(list); 87 | stemp=dlist_pop(list); 88 | printf("popped %s\n",stemp->label); 89 | simple_dump(list); 90 | printf("pushed\n"); 91 | dlist_push(list,s3); 92 | simple_dump(list); 93 | stemp=dlist_shift(list); 94 | printf("shifted %s\n",stemp->label); 95 | simple_dump(list); 96 | printf("unshifted\n"); 97 | dlist_unshift(list,stemp); 98 | simple_dump(list); 99 | dlist_destroy(list); 100 | c1=complex_maker(1,1,"one"); 101 | c2=complex_maker(2,2,"two"); 102 | c3=complex_maker(3,3,"three"); 103 | if((list=dlist_new_with_delete(sizeof(Complex),complex_del))==NULL) 104 | { 105 | fprintf(stderr,"ERR dlist_new fail\n"); 106 | return(2); 107 | } 108 | if(dlist_insert_sorted(list,c1,complex_less)==NULL) 109 | { 110 | fprintf(stderr,"ERR dlist_insert fail\n"); 111 | return(2); 112 | } 113 | printf("sorted insert 1\n"); 114 | if(dlist_insert_sorted(list,c3,complex_less)==NULL) 115 | { 116 | fprintf(stderr,"ERR dlist_insert fail\n"); 117 | return(2); 118 | } 119 | if(dlist_insert_sorted(list,c2,complex_less)==NULL) 120 | { 121 | fprintf(stderr,"ERR dlist_insert fail\n"); 122 | return(2); 123 | } 124 | printf("sorted insert 2\n"); 125 | printf("ascending sorted output\n"); 126 | complex_dump(list); 127 | dlist_transform(list,complex_silly_multiply_by_two); 128 | printf("transform multi by 2 output\n"); 129 | complex_dump(list); 130 | ctemp=complex_maker(6,6,"three"); 131 | if((cfound=(Complex *) dlist_find_custom(list,ctemp,complex_equal))!=NULL) 132 | 133 | { 134 | printf("found %d as %d in list\n",ctemp->cnumber,cfound->cnumber); 135 | } else { 136 | printf("ERROR find failed on %d \n",ctemp->cnumber); 137 | return(3); 138 | } 139 | complex_del(ctemp); 140 | dlist_destroy(list); 141 | c1=complex_maker(1,1,"one"); 142 | c2=complex_maker(2,2,"two"); 143 | c3=complex_maker(3,3,"three"); 144 | if((list=dlist_new_with_delete(sizeof(Complex),complex_del))==NULL) 145 | { 146 | fprintf(stderr,"ERR dlist_new fail\n"); 147 | return(2); 148 | } 149 | if(dlist_insert_sorted(list,c1,complex_greater)==NULL) 150 | { 151 | fprintf(stderr,"ERR dlist_insert fail\n"); 152 | return(2); 153 | } 154 | printf("greater sorted insert 1\n"); 155 | if(dlist_insert_sorted(list,c3,complex_greater)==NULL) 156 | { 157 | fprintf(stderr,"ERR dlist_insert fail\n"); 158 | return(2); 159 | } 160 | printf("greater sorted insert 3\n"); 161 | if(dlist_insert_sorted(list,c2,complex_greater)==NULL) 162 | { 163 | fprintf(stderr,"ERR dlist_insert fail\n"); 164 | return(2); 165 | } 166 | printf("greater sorted insert 2\n"); 167 | printf("descending sorted output using transform\n"); 168 | dlist_transform(list,complex_out); 169 | dlist_destroy(list); 170 | c1=complex_maker(1,1,"one"); 171 | c2=complex_maker(2,2,"two"); 172 | c3=complex_maker(3,3,"three"); 173 | c4=complex_maker(4,4,"four"); 174 | if((list=dlist_new_with_delete(sizeof(Complex),complex_del))==NULL) 175 | { 176 | fprintf(stderr,"ERR dlist_new fail\n"); 177 | return(2); 178 | } 179 | dlist_push(list,c2); 180 | dlist_push(list,c1); 181 | dlist_push(list,c4); 182 | dlist_push(list,c3); 183 | printf("unsorted custom\n"); 184 | complex_dump(list); 185 | printf("unsorted custom reversed\n"); 186 | complex_dump_rev(list); 187 | dlist_sort_custom(list,complex_comp); 188 | printf("custom sorted output\n"); 189 | complex_dump(list); 190 | 191 | dlist_filter_sort(list, complex_filter, complex_comp); 192 | printf("custom filtered and sorted output\n"); 193 | complex_dump(list); 194 | dlist_destroy(list); 195 | } 196 | return(0); 197 | } 198 | 199 | void simple_dump (Dlist *list) 200 | { 201 | Simple *thisone; 202 | printf("count %ld \n",list->count); 203 | dlist_for_each_data(list,thisone,Simple) 204 | { 205 | printf("label %s number %d \n",thisone->label,thisone->number); 206 | } 207 | 208 | } 209 | void simple_dump_rev (Dlist *list) 210 | { 211 | Simple *thisone; 212 | printf("rev count %ld \n",list->count); 213 | dlist_for_each_data_rev(list,thisone,Simple) 214 | { 215 | printf("label %s number %d \n",thisone->label,thisone->number); 216 | } 217 | } 218 | 219 | Simple * simple_maker(int snumber,char *label) 220 | { 221 | Simple *stemp; 222 | if((stemp=malloc(sizeof(Simple)))==NULL) 223 | { 224 | fprintf(stderr,"ERR malloc fail\n"); 225 | return(NULL); 226 | } 227 | stemp->number=snumber; 228 | strcpy(stemp->label,label); 229 | return(stemp); 230 | } 231 | 232 | Complex * complex_maker(int cnumber, int snumber, char* label) 233 | { 234 | Complex *ctemp; 235 | if((ctemp=malloc(sizeof(Complex)))==NULL) 236 | { 237 | fprintf(stderr,"ERR malloc fail\n"); 238 | return(NULL); 239 | } 240 | ctemp->cnumber=cnumber; 241 | ctemp->sthing=simple_maker(snumber,label); 242 | return(ctemp); 243 | } 244 | 245 | void complex_out(void *data) 246 | { 247 | Complex *thisone=(Complex *)data; 248 | printf("cnumber %d label %s number %d \n",thisone->cnumber,thisone->sthing->label,thisone->sthing->number); 249 | } 250 | 251 | /** 252 | * return 1 if a==b, else 0 253 | */ 254 | int complex_equal(void *a, void *b) 255 | { 256 | if((((Complex *)a)->cnumber==((Complex *)b)->cnumber) 257 | && (((Complex *)a)->sthing->number== 258 | ((Complex *)b)->sthing->number) 259 | && strcmp(((Complex *)a)->sthing->label, 260 | ((Complex *)b)->sthing->label)==0) 261 | return(1); 262 | return(0); 263 | } 264 | 265 | /** for sorting 266 | * return 1 if acnumber < ((Complex *)b)->cnumber ); 271 | } 272 | 273 | /** for sorting 274 | * return 1 if a>b, else 0 275 | */ 276 | int complex_greater(void *a, void *b) 277 | { 278 | return( ((Complex *)a)->cnumber > ((Complex *)b)->cnumber ); 279 | } 280 | 281 | int complex_comp(void *a, void *b) 282 | { 283 | return( ((Complex *)a)->cnumber - ((Complex *)b)->cnumber ); 284 | } 285 | 286 | void complex_silly_multiply_by_two( void *a) 287 | { 288 | ((Complex *)a)->cnumber=((Complex *)a)->cnumber*2; 289 | ((Complex *)a)->sthing->number=((Complex *)a)->sthing->number*2; 290 | } 291 | 292 | void complex_dump (Dlist *list) 293 | { 294 | Complex *thisone; 295 | dlist_start(list); 296 | printf("count %ld \n",list->count); 297 | dlist_for_each_data(list,thisone,Complex) 298 | { 299 | printf("cnumber %d label %s number %d \n",thisone->cnumber,thisone->sthing->label,thisone->sthing->number); 300 | } 301 | 302 | } 303 | 304 | void complex_dump_rev (Dlist *list) 305 | { 306 | Complex *thisone; 307 | dlist_start(list); 308 | printf("count %ld \n",list->count); 309 | dlist_for_each_data_rev(list,thisone,Complex) 310 | { 311 | printf("cnumber %d label %s number %d \n",thisone->cnumber,thisone->sthing->label,thisone->sthing->number); 312 | } 313 | 314 | } 315 | 316 | void complex_del (void *item) 317 | { 318 | Complex *corpse=item; 319 | printf("freeing complex\n"); 320 | free(corpse->sthing); 321 | free(corpse); 322 | } 323 | 324 | int complex_filter(void *a) 325 | { 326 | Complex *c = (Complex *)a; 327 | 328 | if (c->cnumber >= 2 && c->cnumber <= 3) 329 | return 1; 330 | else 331 | return 0; 332 | } 333 | -------------------------------------------------------------------------------- /test/get_device.c: -------------------------------------------------------------------------------- 1 | /* 2 | * get_device.c 3 | * 4 | * Utility to get details of a given device 5 | * 6 | * Copyright (C) IBM Corp. 2003-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | #include 27 | 28 | #include "libsysfs.h" 29 | 30 | static void print_usage(void) 31 | { 32 | fprintf(stdout, "Usage: get_device [bus] [device]\n"); 33 | } 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | struct sysfs_device *device = NULL; 38 | 39 | if (argc != 3) { 40 | print_usage(); 41 | return 1; 42 | } 43 | 44 | device = sysfs_open_device(argv[1], argv[2]); 45 | if (device == NULL) { 46 | fprintf(stdout, "Device \"%s\" not found on bus \"%s\"\n", 47 | argv[2], argv[1]); 48 | return 1; 49 | } 50 | fprintf(stdout, "device is on bus %s, using driver %s\n", 51 | device->bus, device->driver_name); 52 | 53 | struct sysfs_device *parent = sysfs_get_device_parent(device); 54 | if (parent) 55 | fprintf(stdout, "parent is %s\n", parent->name); 56 | else 57 | fprintf(stdout, "no parent\n"); 58 | return 0; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /test/get_driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * get_driver.c 3 | * 4 | * Utility to get details of the given driver 5 | * 6 | * Copyright (C) IBM Corp. 2003-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "libsysfs.h" 30 | 31 | static void print_usage(void) 32 | { 33 | fprintf(stdout, "Usage: get_driver [bus] [driver]\n"); 34 | } 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | char *bus = NULL, path[SYSFS_PATH_MAX]; 39 | struct sysfs_driver *driver = NULL; 40 | struct sysfs_device *device = NULL; 41 | struct dlist *devlist = NULL; 42 | 43 | if (argc != 3) { 44 | print_usage(); 45 | return 1; 46 | } 47 | 48 | memset(path, 0, SYSFS_PATH_MAX); 49 | if ((sysfs_get_mnt_path(path, SYSFS_PATH_MAX)) != 0) { 50 | fprintf(stdout, "Sysfs not mounted?\n"); 51 | return 1; 52 | } 53 | strcat(path, "/"); 54 | strcat(path, SYSFS_BUS_NAME); 55 | strcat(path, "/"); 56 | strcat(path, argv[1]); 57 | strcat(path, "/"); 58 | strcat(path, SYSFS_DRIVERS_NAME); 59 | strcat(path, "/"); 60 | strcat(path, argv[2]); 61 | driver = sysfs_open_driver_path(path); 62 | if (driver == NULL) { 63 | fprintf(stdout, "Driver %s not found\n", argv[1]); 64 | free(bus); 65 | return 1; 66 | } 67 | devlist = sysfs_get_driver_devices(driver); 68 | if (devlist != NULL) { 69 | fprintf(stdout, "%s is used by:\n", argv[2]); 70 | dlist_for_each_data(devlist, device, struct sysfs_device) 71 | fprintf(stdout, "\t\t%s\n", device->bus_id); 72 | } else 73 | fprintf(stdout, "%s is presently not used by any device\n", 74 | argv[2]); 75 | 76 | fprintf(stdout, "driver %s is on bus %s\n", driver->name, driver->bus); 77 | 78 | struct sysfs_module *module = sysfs_get_driver_module(driver); 79 | if (module) 80 | fprintf(stdout, "%s is using the module %s\n", 81 | driver->name, module->name); 82 | 83 | sysfs_close_driver(driver); 84 | free(bus); 85 | return 0; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /test/get_module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * get_module.c 3 | * 4 | * Utility to get details of a given module 5 | * 6 | * Copyright (C) IBM Corp. 2003-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | #include 27 | 28 | #include "libsysfs.h" 29 | 30 | static void print_usage(void) 31 | { 32 | fprintf(stdout, "Usage: get_module [name]\n"); 33 | } 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | struct sysfs_module *module = NULL; 38 | struct sysfs_attribute *attr = NULL; 39 | struct dlist *attrlist = NULL; 40 | 41 | if (argc != 2) { 42 | print_usage(); 43 | return 1; 44 | } 45 | module = sysfs_open_module(argv[1]); 46 | if (module == NULL) { 47 | fprintf(stdout, "Module \"%s\" not found\n", argv[1]); 48 | return 1; 49 | } 50 | 51 | attrlist = sysfs_get_module_attributes(module); 52 | if (attrlist != NULL) { 53 | dlist_for_each_data(attrlist, attr, struct sysfs_attribute) 54 | fprintf(stdout, "\t%-20s : %s", 55 | attr->name, attr->value); 56 | } 57 | fprintf(stdout, "\n"); 58 | 59 | attrlist = sysfs_get_module_parms(module); 60 | if (attrlist != NULL) { 61 | fprintf(stdout, "Parameters:\n"); 62 | dlist_for_each_data(attrlist, attr, struct sysfs_attribute) 63 | fprintf(stdout, "\t%-20s : %s", 64 | attr->name, attr->value); 65 | } 66 | attrlist = sysfs_get_module_sections(module); 67 | if (attrlist != NULL) { 68 | fprintf(stdout, "Sections:\n"); 69 | dlist_for_each_data(attrlist, attr, struct sysfs_attribute) 70 | fprintf(stdout, "\t%-20s : %s", 71 | attr->name, attr->value); 72 | } 73 | 74 | sysfs_close_module(module); 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /test/libsysfs.conf: -------------------------------------------------------------------------------- 1 | # The config file for libsysfs testsuite 2 | # All values in this file are in relation to the sysfs filesystem only 3 | # 4 | # Values defined here will be used to dynamically build a header file that 5 | # gets used while compiling the testsuite. 6 | 7 | # NOTE: If you change values in this file, please make sure that you run 8 | # "make" (in the "test" directory) for the changes to take effect. 9 | 10 | 11 | # A valid directory path under sysfs 12 | # A valid link name under a subidirectory of VALID_DIRECTORY_PATH... eg., if 13 | # the VALID_DIRECTORY_PATH is /sys/bus/pci, then enter a pci device name for 14 | # VALID SUBDIR_LINK_NAME 15 | VALID_DIRECTORY_PATH=/sys/bus/pci 16 | VALID_SUBDIR_LINK_NAME=0000:00:00.0 17 | 18 | # A valid link path under sysfs - enter the absolute path to a soft-link here 19 | VALID_LINK_PATH=/sys/block/sda/device 20 | 21 | # Absolute path to a regular (readable) attribute (a normal file) under sysfs 22 | VALID_FILE_PATH=/sys/block/sda/dev 23 | 24 | # A valid subsystem name - an entry under /sys 25 | VALID_SUBSYSTEM=bus 26 | 27 | # A valid bus name supported on this system 28 | # A device belonging to the bus 29 | # Absolute path to the device 30 | # A valid attribute defined for this device 31 | VALID_BUS_NAME=pci 32 | VALID_BUS_ID=0000:00:00.0 33 | VALID_DEVICE_PATH=/sys/devices/pci0000:00/0000:00:00.0 34 | VALID_DEVICE_ATTR=vendor 35 | 36 | # A valid attribute exported under VALID_BUS_NAME 37 | # NOTE: As of now, no buses export attributes, change this to a valid value 38 | # when one becomes avaliable 39 | VALID_BUS_ATTR=online 40 | 41 | # A valid directory under /sys/devices 42 | # Its absolute path 43 | # A valid subdirectory under VALID_ROOT_PATH 44 | VALID_ROOT_NAME=pci0000:00 45 | VALID_ROOT_PATH=/sys/devices/pci0000:00 46 | VALID_SUBDIR_NAME=0000:00:00.0 47 | 48 | # A valid class - directory under /sys/class 49 | # A valid class_device belonging to the class - a dir under VALID_CLASS 50 | # Abslolute path to the VALID_CLASS_DEVICE 51 | # A valid attribute defined for the VALID_CLASS_DEVICE 52 | VALID_CLASS=net 53 | VALID_CLASS_DEVICE=eth0 54 | VALID_CLASS_DEVICE_PATH=/sys/class/net/eth0 55 | VALID_CLASS_DEV_ATTR=type 56 | 57 | # A valid directory path under /sys/block/xxx - preferably a partition 58 | VALID_BLOCK_DEV_PATH=/sys/block/hda/hda1 59 | 60 | # A valid driver (preferably a driver that exports readable attributes) 61 | # The absolute path to the driver 62 | # The bus the driver is registered on 63 | # A device that is using it and 64 | # A valid attribute corresponding to the driver 65 | VALID_DRIVER=e100 66 | VALID_DRIVER_PATH=/sys/bus/pci/drivers/e100 67 | VALID_DRIVER_BUS=pci 68 | VALID_DRIVER_DEVICE=0000:02:08.0 69 | VALID_DRIVER_ATTR=new_id 70 | 71 | # Another valid driver - but one that is not being used by any device 72 | # Absolute path to the driver 73 | # The bus the driver is registered 74 | VALID_DRIVER1=usbfs 75 | VALID_DRIVER1_PATH=/sys/bus/usb/drivers/usbfs 76 | VALID_DRIVER1_BUS=usb 77 | 78 | # Path to a writable attribute - make sure that the tester has permission to 79 | # "write" to the file at VALID_WRITE_ATTR_PATH 80 | VALID_WRITE_ATTR_PATH=/sys/class/net/eth0/tx_queue_len 81 | 82 | VALID_MODULE_PATH=/sys/module/usbcore 83 | VALID_MODULE=usbcore 84 | VALID_MODULE_ATTRIBUTE=refcnt 85 | VALID_MODULE_PARAM=blinkenlights 86 | VALID_MODULE_SECTION=__versions 87 | -------------------------------------------------------------------------------- /test/libsysfs.conf-suse: -------------------------------------------------------------------------------- 1 | # The config file for libsysfs testsuite 2 | # All values in this file are in relation to the sysfs filesystem only 3 | # 4 | # Values defined here will be used to dynamically build a header file that 5 | # gets used while compiling the testsuite. 6 | 7 | # NOTE: If you change values in this file, please make sure that you run 8 | # "make" (in the "test" directory) for the changes to take effect. 9 | 10 | 11 | # A valid directory path under sysfs 12 | # A valid link name under a subidirectory of VALID_DIRECTORY_PATH... eg., if 13 | # the VALID_DIRECTORY_PATH is /sys/bus/pci, then enter a pci device name for 14 | # VALID SUBDIR_LINK_NAME 15 | VALID_DIRECTORY_PATH=/sys/bus/pci 16 | VALID_SUBDIR_LINK_NAME=0000:00:00.0 17 | 18 | # A valid link path under sysfs - enter the absolute path to a soft-link here 19 | VALID_LINK_PATH=/sys/block/sda/device 20 | 21 | # Absolute path to a regular (readable) attribute (a normal file) under sysfs 22 | VALID_FILE_PATH=/sys/block/sda/dev 23 | 24 | # A valid subsystem name - an entry under /sys 25 | VALID_SUBSYSTEM=bus 26 | 27 | # A valid bus name supported on this system 28 | # A device belonging to the bus 29 | # Absolute path to the device 30 | # A valid attribute defined for this device 31 | VALID_BUS_NAME=pci 32 | VALID_BUS_ID=0000:00:00.0 33 | VALID_DEVICE_PATH=/sys/devices/pci0000:00/0000:00:00.0 34 | VALID_DEVICE_ATTR=vendor 35 | 36 | # A valid attribute exported under VALID_BUS_NAME 37 | # NOTE: As of now, no buses export attributes, change this to a valid value 38 | # when one becomes avaliable 39 | VALID_BUS_ATTR=online 40 | 41 | # A valid directory under /sys/devices 42 | # Its absolute path 43 | # A valid subdirectory under VALID_ROOT_PATH 44 | VALID_ROOT_NAME=pci0000:00 45 | VALID_ROOT_PATH=/sys/devices/pci0000:00 46 | VALID_SUBDIR_NAME=0000:00:00.0 47 | 48 | # A valid class - directory under /sys/class 49 | # A valid class_device belonging to the class - a dir under VALID_CLASS 50 | # Abslolute path to the VALID_CLASS_DEVICE 51 | # A valid attribute defined for the VALID_CLASS_DEVICE 52 | VALID_CLASS=net 53 | VALID_CLASS_DEVICE=ens33 54 | VALID_CLASS_DEVICE_PATH=/sys/class/net/ens33 55 | VALID_CLASS_DEV_ATTR=type 56 | 57 | # A valid directory path under /sys/block/xxx - preferably a partition 58 | VALID_BLOCK_DEV_PATH=/sys/block/sda/sda1 59 | 60 | # A valid driver (preferably a driver that exports readable attributes) 61 | # The absolute path to the driver 62 | # The bus the driver is registered on 63 | # A device that is using it and 64 | # A valid attribute corresponding to the driver 65 | VALID_DRIVER=e1000 66 | VALID_DRIVER_PATH=/sys/bus/pci/drivers/e1000 67 | VALID_DRIVER_BUS=pci 68 | VALID_DRIVER_DEVICE=0000:02:01.0 69 | VALID_DRIVER_ATTR=new_id 70 | 71 | # Another valid driver - but one that is not being used by any device 72 | # Absolute path to the driver 73 | # The bus the driver is registered 74 | VALID_DRIVER1=usbfs 75 | VALID_DRIVER1_PATH=/sys/bus/usb/drivers/usbfs 76 | VALID_DRIVER1_BUS=usb 77 | 78 | # Path to a writable attribute - make sure that the tester has permission to 79 | # "write" to the file at VALID_WRITE_ATTR_PATH 80 | VALID_WRITE_ATTR_PATH=/sys/class/net/ens33/tx_queue_len 81 | 82 | VALID_MODULE_PATH=/sys/module/usbcore 83 | VALID_MODULE=usbcore 84 | VALID_MODULE_ATTRIBUTE=refcnt 85 | VALID_MODULE_PARAM=blinkenlights 86 | VALID_MODULE_SECTION=__verbose 87 | -------------------------------------------------------------------------------- /test/test-defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * test.h 3 | * 4 | * Generic defines/declarations for the libsysfs testsuite 5 | * 6 | * Copyright (C) IBM Corp. 2004-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | #ifndef _TESTER_H_ 24 | #define _TESTER_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "libsysfs.h" 36 | #include "dlist.h" 37 | #include "test.h" 38 | 39 | #define val_drv1_dev_name "dummy1" 40 | #define val_drv1_attr_name "dummy2" 41 | #define inval_name "invalid_name" 42 | #define inval_path "/sys/invalid/path" 43 | #define FUNC_TABLE_SIZE (sizeof(func_table) / sizeof(void *)) 44 | 45 | extern FILE *my_stdout; 46 | 47 | #define dbg_print(format, arg...) fprintf(my_stdout, format, ## arg) 48 | 49 | /** 50 | * list of display functions 51 | */ 52 | extern void show_device(struct sysfs_device *device); 53 | extern void show_driver(struct sysfs_driver *driver); 54 | extern void show_device_list(struct dlist *devlist); 55 | extern void show_driver_list(struct dlist *drvlist); 56 | extern void show_attribute(struct sysfs_attribute *attr); 57 | extern void show_attribute_list(struct dlist *list); 58 | extern void show_links_list(struct dlist *linklist); 59 | extern void show_dir_list(struct dlist *dirlist); 60 | extern void show_class_device(struct sysfs_class_device *dev); 61 | extern void show_class_device_list(struct dlist *devlist); 62 | extern void show_list(struct dlist *list); 63 | extern void show_parm_list(struct dlist *list); 64 | extern void show_section_list(struct dlist *list); 65 | extern void show_module(struct sysfs_module *module); 66 | 67 | /** 68 | * list of test functions..... 69 | */ 70 | extern int test_sysfs_get_mnt_path(int flag); 71 | extern int test_sysfs_remove_trailing_slash(int flag); 72 | extern int test_sysfs_get_name_from_path(int flag); 73 | extern int test_sysfs_path_is_dir(int flag); 74 | extern int test_sysfs_path_is_link(int flag); 75 | extern int test_sysfs_path_is_file(int flag); 76 | extern int test_sysfs_get_link(int flag); 77 | extern int test_sysfs_open_directory_list(int flag); 78 | extern int test_sysfs_open_link_list(int flag); 79 | extern int test_sysfs_close_list(int flag); 80 | extern int test_sysfs_close_attribute(int flag); 81 | extern int test_sysfs_open_attribute(int flag); 82 | extern int test_sysfs_read_attribute(int flag); 83 | extern int test_sysfs_write_attribute(int flag); 84 | extern int test_sysfs_close_driver(int flag); 85 | extern int test_sysfs_open_driver(int flag); 86 | extern int test_sysfs_open_driver_path(int flag); 87 | extern int test_sysfs_get_driver_attr(int flag); 88 | extern int test_sysfs_get_driver_attributes(int flag); 89 | extern int test_sysfs_get_driver_devices(int flag); 90 | extern int test_sysfs_get_driver_module(int flag); 91 | extern int test_sysfs_close_device(int flag); 92 | extern int test_sysfs_open_device(int flag); 93 | extern int test_sysfs_get_device_parent(int flag); 94 | extern int test_sysfs_open_device_path(int flag); 95 | extern int test_sysfs_get_device_attr(int flag); 96 | extern int test_sysfs_get_device_attributes(int flag); 97 | extern int test_sysfs_close_bus(int flag); 98 | extern int test_sysfs_open_bus(int flag); 99 | extern int test_sysfs_get_bus_device(int flag); 100 | extern int test_sysfs_get_bus_driver(int flag); 101 | extern int test_sysfs_get_bus_drivers(int flag); 102 | extern int test_sysfs_get_bus_devices(int flag); 103 | extern int test_sysfs_close_class_device(int flag); 104 | extern int test_sysfs_open_class_device_path(int flag); 105 | extern int test_sysfs_open_class_device(int flag); 106 | extern int test_sysfs_get_classdev_device(int flag); 107 | extern int test_sysfs_get_classdev_parent(int flag); 108 | extern int test_sysfs_close_class(int flag); 109 | extern int test_sysfs_open_class(int flag); 110 | extern int test_sysfs_get_class_devices(int flag); 111 | extern int test_sysfs_get_class_device(int flag); 112 | extern int test_sysfs_get_classdev_attributes(int flag); 113 | extern int test_sysfs_get_classdev_attr(int flag); 114 | extern int test_sysfs_open_classdev_attr(int flag); 115 | extern int test_sysfs_close_module(int flag); 116 | extern int test_sysfs_open_module_path(int flag); 117 | extern int test_sysfs_open_module(int flag); 118 | extern int test_sysfs_get_module_attr(int flag); 119 | extern int test_sysfs_get_module_attributes(int flag); 120 | extern int test_sysfs_get_module_parms(int flag); 121 | extern int test_sysfs_get_module_sections(int flag); 122 | extern int test_sysfs_get_module_parm(int flag); 123 | extern int test_sysfs_get_module_section(int flag); 124 | 125 | #endif /* _TESTER_H_ */ 126 | -------------------------------------------------------------------------------- /test/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test.c 3 | * 4 | * Main program for the libsysfs testsuite 5 | * 6 | * Copyright (C) IBM Corp. 2004-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | /** 24 | * this doesn't do much, just loops throug to call each function. 25 | */ 26 | 27 | #include "config.h" 28 | 29 | #include "test-defs.h" 30 | #include 31 | 32 | FILE *my_stdout; 33 | 34 | /*************************************************/ 35 | char *function_name[] = { 36 | "sysfs_get_mnt_path", 37 | "sysfs_remove_trailing_slash", 38 | "sysfs_get_name_from_path", 39 | "sysfs_path_is_dir", 40 | "sysfs_path_is_link", 41 | "sysfs_path_is_file", 42 | "sysfs_get_link", 43 | "sysfs_close_list", 44 | "sysfs_open_directory_list", 45 | "sysfs_open_link_list", 46 | "sysfs_close_attribute", 47 | "sysfs_open_attribute", 48 | "sysfs_read_attribute", 49 | "sysfs_write_attribute", 50 | "sysfs_close_driver", 51 | "sysfs_open_driver", 52 | "sysfs_open_driver_path", 53 | "sysfs_get_driver_attr", 54 | "sysfs_get_driver_attributes", 55 | "sysfs_get_driver_devices", 56 | "sysfs_close_device", 57 | "sysfs_open_device", 58 | "sysfs_get_device_parent", 59 | "sysfs_open_device_path", 60 | "sysfs_get_device_attr", 61 | "sysfs_get_device_attributes", 62 | "sysfs_close_bus", 63 | "sysfs_open_bus", 64 | "sysfs_get_bus_device", 65 | "sysfs_get_bus_driver", 66 | "sysfs_get_bus_drivers", 67 | "sysfs_get_bus_devices", 68 | "sysfs_close_class_device", 69 | "sysfs_open_class_device_path", 70 | "sysfs_open_class_device", 71 | "sysfs_get_classdev_device", 72 | "sysfs_get_classdev_parent", 73 | "sysfs_close_class", 74 | "sysfs_open_class", 75 | "sysfs_get_class_devices", 76 | "sysfs_get_class_device", 77 | "sysfs_get_classdev_attributes", 78 | "sysfs_get_classdev_attr", 79 | "sysfs_close_module", 80 | "sysfs_open_module_path", 81 | "sysfs_open_module", 82 | "sysfs_get_module_attr", 83 | "sysfs_get_module_attributes", 84 | "sysfs_get_module_parms", 85 | "sysfs_get_module_sections", 86 | "sysfs_get_module_parm", 87 | "sysfs_get_module_section", 88 | }; 89 | 90 | int (*func_table[])(int) = { 91 | test_sysfs_get_mnt_path, 92 | test_sysfs_remove_trailing_slash, 93 | test_sysfs_get_name_from_path, 94 | test_sysfs_path_is_dir, 95 | test_sysfs_path_is_link, 96 | test_sysfs_path_is_file, 97 | test_sysfs_get_link, 98 | test_sysfs_close_list, 99 | test_sysfs_open_directory_list, 100 | test_sysfs_open_link_list, 101 | test_sysfs_close_attribute, 102 | test_sysfs_open_attribute, 103 | test_sysfs_read_attribute, 104 | test_sysfs_write_attribute, 105 | test_sysfs_close_driver, 106 | test_sysfs_open_driver, 107 | test_sysfs_open_driver_path, 108 | test_sysfs_get_driver_attr, 109 | test_sysfs_get_driver_attributes, 110 | test_sysfs_get_driver_devices, 111 | test_sysfs_close_device, 112 | test_sysfs_open_device, 113 | test_sysfs_get_device_parent, 114 | test_sysfs_open_device_path, 115 | test_sysfs_get_device_attr, 116 | test_sysfs_get_device_attributes, 117 | test_sysfs_close_bus, 118 | test_sysfs_open_bus, 119 | test_sysfs_get_bus_device, 120 | test_sysfs_get_bus_driver, 121 | test_sysfs_get_bus_drivers, 122 | test_sysfs_get_bus_devices, 123 | test_sysfs_close_class_device, 124 | test_sysfs_open_class_device_path, 125 | test_sysfs_open_class_device, 126 | test_sysfs_get_classdev_device, 127 | test_sysfs_get_classdev_parent, 128 | test_sysfs_close_class, 129 | test_sysfs_open_class, 130 | test_sysfs_get_class_devices, 131 | test_sysfs_get_class_device, 132 | test_sysfs_get_classdev_attributes, 133 | test_sysfs_get_classdev_attr, 134 | test_sysfs_close_module, 135 | test_sysfs_open_module_path, 136 | test_sysfs_open_module, 137 | test_sysfs_get_module_attr, 138 | test_sysfs_get_module_attributes, 139 | test_sysfs_get_module_parms, 140 | test_sysfs_get_module_sections, 141 | test_sysfs_get_module_parm, 142 | test_sysfs_get_module_section, 143 | }; 144 | 145 | char *dir_paths[] = { 146 | val_dir_path, 147 | val_root_dev_path, 148 | val_class_dev_path, 149 | val_block_class_dev_path, 150 | val_drv_path, 151 | val_drv1_path, 152 | NULL 153 | }; 154 | 155 | char *file_paths[] = { 156 | val_file_path, 157 | val_write_attr_path, 158 | NULL 159 | }; 160 | 161 | char *link_paths[] = { 162 | val_link_path, 163 | NULL 164 | }; 165 | 166 | static int path_is_dir(const char *path) 167 | { 168 | struct stat astats; 169 | 170 | if ((stat(path, &astats)) != 0) 171 | goto direrr; 172 | 173 | if (S_ISDIR(astats.st_mode)) 174 | return 0; 175 | 176 | direrr: 177 | fprintf(stdout, "Config error: %s not a directory\n", path); 178 | return 1; 179 | } 180 | 181 | static int path_is_file(const char *path) 182 | { 183 | struct stat astats; 184 | 185 | if ((lstat(path, &astats)) != 0) 186 | goto fileerr; 187 | 188 | if (S_ISREG(astats.st_mode)) 189 | return 0; 190 | 191 | fileerr: 192 | fprintf(stdout, "Config error: %s not a file\n", path); 193 | return 1; 194 | } 195 | 196 | static int path_is_link(const char *path) 197 | { 198 | struct stat astats; 199 | 200 | if ((lstat(path, &astats)) != 0) 201 | goto linkerr; 202 | 203 | if (S_ISLNK(astats.st_mode)) 204 | return 0; 205 | 206 | linkerr: 207 | fprintf(stdout, "Config error: %s not a link\n", path); 208 | return 1; 209 | } 210 | 211 | /* 212 | * Check validity of the test.h file entries 213 | */ 214 | static int check_header(void) 215 | { 216 | char *var_path = NULL; 217 | char path1[SYSFS_PATH_MAX]; 218 | int i = 0; 219 | 220 | for (i = 0; dir_paths[i] != NULL; i++) { 221 | var_path = dir_paths[i]; 222 | if (path_is_dir(var_path) != 0) 223 | return 1; 224 | } 225 | 226 | for (i = 0; file_paths[i] != NULL; i++) { 227 | var_path = file_paths[i]; 228 | if (path_is_file(var_path) != 0) 229 | return 1; 230 | } 231 | 232 | for (i = 0; link_paths[i] != NULL; i++) { 233 | var_path = link_paths[i]; 234 | if (path_is_link(var_path) != 0) 235 | return 1; 236 | } 237 | 238 | memset(path1, 0, SYSFS_PATH_MAX); 239 | strcpy(path1, val_root_dev_path); 240 | strcat(path1, "/"); 241 | strcat(path1, val_subdir_name); 242 | if (path_is_dir(path1) != 0) 243 | return 1; 244 | 245 | memset(path1, 0, SYSFS_PATH_MAX); 246 | strcpy(path1, val_drv_path); 247 | strcat(path1, "/"); 248 | strcat(path1, val_drv_dev_name); 249 | if (path_is_link(path1) != 0) 250 | return 1; 251 | 252 | memset(path1, 0, SYSFS_PATH_MAX); 253 | strcpy(path1, val_dir_path); 254 | strcat(path1, "/devices"); 255 | strcat(path1, "/"); 256 | strcat(path1, val_subdir_link_name); 257 | if (path_is_link(path1) != 0) 258 | return 1; 259 | 260 | memset(path1, 0, SYSFS_PATH_MAX); 261 | strcpy(path1, val_class_dev_path); 262 | strcat(path1, "/"); 263 | strcat(path1, val_class_dev_attr); 264 | if (path_is_file(path1) != 0) 265 | return 1; 266 | 267 | memset(path1, 0, SYSFS_PATH_MAX); 268 | strcpy(path1, val_dev_path); 269 | strcat(path1, "/"); 270 | strcat(path1, val_dev_attr); 271 | if (path_is_file(path1) != 0) 272 | return 1; 273 | 274 | memset(path1, 0, SYSFS_PATH_MAX); 275 | strcpy(path1, val_drv_path); 276 | strcat(path1, "/"); 277 | strcat(path1, val_drv_attr_name); 278 | if (path_is_file(path1) != 0) 279 | return 1; 280 | 281 | return 0; 282 | } 283 | 284 | static void usage(void) 285 | { 286 | fprintf(stdout, "testlibsysfs [log-file]\n"); 287 | fprintf(stdout, "\t eg: testlibsysfs 3 /home/user/test.log\n"); 288 | } 289 | 290 | int main(int argc, char *argv[]) 291 | { 292 | char std_out[] = "/dev/stdout"; 293 | char *file_name = NULL; 294 | int i = 0, j = 0, k = 0, num = 1; 295 | 296 | if (argc == 3) { 297 | file_name = argv[2]; 298 | } else { 299 | file_name = std_out; 300 | } 301 | my_stdout = fopen(file_name,"w"); 302 | if (argc < 2) { 303 | usage(); 304 | return 0; 305 | } else 306 | num = strtol(argv[1], NULL, 0); 307 | 308 | if (check_header() != 0) 309 | return 1; 310 | 311 | dbg_print("\nTest running %d times\n", num); 312 | 313 | for (k = 0; k < num ; k++) { 314 | dbg_print("\nThis is the %d test run\n", k+1); 315 | 316 | for (i = 0; i < (int)FUNC_TABLE_SIZE; i++) { 317 | dbg_print("\n**************************************************************\n"); 318 | dbg_print("TESTING: %s, function no: %d\n\n", 319 | function_name[i], i); 320 | for (j = 0; ; j++) { 321 | fflush(my_stdout); 322 | if (func_table[i](j) == -1) 323 | break; 324 | } 325 | dbg_print("**************************************************************\n"); 326 | } 327 | } 328 | 329 | fclose(my_stdout); 330 | return 0; 331 | } 332 | -------------------------------------------------------------------------------- /test/test_attr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_dir.c 3 | * 4 | * Tests for directory related functions for the libsysfs testsuite 5 | * 6 | * Copyright (C) IBM Corp. 2004-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | /** 24 | *************************************************************************** 25 | * this will test the directory related functions provided by libsysfs. 26 | * 27 | * extern void sysfs_close_attribute(struct sysfs_attribute *sysattr); 28 | * extern struct sysfs_attribute *sysfs_open_attribute 29 | * (const char *path); 30 | * extern int sysfs_read_attribute(struct sysfs_attribute *sysattr); 31 | * extern int sysfs_write_attribute(struct sysfs_attribute *sysattr, 32 | * const char *new_value, size_t len); 33 | **************************************************************************** 34 | */ 35 | 36 | #include "config.h" 37 | 38 | #include "test-defs.h" 39 | #include 40 | 41 | /** 42 | * extern void sysfs_close_attribute(struct sysfs_attribute *sysattr); 43 | * 44 | * flag: 45 | * 0: sysattr -> valid 46 | * 1: sysattr -> NULL 47 | */ 48 | int test_sysfs_close_attribute(int flag) 49 | { 50 | struct sysfs_attribute *sysattr = NULL; 51 | char *path = NULL; 52 | 53 | switch (flag) { 54 | case 0: 55 | path = val_file_path; 56 | sysattr = sysfs_open_attribute(path); 57 | if (sysattr == NULL) { 58 | dbg_print("%s: Error opening attribute at %s\n", 59 | __FUNCTION__, val_file_path); 60 | return 0; 61 | } 62 | break; 63 | case 1: 64 | sysattr = NULL; 65 | break; 66 | default: 67 | return -1; 68 | } 69 | sysfs_close_attribute(sysattr); 70 | 71 | dbg_print("%s: returns void\n", __FUNCTION__); 72 | 73 | return 0; 74 | } 75 | 76 | /** 77 | * extern struct sysfs_attribute *sysfs_open_attribute 78 | * (const char *path); 79 | * 80 | * flag: 81 | * 0: path -> valid 82 | * 1: path -> invalid 83 | * 2: path -> NULL 84 | */ 85 | int test_sysfs_open_attribute(int flag) 86 | { 87 | char *path = NULL; 88 | struct sysfs_attribute *sysattr = NULL; 89 | 90 | switch (flag) { 91 | case 0: 92 | path = val_file_path; 93 | break; 94 | case 1: 95 | path = inval_path; 96 | break; 97 | case 2: 98 | path = NULL; 99 | break; 100 | default: 101 | return -1; 102 | } 103 | sysattr = sysfs_open_attribute(path); 104 | 105 | switch (flag) { 106 | case 0: 107 | if (sysattr == NULL) 108 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 109 | __FUNCTION__, flag, errno); 110 | else { 111 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 112 | __FUNCTION__, flag); 113 | dbg_print("Attrib name = %s, at %s\n\n", 114 | sysattr->name, sysattr->path); 115 | } 116 | break; 117 | case 1: 118 | case 2: 119 | if (sysattr != NULL) 120 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 121 | __FUNCTION__, flag, errno); 122 | else 123 | dbg_print("%s: SUCCEEDED with flag = %d\n", 124 | __FUNCTION__, flag); 125 | break; 126 | default: 127 | break; 128 | 129 | } 130 | if (sysattr != NULL) { 131 | sysfs_close_attribute(sysattr); 132 | sysattr = NULL; 133 | } 134 | 135 | return 0; 136 | } 137 | 138 | /** 139 | * extern int sysfs_read_attribute(struct sysfs_attribute *sysattr); 140 | * 141 | * flag: 142 | * 0: sysattr -> valid 143 | * 1: sysattr -> NULL 144 | */ 145 | int test_sysfs_read_attribute(int flag) 146 | { 147 | struct sysfs_attribute *sysattr = NULL; 148 | int ret = 0; 149 | 150 | switch (flag) { 151 | case 0: 152 | sysattr = sysfs_open_attribute(val_file_path); 153 | if (sysattr == NULL) { 154 | dbg_print("%s: failed opening attribute at %s\n", 155 | __FUNCTION__, val_file_path); 156 | return 0; 157 | } 158 | break; 159 | case 1: 160 | sysattr = NULL; 161 | break; 162 | default: 163 | return -1; 164 | } 165 | ret = sysfs_read_attribute(sysattr); 166 | 167 | switch (flag) { 168 | case 0: 169 | if (ret != 0) 170 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 171 | __FUNCTION__, flag, errno); 172 | else { 173 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 174 | __FUNCTION__, flag); 175 | show_attribute(sysattr); 176 | dbg_print("\n"); 177 | } 178 | break; 179 | case 1: 180 | if (ret == 0) 181 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 182 | __FUNCTION__, flag, errno); 183 | else 184 | dbg_print("%s: SUCCEEDED with flag = %d\n", 185 | __FUNCTION__, flag); 186 | break; 187 | default: 188 | break; 189 | } 190 | 191 | if (sysattr != NULL) 192 | sysfs_close_attribute(sysattr); 193 | 194 | return 0; 195 | } 196 | 197 | /** 198 | * extern int sysfs_write_attribute(struct sysfs_attribute *sysattr, 199 | * const char *new_value, size_t len); 200 | * 201 | * flag: 202 | * 0: sysattr -> valid, new_value -> valid, len -> valid; 203 | * 1: sysattr -> valid, new_value -> invalid, len -> invalid; 204 | * 2: sysattr -> valid, new_value -> NULL, len -> invalid; 205 | * 3: sysattr -> NULL, new_value -> valid, len -> valid; 206 | * 4: sysattr -> NULL, new_value -> invalid, len -> invalid; 207 | * 5: sysattr -> NULL, new_value -> NULL, len -> invalid; 208 | */ 209 | int test_sysfs_write_attribute(int flag) 210 | { 211 | struct sysfs_attribute *sysattr = NULL; 212 | char *new_value = NULL; 213 | size_t len = 0; 214 | int ret = 0; 215 | 216 | switch (flag) { 217 | case 0: 218 | sysattr = sysfs_open_attribute(val_write_attr_path); 219 | if (sysattr == NULL) { 220 | dbg_print("%s: failed opening attribute at %s\n", 221 | __FUNCTION__, val_write_attr_path); 222 | return 0; 223 | } 224 | if (sysfs_read_attribute(sysattr) != 0) { 225 | dbg_print("%s: failed reading attribute at %s\n", 226 | __FUNCTION__, val_write_attr_path); 227 | return 0; 228 | } 229 | new_value = calloc(1, sysattr->len + 1); 230 | strncpy(new_value, sysattr->value, sysattr->len); 231 | len = sysattr->len; 232 | break; 233 | case 1: 234 | sysattr = sysfs_open_attribute(val_write_attr_path); 235 | if (sysattr == NULL) { 236 | dbg_print("%s: failed opening attribute at %s\n", 237 | __FUNCTION__, val_write_attr_path); 238 | return 0; 239 | } 240 | new_value = calloc(1, SYSFS_PATH_MAX); 241 | strncpy(new_value, "this should not get copied in the attrib", 242 | SYSFS_PATH_MAX); 243 | len = SYSFS_PATH_MAX; 244 | break; 245 | case 2: 246 | sysattr = sysfs_open_attribute(val_write_attr_path); 247 | if (sysattr == NULL) { 248 | dbg_print("%s: failed opening attribute at %s\n", 249 | __FUNCTION__, val_write_attr_path); 250 | return 0; 251 | } 252 | new_value = NULL; 253 | len = SYSFS_PATH_MAX; 254 | break; 255 | case 3: 256 | sysattr = sysfs_open_attribute(val_write_attr_path); 257 | if (sysattr == NULL) { 258 | dbg_print("%s: failed opening attribute at %s\n", 259 | __FUNCTION__, val_write_attr_path); 260 | return 0; 261 | } 262 | new_value = calloc(1, sysattr->len + 1); 263 | strncpy(new_value, sysattr->value, sysattr->len); 264 | len = sysattr->len; 265 | sysfs_close_attribute(sysattr); 266 | sysattr = NULL; 267 | break; 268 | case 4: 269 | sysattr = NULL; 270 | new_value = calloc(1, SYSFS_PATH_MAX); 271 | strncpy(new_value, "this should not get copied in the attrib", 272 | SYSFS_PATH_MAX); 273 | len = SYSFS_PATH_MAX; 274 | break; 275 | case 5: 276 | sysattr = NULL; 277 | new_value = NULL; 278 | len = SYSFS_PATH_MAX; 279 | break; 280 | default: 281 | return -1; 282 | } 283 | ret = sysfs_write_attribute(sysattr, new_value, len); 284 | 285 | switch (flag) { 286 | case 0: 287 | if (ret != 0) 288 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 289 | __FUNCTION__, flag, errno); 290 | else { 291 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 292 | __FUNCTION__, flag); 293 | dbg_print("Attribute at %s now has value %s\n\n", 294 | sysattr->path, sysattr->value); 295 | } 296 | break; 297 | case 1: 298 | case 2: 299 | case 3: 300 | case 4: 301 | case 5: 302 | if (ret == 0) 303 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 304 | __FUNCTION__, flag, errno); 305 | else 306 | dbg_print("%s: SUCCEEDED with flag = %d\n", 307 | __FUNCTION__, flag); 308 | break; 309 | default: 310 | break; 311 | } 312 | if (sysattr != NULL) { 313 | sysfs_close_attribute(sysattr); 314 | sysattr = NULL; 315 | } 316 | if (new_value != NULL) 317 | free(new_value); 318 | 319 | return 0; 320 | } 321 | -------------------------------------------------------------------------------- /test/test_bus.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_bus.c 3 | * 4 | * Tests for bus related functions for the libsysfs testsuite 5 | * 6 | * Copyright (C) IBM Corp. 2004-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | /** 24 | ****************************************************************************** 25 | * this will test the bus related functions provided by libsysfs. 26 | * 27 | * extern void sysfs_close_bus(struct sysfs_bus *bus); 28 | * extern struct sysfs_bus *sysfs_open_bus(const char *name); 29 | * extern struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, 30 | * char *id); 31 | * extern struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, 32 | * char *drvname); 33 | * extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus); 34 | * extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus); 35 | ****************************************************************************** 36 | */ 37 | 38 | #include "config.h" 39 | 40 | #include "test-defs.h" 41 | #include 42 | 43 | /** 44 | * extern void sysfs_close_bus(struct sysfs_bus *bus); 45 | * 46 | * flags: 47 | * 0 -> bus -> valid 48 | * 1 -> bus -> null. 49 | */ 50 | int test_sysfs_close_bus(int flag) 51 | { 52 | struct sysfs_bus *bus = NULL; 53 | char *bus_name = NULL; 54 | 55 | switch (flag) { 56 | case 0: 57 | bus_name = val_bus_name; 58 | bus = sysfs_open_bus(bus_name); 59 | if (bus == NULL) { 60 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 61 | return 0; 62 | } 63 | break; 64 | case 1: 65 | bus = NULL; 66 | break; 67 | default: 68 | return -1; 69 | } 70 | sysfs_close_bus(bus); 71 | 72 | dbg_print("%s: returns void\n", __FUNCTION__); 73 | return 0; 74 | } 75 | 76 | /** 77 | * extern struct sysfs_bus *sysfs_open_bus(const char *name); 78 | * 79 | * flag: 80 | * 0 - name -> valid 81 | * 1 - name -> invalid 82 | * 2 - name -> null 83 | */ 84 | int test_sysfs_open_bus(int flag) 85 | { 86 | struct sysfs_bus *bus = NULL; 87 | char *name = NULL; 88 | 89 | switch (flag) { 90 | case 0: 91 | name = val_bus_name; 92 | break; 93 | case 1: 94 | name = inval_name; 95 | break; 96 | case 2: 97 | name = NULL; 98 | break; 99 | default: 100 | return -1; 101 | } 102 | bus = sysfs_open_bus(name); 103 | 104 | switch (flag) { 105 | case 0: 106 | if (bus == NULL) 107 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 108 | __FUNCTION__, flag, errno); 109 | else { 110 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 111 | __FUNCTION__, flag); 112 | dbg_print("Bus = %s, path = %s\n\n", 113 | bus->name, bus->path); 114 | } 115 | break; 116 | case 1: 117 | case 2: 118 | if (bus != NULL) 119 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 120 | __FUNCTION__, flag, errno); 121 | else 122 | dbg_print("%s: SUCCEEDED with flag = %d\n", 123 | __FUNCTION__, flag); 124 | break; 125 | default: 126 | return 0; 127 | } 128 | if (bus != NULL) 129 | sysfs_close_bus(bus); 130 | 131 | return 0; 132 | } 133 | 134 | /** 135 | * extern struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, 136 | * char *id); 137 | * 138 | * flag: 139 | * 0 : bus -> valid, id -> valid 140 | * 1 : bus -> valid, id -> invalid 141 | * 2 : bus -> valid, id -> NULL 142 | * 3 : bus -> NULL, id -> valid 143 | * 4 : bus -> NULL, id -> invalid 144 | * 5 : bus -> NULL, id -> NULL 145 | */ 146 | int test_sysfs_get_bus_device(int flag) 147 | { 148 | struct sysfs_bus *bus = NULL; 149 | struct sysfs_device *dev = NULL; 150 | char *bus_name = NULL; 151 | char *id = NULL; 152 | 153 | switch(flag) { 154 | case 0: 155 | bus_name = val_bus_name; 156 | bus = sysfs_open_bus(bus_name); 157 | if (bus == NULL) { 158 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 159 | return 0; 160 | } 161 | id = val_bus_id; 162 | break; 163 | case 1: 164 | bus_name = val_bus_name; 165 | bus = sysfs_open_bus(bus_name); 166 | if (bus == NULL) { 167 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 168 | return 0; 169 | } 170 | id = inval_name; 171 | break; 172 | case 2: 173 | bus_name = val_bus_name; 174 | bus = sysfs_open_bus(bus_name); 175 | if (bus == NULL) { 176 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 177 | return 0; 178 | } 179 | id = NULL; 180 | break; 181 | case 3: 182 | bus = NULL; 183 | id = val_bus_id; 184 | break; 185 | case 4: 186 | bus = NULL; 187 | id = inval_name; 188 | break; 189 | case 5: 190 | bus = NULL; 191 | id = NULL; 192 | break; 193 | default: 194 | return -1; 195 | } 196 | dev = sysfs_get_bus_device(bus, id); 197 | 198 | switch (flag) { 199 | case 0: 200 | if (dev == NULL) { 201 | if (errno == 0) 202 | dbg_print("%s: Device %s not on bus %s\n", 203 | __FUNCTION__, id, bus_name); 204 | else 205 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 206 | __FUNCTION__, flag, errno); 207 | } else { 208 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 209 | __FUNCTION__, flag); 210 | show_device(dev); 211 | dbg_print("\n"); 212 | } 213 | break; 214 | case 1: 215 | case 2: 216 | case 3: 217 | case 4: 218 | case 5: 219 | if (dev != NULL) 220 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 221 | __FUNCTION__, flag, errno); 222 | else 223 | dbg_print("%s: SUCCEEDED with flag = %d\n", 224 | __FUNCTION__, flag); 225 | break; 226 | default: 227 | break; 228 | } 229 | 230 | if (bus != NULL) 231 | sysfs_close_bus(bus); 232 | 233 | return 0; 234 | } 235 | 236 | /** 237 | * extern struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, 238 | * char *drvname); 239 | * 240 | * flag: 241 | * 0 : bus -> valid, drvname -> valid 242 | * 1 : bus -> valid, drvname -> invalid 243 | * 2 : bus -> valid, drvname -> NULL 244 | * 3 : bus -> NULL, drvname -> valid 245 | * 4 : bus -> NULL, drvname -> invalid 246 | * 5 : bus -> NULL, drvname -> NULL 247 | */ 248 | int test_sysfs_get_bus_driver(int flag) 249 | { 250 | struct sysfs_bus *bus = NULL; 251 | struct sysfs_driver *drv = NULL; 252 | char *drvname = NULL; 253 | char *bus_name = NULL; 254 | 255 | switch(flag) { 256 | case 0: 257 | bus_name = val_drv_bus_name; 258 | bus = sysfs_open_bus(bus_name); 259 | if (bus == NULL) { 260 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 261 | return 0; 262 | } 263 | drvname = val_drv_name; 264 | break; 265 | case 1: 266 | bus_name = val_drv_bus_name; 267 | bus = sysfs_open_bus(bus_name); 268 | if (bus == NULL) { 269 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 270 | return 0; 271 | } 272 | drvname = inval_name; 273 | break; 274 | case 2: 275 | bus_name = val_drv_bus_name; 276 | bus = sysfs_open_bus(bus_name); 277 | if (bus == NULL) { 278 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 279 | return 0; 280 | } 281 | drvname = NULL; 282 | break; 283 | case 3: 284 | bus = NULL; 285 | drvname = val_drv_name; 286 | break; 287 | case 4: 288 | bus = NULL; 289 | drvname = inval_name; 290 | break; 291 | case 5: 292 | bus = NULL; 293 | drvname = NULL; 294 | break; 295 | default: 296 | return -1; 297 | } 298 | drv = sysfs_get_bus_driver(bus, drvname); 299 | 300 | switch (flag) { 301 | case 0: 302 | if (drv == NULL) { 303 | if (errno == 0) 304 | dbg_print("%s: Driver %s not on bus %s\n", 305 | __FUNCTION__, drvname, bus_name); 306 | else 307 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 308 | __FUNCTION__, flag, errno); 309 | } else { 310 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 311 | __FUNCTION__, flag); 312 | show_driver(drv); 313 | dbg_print("\n"); 314 | } 315 | break; 316 | case 1: 317 | case 2: 318 | case 3: 319 | case 4: 320 | case 5: 321 | if (drv != NULL) 322 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 323 | __FUNCTION__, flag, errno); 324 | else 325 | dbg_print("%s: SUCCEEDED with flag = %d\n", 326 | __FUNCTION__, flag); 327 | break; 328 | default: 329 | break; 330 | } 331 | 332 | if (bus != NULL) 333 | sysfs_close_bus(bus); 334 | 335 | return 0; 336 | } 337 | 338 | /** 339 | * extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus); 340 | * 341 | * flag: 342 | * 0 : bus -> valid 343 | * 1 : bus -> NULL 344 | */ 345 | int test_sysfs_get_bus_drivers(int flag) 346 | { 347 | struct sysfs_bus *bus = NULL; 348 | struct dlist *list = NULL; 349 | char *bus_name = NULL; 350 | 351 | switch (flag) { 352 | case 0: 353 | bus_name = val_bus_name; 354 | bus = sysfs_open_bus(bus_name); 355 | if (bus == NULL) { 356 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 357 | return 0; 358 | } 359 | break; 360 | case 1: 361 | bus = NULL; 362 | break; 363 | default: 364 | return -1; 365 | } 366 | list = sysfs_get_bus_drivers(bus); 367 | 368 | switch (flag) { 369 | case 0: 370 | if (list == NULL) { 371 | if (errno == 0) 372 | dbg_print("%s: No drivers registered with bus %s\n", 373 | __FUNCTION__, bus_name); 374 | else 375 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 376 | __FUNCTION__, flag, errno); 377 | } else { 378 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 379 | __FUNCTION__, flag); 380 | show_driver_list(list); 381 | dbg_print("\n"); 382 | } 383 | break; 384 | case 1: 385 | if (list != NULL) 386 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 387 | __FUNCTION__, flag, errno); 388 | else 389 | dbg_print("%s: SUCCEEDED with flag = %d\n", 390 | __FUNCTION__, flag); 391 | break; 392 | default: 393 | return 0; 394 | } 395 | if (bus != NULL) 396 | sysfs_close_bus(bus); 397 | 398 | return 0; 399 | } 400 | 401 | /** 402 | * extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus); 403 | * 404 | * flag: 405 | * 0 : bus -> valid 406 | * 1 : bus -> NULL 407 | */ 408 | int test_sysfs_get_bus_devices(int flag) 409 | { 410 | struct sysfs_bus *bus = NULL; 411 | struct dlist *list = NULL; 412 | char *bus_name = NULL; 413 | 414 | switch (flag) { 415 | case 0: 416 | bus_name = val_bus_name; 417 | bus = sysfs_open_bus(bus_name); 418 | if (bus == NULL) { 419 | dbg_print("%s: sysfs_open_bus() failed\n",__FUNCTION__); 420 | return 0; 421 | } 422 | break; 423 | case 1: 424 | bus = NULL; 425 | break; 426 | default: 427 | return -1; 428 | } 429 | list = sysfs_get_bus_devices(bus); 430 | 431 | switch (flag) { 432 | case 0: 433 | if (list == NULL) { 434 | if (errno == 0) 435 | dbg_print("%s: No devices registered with bus %s\n", 436 | __FUNCTION__, bus_name); 437 | else 438 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 439 | __FUNCTION__, flag, errno); 440 | } else { 441 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 442 | __FUNCTION__, flag); 443 | show_device_list(list); 444 | dbg_print("\n"); 445 | } 446 | break; 447 | case 1: 448 | if (list != NULL) 449 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 450 | __FUNCTION__, flag, errno); 451 | else 452 | dbg_print("%s: SUCCEEDED with flag = %d\n", 453 | __FUNCTION__, flag); 454 | break; 455 | default: 456 | return 0; 457 | } 458 | if (bus != NULL) 459 | sysfs_close_bus(bus); 460 | 461 | return 0; 462 | } 463 | -------------------------------------------------------------------------------- /test/test_device.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_root.c 3 | * 4 | * Tests for device/root device related functions for the libsysfs testsuite 5 | * 6 | * Copyright (C) IBM Corp. 2004-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | /** 24 | ****************************************************************************** 25 | * this will test the device/root device related functions provided by libsysfs 26 | * 27 | * extern void sysfs_close_device(struct sysfs_device *dev); 28 | * extern struct sysfs_device *sysfs_open_device 29 | * (const char *bus, const char *bus_id); 30 | * extern struct sysfs_device *sysfs_get_device_parent 31 | * (struct sysfs_device *dev); 32 | * extern struct sysfs_device *sysfs_open_device_path 33 | * (const char *path); 34 | * extern struct sysfs_attribute *sysfs_get_device_attr 35 | * (struct sysfs_device *dev, const char *name); 36 | * extern struct dlist *sysfs_get_device_attributes 37 | * (struct sysfs_device *device); 38 | ****************************************************************************** 39 | */ 40 | 41 | #include "config.h" 42 | 43 | #include "test-defs.h" 44 | #include 45 | 46 | /** 47 | * extern void sysfs_close_device(struct sysfs_device *dev); 48 | * 49 | * flag: 50 | * 0: dev -> valid 51 | * 1: dev -> NULL 52 | */ 53 | int test_sysfs_close_device(int flag) 54 | { 55 | struct sysfs_device *dev = NULL; 56 | char *path = NULL; 57 | 58 | switch (flag) { 59 | case 0: 60 | path = val_dev_path; 61 | dev = sysfs_open_device_path(path); 62 | if (dev == NULL) { 63 | dbg_print("%s: failed to open device at %s\n", 64 | __FUNCTION__, path); 65 | return 0; 66 | } 67 | break; 68 | case 1: 69 | dev = NULL; 70 | break; 71 | default: 72 | return -1; 73 | } 74 | sysfs_close_device(dev); 75 | 76 | dbg_print("%s: returns void\n", __FUNCTION__); 77 | return 0; 78 | } 79 | 80 | /** 81 | * extern struct sysfs_device *sysfs_open_device 82 | * (const char *bus, const char *bus_id); 83 | * 84 | * flag: 85 | * 0: bus -> valid, bus_id -> valid 86 | * 1: bus -> valid, bus_id -> invalid 87 | * 2: bus -> valid, bus_id -> invalid 88 | * 3: bus -> invalid, bus_id -> valid 89 | * 4: bus -> invalid, bus_id -> invalid 90 | * 5: bus -> invalid, bus_id -> invalid 91 | * 6: bus -> NULL, bus_id -> valid 92 | * 7: bus -> NULL, bus_id -> invalid 93 | * 8: bus -> NULL, bus_id -> invalid 94 | */ 95 | int test_sysfs_open_device(int flag) 96 | { 97 | struct sysfs_device *dev = NULL; 98 | char *bus = NULL; 99 | char *bus_id = NULL; 100 | 101 | switch (flag) { 102 | case 0: 103 | bus = val_bus_name; 104 | bus_id = val_bus_id; 105 | break; 106 | case 1: 107 | bus = val_bus_name; 108 | bus_id = inval_name; 109 | break; 110 | case 2: 111 | bus = val_bus_name; 112 | bus_id = NULL; 113 | break; 114 | case 3: 115 | bus = inval_name; 116 | bus_id = val_bus_id; 117 | break; 118 | case 4: 119 | bus = inval_name; 120 | bus_id = inval_name; 121 | break; 122 | case 5: 123 | bus = inval_name; 124 | bus_id = NULL; 125 | break; 126 | case 6: 127 | bus = NULL; 128 | bus_id = val_bus_id; 129 | break; 130 | case 7: 131 | bus = NULL; 132 | bus_id = inval_name; 133 | break; 134 | case 8: 135 | bus = NULL; 136 | bus_id = NULL; 137 | break; 138 | default: 139 | return -1; 140 | } 141 | dev = sysfs_open_device(bus, bus_id); 142 | 143 | switch (flag) { 144 | case 0: 145 | if (dev == NULL) 146 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 147 | __FUNCTION__, flag, errno); 148 | else { 149 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 150 | __FUNCTION__, flag); 151 | show_device(dev); 152 | dbg_print("\n"); 153 | } 154 | break; 155 | case 1: 156 | case 2: 157 | case 3: 158 | case 4: 159 | case 5: 160 | case 6: 161 | case 7: 162 | case 8: 163 | if (dev == NULL) 164 | dbg_print("%s: SUCCEEDED with flag = %d\n", 165 | __FUNCTION__, flag); 166 | else 167 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 168 | __FUNCTION__, flag, errno); 169 | break; 170 | } 171 | 172 | if (dev != NULL) 173 | sysfs_close_device(dev); 174 | return 0; 175 | } 176 | 177 | /** 178 | * extern struct sysfs_device *sysfs_get_device_parent 179 | * (struct sysfs_device *dev); 180 | * 181 | * flag: 182 | * 0: dev -> valid 183 | * 1: dev -> NULL 184 | */ 185 | int test_sysfs_get_device_parent(int flag) 186 | { 187 | struct sysfs_device *pdev = NULL; 188 | struct sysfs_device *dev = NULL; 189 | char *dev_path = NULL; 190 | 191 | switch (flag) { 192 | case 0: 193 | dev_path = val_dev_path; 194 | dev = sysfs_open_device_path(dev_path); 195 | if (dev == NULL) { 196 | dbg_print("%s: failed to open device at %s\n", 197 | __FUNCTION__, dev_path); 198 | return 0; 199 | } 200 | break; 201 | case 1: 202 | dev = NULL; 203 | break; 204 | default: 205 | return -1; 206 | } 207 | pdev = sysfs_get_device_parent(dev); 208 | 209 | switch (flag) { 210 | case 0: 211 | if (pdev == NULL) { 212 | if (errno == 0) 213 | dbg_print("%s: Device at %s does not have a parent\n", 214 | __FUNCTION__, dev_path); 215 | else 216 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 217 | __FUNCTION__, flag, errno); 218 | } else { 219 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 220 | __FUNCTION__, flag); 221 | show_device(pdev); 222 | dbg_print("\n"); 223 | } 224 | break; 225 | case 1: 226 | if (pdev == NULL) 227 | dbg_print("%s: SUCCEEDED with flag = %d\n", 228 | __FUNCTION__, flag); 229 | else 230 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 231 | __FUNCTION__, flag, errno); 232 | default: 233 | break; 234 | } 235 | if (dev != NULL) { 236 | sysfs_close_device(dev); 237 | } 238 | return 0; 239 | } 240 | 241 | /** 242 | * extern struct sysfs_device *sysfs_open_device_path 243 | * (const char *path); 244 | * 245 | * flag: 246 | * 0: path -> valid 247 | * 1: path -> invalid 248 | * 2: path -> NULL 249 | * 250 | */ 251 | int test_sysfs_open_device_path(int flag) 252 | { 253 | struct sysfs_device *dev = NULL; 254 | char *path = NULL; 255 | 256 | switch (flag) { 257 | case 0: 258 | path = val_dev_path; 259 | break; 260 | case 1: 261 | path = inval_path; 262 | break; 263 | case 2: 264 | path = NULL; 265 | break; 266 | default: 267 | return -1; 268 | } 269 | dev = sysfs_open_device_path(path); 270 | 271 | switch (flag) { 272 | case 0: 273 | if (dev == NULL) 274 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 275 | __FUNCTION__, flag, errno); 276 | else { 277 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 278 | __FUNCTION__, flag); 279 | show_device(dev); 280 | dbg_print("\n"); 281 | } 282 | break; 283 | case 1: 284 | case 2: 285 | if (dev == NULL) 286 | dbg_print("%s: SUCCEEDED with flag = %d\n", 287 | __FUNCTION__, flag); 288 | else 289 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 290 | __FUNCTION__, flag, errno); 291 | default: 292 | break; 293 | } 294 | if (dev != NULL) 295 | sysfs_close_device(dev); 296 | return 0; 297 | } 298 | 299 | /** 300 | * extern struct sysfs_attribute *sysfs_get_device_attr 301 | * (struct sysfs_device *dev, const char *name); 302 | * 303 | * flag: 304 | * 0: dev -> valid, name -> valid 305 | * 1: dev -> valid, name -> invalid 306 | * 2: dev -> valid, name -> NULL 307 | * 3: dev -> NULL, name -> valid 308 | * 4: dev -> NULL, name -> invalid 309 | * 5: dev -> NULL, name -> NULL 310 | */ 311 | int test_sysfs_get_device_attr(int flag) 312 | { 313 | struct sysfs_device *dev = NULL; 314 | char *name = NULL; 315 | char *path = NULL; 316 | struct sysfs_attribute *attr = NULL; 317 | 318 | switch (flag) { 319 | case 0: 320 | path = val_dev_path; 321 | dev = sysfs_open_device_path(path); 322 | if (dev == NULL) { 323 | dbg_print("%s: failed to open device at %s\n", 324 | __FUNCTION__, path); 325 | return 0; 326 | } 327 | name = val_dev_attr; 328 | break; 329 | case 1: 330 | dev = sysfs_open_device_path(path); 331 | name = inval_name; 332 | break; 333 | case 2: 334 | dev = sysfs_open_device_path(path); 335 | name = NULL; 336 | break; 337 | case 3: 338 | dev = NULL; 339 | name = val_dev_attr; 340 | break; 341 | case 4: 342 | dev = NULL; 343 | name = inval_name; 344 | break; 345 | case 5: 346 | dev = NULL; 347 | name = NULL; 348 | break; 349 | default: 350 | return -1; 351 | } 352 | attr = sysfs_get_device_attr(dev, name); 353 | 354 | switch (flag) { 355 | case 0: 356 | if (attr == NULL) { 357 | if (errno == EACCES) 358 | dbg_print("%s: attribute %s does not support READ\n", 359 | __FUNCTION__, name); 360 | else if (errno == ENOENT) 361 | dbg_print("%s: attribute %s not defined for device at %s\n", 362 | __FUNCTION__, name, path); 363 | else if (errno == 0) 364 | dbg_print("%s: device at %s does not export attributes\n", 365 | __FUNCTION__, path); 366 | else 367 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 368 | __FUNCTION__, flag, errno); 369 | } else { 370 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 371 | __FUNCTION__, flag); 372 | show_attribute(attr); 373 | dbg_print("\n"); 374 | } 375 | break; 376 | case 1: 377 | case 2: 378 | case 3: 379 | case 4: 380 | case 5: 381 | if (attr != NULL) 382 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 383 | __FUNCTION__, flag, errno); 384 | else { 385 | if (errno == EINVAL) 386 | dbg_print("%s: SUCCEEDED with flag = %d\n", 387 | __FUNCTION__, flag); 388 | else 389 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 390 | __FUNCTION__, flag, errno); 391 | } 392 | default: 393 | break; 394 | } 395 | 396 | if (dev != NULL) 397 | sysfs_close_device(dev); 398 | return 0; 399 | } 400 | 401 | /** 402 | * extern struct dlist *sysfs_get_device_attributes 403 | * (struct sysfs_device *device); 404 | * 405 | * flag: 406 | * 0: device -> valid 407 | * 1: device -> NULL 408 | */ 409 | int test_sysfs_get_device_attributes(int flag) 410 | { 411 | struct sysfs_device *device = NULL; 412 | struct dlist *list = NULL; 413 | char *path = NULL; 414 | 415 | switch (flag) { 416 | case 0: 417 | path = val_dev_path; 418 | device = sysfs_open_device_path(path); 419 | if (device == NULL) { 420 | dbg_print("%s: failed to open device at %s\n", 421 | __FUNCTION__, path); 422 | return 0; 423 | } 424 | break; 425 | case 1: 426 | device = NULL; 427 | break; 428 | default: 429 | return -1; 430 | } 431 | list = sysfs_get_device_attributes(device); 432 | 433 | switch (flag) { 434 | case 0: 435 | if (list == NULL) { 436 | if (errno == 0) 437 | dbg_print("%s: device at %s does not export attributes\n", 438 | __FUNCTION__, path); 439 | else 440 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 441 | __FUNCTION__, flag, errno); 442 | } else { 443 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 444 | __FUNCTION__, flag); 445 | show_attribute_list(list); 446 | dbg_print("\n"); 447 | } 448 | break; 449 | case 1: 450 | if (errno != EINVAL) 451 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 452 | __FUNCTION__, flag, errno); 453 | else 454 | dbg_print("%s: SUCCEEDED with flag = %d\n", 455 | __FUNCTION__, flag); 456 | default: 457 | break; 458 | } 459 | if (device != NULL) 460 | sysfs_close_device(device); 461 | return 0; 462 | } 463 | -------------------------------------------------------------------------------- /test/test_driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_driver.c 3 | * 4 | * Tests for driver related functions for the libsysfs testsuite 5 | * 6 | * Copyright (C) IBM Corp. 2004-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | /** 24 | ****************************************************************************** 25 | * this will test the driver related functions provided by libsysfs. 26 | * 27 | * extern void sysfs_close_driver(struct sysfs_driver *driver); 28 | * extern struct sysfs_driver *sysfs_open_driver 29 | * (const char *bus_name, const char *drv_name); 30 | * extern struct sysfs_driver *sysfs_open_driver_path 31 | * (const char *path); 32 | * extern struct sysfs_attribute *sysfs_get_driver_attr 33 | * (struct sysfs_driver *drv, const char *name); 34 | * extern struct dlist *sysfs_get_driver_attributes 35 | * (struct sysfs_driver *driver); 36 | * extern struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver); 37 | ****************************************************************************** 38 | */ 39 | 40 | #include "config.h" 41 | 42 | #include "test-defs.h" 43 | #include 44 | 45 | /** 46 | * extern void sysfs_close_driver(struct sysfs_driver *driver); 47 | * 48 | * flag: 49 | * 0: driver -> valid 50 | * 1: driver -> NULL 51 | */ 52 | int test_sysfs_close_driver(int flag) 53 | { 54 | struct sysfs_driver *driver = NULL; 55 | 56 | switch (flag) { 57 | case 0: 58 | driver = sysfs_open_driver_path(val_drv_path); 59 | if (driver == NULL) 60 | return 0; 61 | break; 62 | case 1: 63 | driver = NULL; 64 | break; 65 | default: 66 | return -1; 67 | } 68 | sysfs_close_driver(driver); 69 | 70 | dbg_print("%s: returns void\n", __FUNCTION__); 71 | return 0; 72 | } 73 | 74 | /** 75 | * extern struct sysfs_driver *sysfs_open_driver_path 76 | * (const char *path); 77 | * 78 | * flag: 79 | * 0: path -> valid 80 | * 1: path -> invalid 81 | * 2: path -> NULL 82 | */ 83 | int test_sysfs_open_driver_path(int flag) 84 | { 85 | struct sysfs_driver *driver = NULL; 86 | char *path = NULL; 87 | 88 | switch (flag) { 89 | case 0: 90 | path = val_drv_path; 91 | break; 92 | case 1: 93 | path = inval_path; 94 | break; 95 | case 2: 96 | path = NULL; 97 | break; 98 | default: 99 | return -1; 100 | } 101 | driver = sysfs_open_driver_path(path); 102 | 103 | switch (flag) { 104 | case 0: 105 | if (driver == NULL) 106 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 107 | __FUNCTION__, flag, errno); 108 | else { 109 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 110 | __FUNCTION__, flag); 111 | show_driver(driver); 112 | dbg_print("\n"); 113 | } 114 | break; 115 | case 1: 116 | case 2: 117 | if (driver != NULL) 118 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 119 | __FUNCTION__, flag, errno); 120 | else 121 | dbg_print("%s: SUCCEEDED with flag = %d\n", 122 | __FUNCTION__, flag); 123 | default: 124 | break; 125 | } 126 | if (driver != NULL) 127 | sysfs_close_driver(driver); 128 | 129 | return 0; 130 | } 131 | 132 | /** 133 | * extern struct sysfs_driver *sysfs_open_driver 134 | * (const char *bus_name, const char *drv_name); 135 | * 136 | * flag: 137 | * 0: path -> valid, name -> valid 138 | * 1: path -> valid, name -> invalid 139 | * 2: path -> valid, name -> NULL 140 | * 3: path -> invalid, name -> valid 141 | * 4: path -> invalid, name -> invalid 142 | * 5: path -> invalid, name -> NULL 143 | * 6: path -> NULL, name -> valid 144 | * 7: path -> NULL, name -> invalid 145 | * 8: path -> NULL, name -> NULL 146 | */ 147 | int test_sysfs_open_driver(int flag) 148 | { 149 | struct sysfs_driver *driver = NULL; 150 | char *bus_name = NULL; 151 | char *drv_name = NULL; 152 | 153 | switch (flag) { 154 | case 0: 155 | bus_name = val_drv_bus_name; 156 | drv_name = val_drv_name; 157 | dbg_print("bus_name = %s, drv_name = %s\n", bus_name, drv_name); 158 | break; 159 | case 1: 160 | bus_name = val_drv_bus_name; 161 | drv_name = inval_name; 162 | break; 163 | case 2: 164 | bus_name = val_drv_bus_name; 165 | drv_name = NULL; 166 | break; 167 | case 3: 168 | bus_name = inval_name; 169 | drv_name = val_drv_name; 170 | break; 171 | case 4: 172 | bus_name = inval_name; 173 | drv_name = inval_name; 174 | break; 175 | case 5: 176 | bus_name = inval_name; 177 | drv_name = NULL; 178 | break; 179 | case 6: 180 | bus_name = NULL; 181 | drv_name = val_drv_name; 182 | break; 183 | case 7: 184 | bus_name = NULL; 185 | drv_name = inval_name; 186 | break; 187 | case 8: 188 | bus_name = NULL; 189 | drv_name = NULL; 190 | break; 191 | 192 | default: 193 | return -1; 194 | } 195 | driver = sysfs_open_driver(bus_name, drv_name); 196 | switch (flag) { 197 | case 0: 198 | if (driver == NULL) 199 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 200 | __FUNCTION__, flag, errno); 201 | else { 202 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 203 | __FUNCTION__, flag); 204 | show_driver(driver); 205 | dbg_print("\n"); 206 | } 207 | break; 208 | case 1: 209 | case 2: 210 | if (driver != NULL) 211 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 212 | __FUNCTION__, flag, errno); 213 | else 214 | dbg_print("%s: SUCCEEDED with flag = %d\n", 215 | __FUNCTION__, flag); 216 | default: 217 | break; 218 | } 219 | if (driver != NULL) 220 | sysfs_close_driver(driver); 221 | 222 | return 0; 223 | } 224 | 225 | /** 226 | * extern struct sysfs_attribute *sysfs_get_driver_attr 227 | * (struct sysfs_driver *drv, const char *name); 228 | * 229 | * flag: 230 | * 0: drv -> valid, name -> valid 231 | * 1: drv -> valid, name -> invalid 232 | * 2: drv -> valid, name -> NULL 233 | * 3: drv -> NULL, name -> valid 234 | * 4: drv -> NULL, name -> invalid 235 | * 5: drv -> NULL, name -> NULL 236 | */ 237 | int test_sysfs_get_driver_attr(int flag) 238 | { 239 | char *name = NULL; 240 | char *attrname = NULL; 241 | struct sysfs_driver *drv = NULL; 242 | struct sysfs_attribute *attr = NULL; 243 | 244 | switch (flag) { 245 | case 0: 246 | name = val_drv_path; 247 | drv = sysfs_open_driver_path(name); 248 | if (drv == NULL) { 249 | dbg_print("%s: failed opening driver at %s\n", 250 | __FUNCTION__, name); 251 | return 0; 252 | } 253 | attrname = val_drv_attr_name; 254 | break; 255 | case 1: 256 | name = val_drv_path; 257 | drv = sysfs_open_driver_path(name); 258 | if (drv == NULL) { 259 | dbg_print("%s: failed opening driver at %s\n", 260 | __FUNCTION__, name); 261 | return 0; 262 | } 263 | attrname = inval_name; 264 | break; 265 | case 2: 266 | name = val_drv_path; 267 | drv = sysfs_open_driver_path(name); 268 | if (drv == NULL) { 269 | dbg_print("%s: failed opening driver at %s\n", 270 | __FUNCTION__, name); 271 | return 0; 272 | } 273 | attrname = NULL; 274 | break; 275 | case 3: 276 | drv = NULL; 277 | attrname = val_drv_attr_name; 278 | break; 279 | case 4: 280 | drv = NULL; 281 | attrname = inval_name; 282 | break; 283 | case 5: 284 | drv = NULL; 285 | attrname = NULL; 286 | break; 287 | default: 288 | return -1; 289 | } 290 | 291 | attr = sysfs_get_driver_attr(drv, attrname); 292 | switch (flag) { 293 | case 0: 294 | if (attr == NULL) { 295 | if (errno == EACCES) 296 | dbg_print("%s: attribute %s does not support READ\n", 297 | __FUNCTION__, attrname); 298 | else if (errno == ENOENT) 299 | dbg_print("%s: attribute %s not defined for driver at %s\n", 300 | __FUNCTION__, attrname, name); 301 | else if (errno == 0) 302 | dbg_print("%s: driver at %s does not export attributes\n", 303 | __FUNCTION__, val_drv_path); 304 | else 305 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 306 | __FUNCTION__, flag, errno); 307 | } else { 308 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 309 | __FUNCTION__, flag); 310 | show_attribute(attr); 311 | dbg_print("\n"); 312 | } 313 | break; 314 | case 1: 315 | case 2: 316 | case 3: 317 | case 4: 318 | case 5: 319 | if (attr != NULL) 320 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 321 | __FUNCTION__, flag, errno); 322 | else 323 | dbg_print("%s: SUCCEEDED with flag = %d\n", 324 | __FUNCTION__, flag); 325 | default: 326 | break; 327 | } 328 | if (drv != NULL) 329 | sysfs_close_driver(drv); 330 | 331 | return 0; 332 | } 333 | 334 | /** 335 | * extern struct dlist *sysfs_get_driver_attributes 336 | * (struct sysfs_driver *driver); 337 | * 338 | * flag: 339 | * 0: driver -> valid 340 | * 1: driver -> NULL 341 | */ 342 | int test_sysfs_get_driver_attributes(int flag) 343 | { 344 | struct sysfs_driver *driver = NULL; 345 | struct dlist *list = NULL; 346 | char *drv = NULL; 347 | 348 | switch (flag) { 349 | case 0: 350 | drv = val_drv_path; 351 | driver = sysfs_open_driver_path(drv); 352 | if (driver == NULL) { 353 | dbg_print("%s: failed opening driver at %s\n", 354 | __FUNCTION__, val_drv_path); 355 | return 0; 356 | } 357 | break; 358 | case 1: 359 | driver = NULL; 360 | break; 361 | case 2: 362 | drv = val_drv1_path; 363 | driver = sysfs_open_driver_path(drv); 364 | if (driver == NULL) { 365 | dbg_print("%s: failed opening driver at %s\n", 366 | __FUNCTION__, val_drv1_path); 367 | return 0; 368 | } 369 | break; 370 | default: 371 | return -1; 372 | } 373 | list = sysfs_get_driver_attributes(driver); 374 | 375 | switch (flag) { 376 | case 0: 377 | case 2: 378 | if (list == NULL) { 379 | if (errno == 0) 380 | dbg_print("%s: No attributes are defined for the driver at %s\n", 381 | __FUNCTION__, drv); 382 | else 383 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 384 | __FUNCTION__, flag, errno); 385 | } else { 386 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 387 | __FUNCTION__, flag); 388 | show_attribute_list(list); 389 | dbg_print("\n"); 390 | } 391 | break; 392 | case 1: 393 | if (list != NULL) 394 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 395 | __FUNCTION__, flag, errno); 396 | else 397 | dbg_print("%s: SUCCEEDED with flag = %d\n", 398 | __FUNCTION__, flag); 399 | default: 400 | break; 401 | } 402 | if (driver != NULL) 403 | sysfs_close_driver(driver); 404 | 405 | return 0; 406 | } 407 | 408 | /** 409 | * extern struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver); 410 | * 411 | * flag: 412 | * 0: driver -> valid 413 | * 1: driver -> NULL 414 | */ 415 | int test_sysfs_get_driver_devices(int flag) 416 | { 417 | struct sysfs_driver *driver = NULL; 418 | struct dlist *list = NULL; 419 | char *drv = NULL; 420 | 421 | switch (flag) { 422 | case 0: 423 | drv = val_drv_path; 424 | driver = sysfs_open_driver_path(drv); 425 | if (driver == NULL) { 426 | dbg_print("%s: failed opening driver at %s\n", 427 | __FUNCTION__, val_drv_path); 428 | return 0; 429 | } 430 | break; 431 | case 1: 432 | driver = NULL; 433 | break; 434 | case 2: 435 | drv = val_drv1_path; 436 | driver = sysfs_open_driver_path(drv); 437 | if (driver == NULL) { 438 | dbg_print("%s: failed opening driver at %s\n", 439 | __FUNCTION__, val_drv1_path); 440 | return 0; 441 | } 442 | break; 443 | default: 444 | return -1; 445 | } 446 | errno = 0; 447 | list = sysfs_get_driver_devices(driver); 448 | 449 | switch (flag) { 450 | case 0: 451 | case 2: 452 | if (list == NULL) { 453 | if (errno == 0) 454 | dbg_print("%s: No devices are using the driver at %s\n", 455 | __FUNCTION__, drv); 456 | else 457 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 458 | __FUNCTION__, flag, errno); 459 | } else { 460 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 461 | __FUNCTION__, flag); 462 | show_device_list(list); 463 | dbg_print("\n"); 464 | } 465 | break; 466 | case 1: 467 | if (list != NULL) 468 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 469 | __FUNCTION__, flag, errno); 470 | else 471 | dbg_print("%s: SUCCEEDED with flag = %d\n", 472 | __FUNCTION__, flag); 473 | default: 474 | break; 475 | } 476 | if (driver != NULL) 477 | sysfs_close_driver(driver); 478 | 479 | return 0; 480 | } 481 | -------------------------------------------------------------------------------- /test/test_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * test_utils.c 3 | * 4 | * Tests for utility functions for the libsysfs testsuite 5 | * 6 | * Copyright (C) IBM Corp. 2004-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | /** 24 | *************************************************************************** 25 | * this will test the utility functions provided by libsysfs. 26 | * 27 | * extern int sysfs_get_mnt_path(char *mnt_path, size_t len); 28 | * extern int sysfs_remove_trailing_slash(char *path); 29 | * extern int sysfs_get_name_from_path(const char *path, 30 | * char *name, size_t len); 31 | * extern int sysfs_path_is_dir(const char *path); 32 | * extern int sysfs_path_is_link(const char *path); 33 | * extern int sysfs_path_is_file(const char *path); 34 | * extern int sysfs_get_link(const char *path, char *target, size_t len); 35 | * extern struct dlist *sysfs_open_directory_list(char *name); 36 | * extern struct dlist *sysfs_open_link_list(char *name); 37 | * extern void sysfs_close_list(struct dlist *list); 38 | ***************************************************************************** 39 | */ 40 | 41 | #include "config.h" 42 | 43 | #include "test-defs.h" 44 | #include 45 | 46 | /** 47 | * extern int sysfs_get_mnt_path(char *mnt_path, size_t len); 48 | * 49 | * flag: 50 | * 0: mnt_path -> valid, len -> valid 51 | * 1: mnt_path -> valid, len -> 0 52 | * 2: mnt_path -> NULL, len -> valid 53 | * 3: mnt_path -> NULL, len -> NULL 54 | */ 55 | int test_sysfs_get_mnt_path(int flag) 56 | { 57 | char *mnt_path = NULL; 58 | size_t len = 0; 59 | int ret = 0; 60 | 61 | switch (flag) { 62 | case 0: 63 | mnt_path = calloc(1, SYSFS_PATH_MAX); 64 | len = SYSFS_PATH_MAX; 65 | break; 66 | case 1: 67 | mnt_path = calloc(1, SYSFS_PATH_MAX); 68 | len = 0; 69 | break; 70 | case 2: 71 | mnt_path = NULL; 72 | len = SYSFS_PATH_MAX; 73 | break; 74 | case 3: 75 | mnt_path = NULL; 76 | len = 0; 77 | break; 78 | default: 79 | return -1; 80 | } 81 | ret = sysfs_get_mnt_path(mnt_path, len); 82 | 83 | switch (flag) { 84 | case 0: 85 | if (ret) 86 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 87 | __FUNCTION__, flag, errno); 88 | else { 89 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 90 | __FUNCTION__, flag); 91 | dbg_print("sysfs is mounted at \"%s\"\n\n", mnt_path); 92 | } 93 | break; 94 | case 1: 95 | case 2: 96 | case 3: 97 | if (!ret) 98 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 99 | __FUNCTION__, flag, errno); 100 | else 101 | dbg_print("%s: SUCCEEDED with flag = %d\n", 102 | __FUNCTION__, flag); 103 | break; 104 | default: 105 | break; 106 | } 107 | if (mnt_path != NULL) { 108 | free(mnt_path); 109 | mnt_path = NULL; 110 | } 111 | 112 | return 0; 113 | } 114 | 115 | /** 116 | * extern int sysfs_remove_trailing_slash(char *path); 117 | * 118 | * flag: 119 | * 0: path -> valid 120 | * 1: path -> NULL 121 | */ 122 | int test_sysfs_remove_trailing_slash(int flag) 123 | { 124 | char *path = NULL; 125 | int ret = 0; 126 | 127 | switch (flag) { 128 | case 0: 129 | path = calloc(1, SYSFS_PATH_MAX); 130 | strcpy(path, "/some/path/is/this/"); 131 | break; 132 | case 1: 133 | path = NULL; 134 | break; 135 | default: 136 | return -1; 137 | } 138 | ret = sysfs_remove_trailing_slash(path); 139 | 140 | switch (flag) { 141 | case 0: 142 | if (ret != 0) 143 | dbg_print("%s: FAILED with flag = %d errno = %d\n\n", 144 | __FUNCTION__, flag, errno); 145 | else { 146 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 147 | __FUNCTION__, flag); 148 | dbg_print("Path now is \"%s\"\n\n", path); 149 | } 150 | break; 151 | case 1: 152 | if (ret == 0) 153 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 154 | __FUNCTION__, flag, errno); 155 | else 156 | dbg_print("%s: SUCCEEDED with flag = %d\n", 157 | __FUNCTION__, flag); 158 | break; 159 | default: 160 | break; 161 | } 162 | 163 | if (path != NULL) { 164 | free(path); 165 | path = NULL; 166 | } 167 | 168 | return 0; 169 | } 170 | 171 | /** 172 | * extern int sysfs_get_name_from_path(const char *path, 173 | * char *name, size_t len); 174 | * 175 | * flag: 176 | * 0: path -> valid, name -> valid, len -> valid 177 | * 1: path -> valid, name -> NULL, len -> invalid 178 | * 2: path -> NULL, name -> valid, len -> valid 179 | * 3: path -> NULL, name -> NULL, len -> invalid 180 | */ 181 | int test_sysfs_get_name_from_path(int flag) 182 | { 183 | char *path = NULL; 184 | char *name = NULL; 185 | size_t len = SYSFS_NAME_LEN; 186 | int ret = 0; 187 | 188 | switch (flag) { 189 | case 0: 190 | path = val_dir_path; 191 | name = calloc(1, SYSFS_NAME_LEN); 192 | break; 193 | case 1: 194 | path = val_dir_path; 195 | name = NULL; 196 | break; 197 | case 2: 198 | path = NULL; 199 | name = calloc(1, SYSFS_NAME_LEN); 200 | break; 201 | case 3: 202 | path = NULL; 203 | name = NULL; 204 | break; 205 | default: 206 | return -1; 207 | } 208 | ret = sysfs_get_name_from_path(path, name, len); 209 | 210 | switch (flag) { 211 | case 0: 212 | if (ret != 0) 213 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 214 | __FUNCTION__, flag, errno); 215 | else { 216 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 217 | __FUNCTION__, flag); 218 | dbg_print("Name extracted from \"%s\" is \"%s\"\n\n", 219 | path, name); 220 | } 221 | break; 222 | case 1: 223 | case 2: 224 | case 3: 225 | if (ret == 0) 226 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 227 | __FUNCTION__, flag, errno); 228 | else 229 | dbg_print("%s: SUCCEEDED with flag = %d\n", 230 | __FUNCTION__, flag); 231 | break; 232 | default: 233 | break; 234 | } 235 | if (name != NULL) { 236 | free(name); 237 | name = NULL; 238 | } 239 | 240 | return 0; 241 | } 242 | 243 | /** 244 | * extern int sysfs_path_is_dir(const char *path); 245 | * 246 | * flag: 247 | * 0: path -> valid 248 | * 1: path -> invalid 249 | * 2: path -> NULL 250 | */ 251 | int test_sysfs_path_is_dir(int flag) 252 | { 253 | char *path = NULL; 254 | int ret = 0; 255 | 256 | switch (flag) { 257 | case 0: 258 | path = val_dir_path; 259 | break; 260 | case 1: 261 | path = inval_path; 262 | break; 263 | case 2: 264 | path = NULL; 265 | break; 266 | default: 267 | return -1; 268 | } 269 | ret = sysfs_path_is_dir(path); 270 | 271 | switch (flag) { 272 | case 0: 273 | if (ret != 0) 274 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 275 | __FUNCTION__, flag, errno); 276 | else { 277 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 278 | __FUNCTION__, flag); 279 | dbg_print("Path \"%s\" points to a directory\n\n", 280 | path); 281 | } 282 | break; 283 | case 1: 284 | case 2: 285 | if (ret == 0) 286 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 287 | __FUNCTION__, flag, errno); 288 | else 289 | dbg_print("%s: SUCCEEDED with flag = %d\n", 290 | __FUNCTION__, flag); 291 | break; 292 | default: 293 | return 0; 294 | break; 295 | } 296 | 297 | return 0; 298 | } 299 | 300 | /** 301 | * extern int sysfs_path_is_link(const char *path); 302 | * 303 | * flag: 304 | * 0: path -> valid 305 | * 1: path -> invalid 306 | * 2: path -> NULL 307 | */ 308 | int test_sysfs_path_is_link(int flag) 309 | { 310 | char *path = NULL; 311 | int ret = 0; 312 | 313 | switch (flag) { 314 | case 0: 315 | path = val_link_path; 316 | break; 317 | case 1: 318 | path = inval_path; 319 | break; 320 | case 2: 321 | path = NULL; 322 | break; 323 | default: 324 | return -1; 325 | } 326 | ret = sysfs_path_is_link(path); 327 | 328 | switch (flag) { 329 | case 0: 330 | if (ret != 0) 331 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 332 | __FUNCTION__, flag, errno); 333 | else { 334 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 335 | __FUNCTION__, flag); 336 | dbg_print("Path \"%s\" points to a link\n\n", 337 | path); 338 | } 339 | break; 340 | case 1: 341 | case 2: 342 | if (ret == 0) 343 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 344 | __FUNCTION__, flag, errno); 345 | else 346 | dbg_print("%s: SUCCEEDED with flag = %d\n", 347 | __FUNCTION__, flag); 348 | break; 349 | default: 350 | return 0; 351 | break; 352 | } 353 | 354 | return 0; 355 | } 356 | 357 | /** 358 | * extern int sysfs_path_is_file(const char *path); 359 | * 360 | * flag: 361 | * 0: path -> valid 362 | * 1: path -> invalid 363 | * 2: path -> NULL 364 | */ 365 | int test_sysfs_path_is_file(int flag) 366 | { 367 | char *path = NULL; 368 | int ret = 0; 369 | 370 | switch (flag) { 371 | case 0: 372 | path = val_file_path; 373 | break; 374 | case 1: 375 | path = inval_path; 376 | break; 377 | case 2: 378 | path = NULL; 379 | break; 380 | default: 381 | return -1; 382 | } 383 | ret = sysfs_path_is_file(path); 384 | 385 | switch (flag) { 386 | case 0: 387 | if (ret != 0) 388 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 389 | __FUNCTION__, flag, errno); 390 | else { 391 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 392 | __FUNCTION__, flag); 393 | dbg_print("Path \"%s\" points to a file\n\n", 394 | path); 395 | } 396 | break; 397 | case 1: 398 | case 2: 399 | if (ret == 0) 400 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 401 | __FUNCTION__, flag, errno); 402 | else 403 | dbg_print("%s: SUCCEEDED with flag = %d\n", 404 | __FUNCTION__, flag); 405 | break; 406 | default: 407 | return 0; 408 | break; 409 | } 410 | return 0; 411 | } 412 | 413 | /** 414 | * extern int sysfs_get_link(const char *path, 415 | * char *target, size_t len); 416 | * 417 | * flag: 418 | * 0: path -> valid, target -> valid 419 | * 1: path -> valid, target -> NULL 420 | * 2: path -> NULL, target -> valid 421 | * 3: path -> NULL, target -> NULL 422 | */ 423 | int test_sysfs_get_link(int flag) 424 | { 425 | char *path = NULL; 426 | char *target = NULL; 427 | size_t len = SYSFS_PATH_MAX; 428 | int ret = 0; 429 | 430 | switch (flag) { 431 | case 0: 432 | path = val_link_path; 433 | target = calloc(1, SYSFS_PATH_MAX); 434 | break; 435 | case 1: 436 | path = val_link_path; 437 | target = NULL; 438 | break; 439 | case 2: 440 | path = NULL; 441 | target = calloc(1, SYSFS_PATH_MAX); 442 | break; 443 | case 3: 444 | path = NULL; 445 | target = NULL; 446 | break; 447 | default: 448 | return -1; 449 | } 450 | ret = sysfs_get_link(path, target, len); 451 | 452 | switch (flag) { 453 | case 0: 454 | if (ret != 0) 455 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 456 | __FUNCTION__, flag, errno); 457 | else { 458 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 459 | __FUNCTION__, flag); 460 | dbg_print("Link at \"%s\" points to \"%s\"\n\n", 461 | path, target); 462 | } 463 | break; 464 | case 1: 465 | case 2: 466 | case 3: 467 | if (ret == 0) 468 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 469 | __FUNCTION__, flag, errno); 470 | else 471 | dbg_print("%s: SUCCEEDED with flag = %d\n", 472 | __FUNCTION__, flag); 473 | break; 474 | default: 475 | return 0; 476 | break; 477 | } 478 | if (target != NULL) { 479 | free(target); 480 | target = NULL; 481 | } 482 | 483 | return 0; 484 | } 485 | 486 | /** 487 | * extern struct dlist *sysfs_open_directory_list(char *name); 488 | * 489 | * flag: 490 | * 0: name -> valid 491 | * 1: name -> invalid 492 | * 2: name -> NULL 493 | * 494 | */ 495 | int test_sysfs_open_directory_list(int flag) 496 | { 497 | char *path = NULL; 498 | struct dlist *list = NULL; 499 | 500 | switch (flag) { 501 | case 0: 502 | path = val_dir_path; 503 | break; 504 | case 1: 505 | path = inval_path; 506 | break; 507 | case 2: 508 | path = NULL; 509 | break; 510 | default: 511 | return -1; 512 | } 513 | list = sysfs_open_directory_list(path); 514 | 515 | switch (flag) { 516 | case 0: 517 | if (list == NULL) 518 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 519 | __FUNCTION__, flag, errno); 520 | else { 521 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 522 | __FUNCTION__, flag); 523 | show_list(list); 524 | dbg_print("\n"); 525 | } 526 | break; 527 | case 1: 528 | case 2: 529 | if (list != NULL) 530 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 531 | __FUNCTION__, flag, errno); 532 | else 533 | dbg_print("%s: SUCCEEDED with flag = %d\n", 534 | __FUNCTION__, flag); 535 | break; 536 | default: 537 | break; 538 | } 539 | if (list != NULL) { 540 | sysfs_close_list(list); 541 | list = NULL; 542 | } 543 | 544 | return 0; 545 | } 546 | 547 | /** 548 | * extern struct dlist *sysfs_open_link_list(char *name); 549 | * 550 | * flag: 551 | * 0: name -> valid 552 | * 1: name -> invalid 553 | * 2: name -> NULL 554 | * 555 | */ 556 | int test_sysfs_open_link_list(int flag) 557 | { 558 | char *path = NULL; 559 | struct dlist *list = NULL; 560 | 561 | switch (flag) { 562 | case 0: 563 | path = val_link_path; 564 | break; 565 | case 1: 566 | path = inval_path; 567 | break; 568 | case 2: 569 | path = NULL; 570 | break; 571 | default: 572 | return -1; 573 | } 574 | list = sysfs_open_link_list(path); 575 | 576 | switch (flag) { 577 | case 0: 578 | if (list == NULL) 579 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 580 | __FUNCTION__, flag, errno); 581 | else { 582 | dbg_print("%s: SUCCEEDED with flag = %d\n\n", 583 | __FUNCTION__, flag); 584 | show_list(list); 585 | dbg_print("\n"); 586 | } 587 | break; 588 | case 1: 589 | case 2: 590 | if (list != NULL) 591 | dbg_print("%s: FAILED with flag = %d errno = %d\n", 592 | __FUNCTION__, flag, errno); 593 | else 594 | dbg_print("%s: SUCCEEDED with flag = %d\n", 595 | __FUNCTION__, flag); 596 | break; 597 | default: 598 | break; 599 | } 600 | if (list != NULL) { 601 | sysfs_close_list(list); 602 | list = NULL; 603 | } 604 | 605 | return 0; 606 | } 607 | /** 608 | * extern void sysfs_close_list(struct dlist *list); 609 | * 610 | * flag: 611 | * 0: list -> valid 612 | * 1: list -> NULL 613 | */ 614 | int test_sysfs_close_list(int flag) 615 | { 616 | struct dlist *list = NULL; 617 | 618 | switch (flag) { 619 | case 0: 620 | list = NULL; 621 | break; 622 | default: 623 | return -1; 624 | } 625 | sysfs_close_list(list); 626 | 627 | dbg_print("%s: returns void\n", __FUNCTION__); 628 | 629 | return 0; 630 | } 631 | -------------------------------------------------------------------------------- /test/testout.c: -------------------------------------------------------------------------------- 1 | /* 2 | * testout.c 3 | * 4 | * Display routines for the libsysfs testsuite 5 | * 6 | * Copyright (C) IBM Corp. 2004-2005 7 | * 8 | * This program is free software; you can redistribute it and/or modify it 9 | * under the terms of the GNU General Public License as published by the 10 | * Free Software Foundation version 2 of the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 675 Mass Ave, Cambridge, MA 02139, USA. 20 | * 21 | */ 22 | 23 | /** 24 | * Display routines for test functions 25 | */ 26 | 27 | #include "config.h" 28 | 29 | #include 30 | 31 | static void remove_end_newline(char *value) 32 | { 33 | char *p = value + (strlen(value) - 1); 34 | 35 | if (p != NULL && *p == '\n') 36 | *p = '\0'; 37 | } 38 | 39 | void show_device(struct sysfs_device *device) 40 | { 41 | if (device != NULL) 42 | dbg_print("Device is \"%s\" at \"%s\"\n", 43 | device->name, device->path); 44 | } 45 | 46 | void show_driver(struct sysfs_driver *driver) 47 | { 48 | if (driver != NULL) 49 | dbg_print("Driver is \"%s\" at \"%s\"\n", 50 | driver->name, driver->path); 51 | } 52 | 53 | void show_device_list(struct dlist *devlist) 54 | { 55 | if (devlist != NULL) { 56 | struct sysfs_device *dev = NULL; 57 | 58 | dlist_for_each_data(devlist, dev, struct sysfs_device) 59 | show_device(dev); 60 | } 61 | } 62 | 63 | void show_driver_list(struct dlist *drvlist) 64 | { 65 | if (drvlist != NULL) { 66 | struct sysfs_driver *drv = NULL; 67 | 68 | dlist_for_each_data(drvlist, drv, struct sysfs_driver) 69 | show_driver(drv); 70 | } 71 | } 72 | 73 | void show_attribute(struct sysfs_attribute *attr) 74 | { 75 | if (attr != NULL) { 76 | if (attr->value) 77 | remove_end_newline(attr->value); 78 | dbg_print("Attr \"%s\" at \"%s\" has a value \"%s\" \n", 79 | attr->name, attr->path, attr->value); 80 | } 81 | } 82 | 83 | void show_attribute_list(struct dlist *attrlist) 84 | { 85 | if (attrlist != NULL) { 86 | struct sysfs_attribute *attr = NULL; 87 | 88 | dlist_for_each_data(attrlist, attr, struct sysfs_attribute) 89 | show_attribute(attr); 90 | } 91 | } 92 | 93 | void show_class_device(struct sysfs_class_device *dev) 94 | { 95 | if (dev != NULL) 96 | dbg_print("Class device \"%s\" belongs to the \"%s\" class\n", 97 | dev->name, dev->classname); 98 | } 99 | 100 | void show_class_device_list(struct dlist *devlist) 101 | { 102 | if (devlist != NULL) { 103 | struct sysfs_class_device *dev = NULL; 104 | 105 | dlist_for_each_data(devlist, dev, struct sysfs_class_device) 106 | show_class_device(dev); 107 | } 108 | } 109 | 110 | void show_list(struct dlist *list) 111 | { 112 | if (list != NULL) { 113 | char *name = NULL; 114 | 115 | dlist_for_each_data(list, name, char) 116 | dbg_print("%s\n", name); 117 | } 118 | } 119 | 120 | void show_parm_list(struct dlist *list) 121 | { 122 | if (list != NULL) { 123 | char *name = NULL; 124 | 125 | dlist_for_each_data(list, name, char) 126 | dbg_print("%s\n", name); 127 | } 128 | } 129 | 130 | void show_section_list(struct dlist *list) 131 | { 132 | if (list != NULL) { 133 | char *name = NULL; 134 | 135 | dlist_for_each_data(list, name, char) 136 | dbg_print("%s\n", name); 137 | } 138 | } 139 | 140 | void show_module(struct sysfs_module *module) 141 | { 142 | if (module) { 143 | dbg_print("Module name is %s, path is %s\n", 144 | module->name, module->path); 145 | show_attribute_list(module->attrlist); 146 | show_parm_list(module->parmlist); 147 | show_section_list(module->sections); 148 | } 149 | } 150 | --------------------------------------------------------------------------------