diff options
author | Christophe Fergeau <cfergeau@mandriva.com> | 2009-04-03 17:46:41 +0000 |
---|---|---|
committer | Christophe Fergeau <cfergeau@mandriva.com> | 2009-04-03 17:46:41 +0000 |
commit | 799454569d7b3f62d0e93719d298c438812bedf1 (patch) | |
tree | 76e6fe5a2165ef66eda92720676393e400cb2993 | |
parent | c6ca41dab1d22400ae8bccee56968badc641a849 (diff) | |
download | ldetect-799454569d7b3f62d0e93719d298c438812bedf1.tar ldetect-799454569d7b3f62d0e93719d298c438812bedf1.tar.gz ldetect-799454569d7b3f62d0e93719d298c438812bedf1.tar.bz2 ldetect-799454569d7b3f62d0e93719d298c438812bedf1.tar.xz ldetect-799454569d7b3f62d0e93719d298c438812bedf1.zip |
Forgot to add sysfs files
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | hid.c | 2 | ||||
-rw-r--r-- | libsysfs.h | 90 | ||||
-rw-r--r-- | sysfs.h | 64 | ||||
-rw-r--r-- | sysfs_attr.c | 241 | ||||
-rw-r--r-- | sysfs_utils.c | 59 |
6 files changed, 457 insertions, 3 deletions
@@ -46,8 +46,8 @@ pciusb.o: pciusb.c libldetect.h common.h pci.o: pci.c libldetect.h common.h usb.o: usb.c libldetect.h common.h dmi.o: dmi.c libldetect.h common.h -sysfs_attr.o: sysfs/sysfs_attr.c sysfs/sysfs.h sysfs/libsysfs.h -sysfs_utils.o: sysfs/sysfs_utils.c sysfs/sysfs.h sysfs/libsysfs.h +sysfs_attr.o: sysfs_attr.c sysfs.h libsysfs.h +sysfs_utils.o: sysfs_utils.c sysfs.h libsysfs.h clean: rm -f *~ *.o pciclass.c usbclass.c $(binaries) $(libraries) @@ -6,7 +6,7 @@ #include <stdlib.h> #include <string.h> -#include "sysfs/libsysfs.h" +#include "libsysfs.h" #include "libldetect.h" #include "common.h" diff --git a/libsysfs.h b/libsysfs.h new file mode 100644 index 0000000..7bdf54f --- /dev/null +++ b/libsysfs.h @@ -0,0 +1,90 @@ +/* + * libsysfs.h + * + * Header Definitions for libsysfs + * + * Copyright (C) IBM Corp. 2004-2005 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _LIBSYSFS_H_ +#define _LIBSYSFS_H_ + +#include <sys/types.h> +#include <string.h> + +#define SYSFS_FSTYPE_NAME "sysfs" +#define SYSFS_PROC_MNTS "/proc/mounts" +#define SYSFS_BUS_NAME "bus" +#define SYSFS_CLASS_NAME "class" +#define SYSFS_BLOCK_NAME "block" +#define SYSFS_DEVICES_NAME "devices" +#define SYSFS_DRIVERS_NAME "drivers" +#define SYSFS_MODULE_NAME "module" +#define SYSFS_NAME_ATTRIBUTE "name" +#define SYSFS_MOD_PARM_NAME "parameters" +#define SYSFS_MOD_SECT_NAME "sections" +#define SYSFS_UNKNOWN "unknown" +#define SYSFS_PATH_ENV "SYSFS_PATH" + +#define SYSFS_PATH_MAX 256 +#define SYSFS_NAME_LEN 64 +#define SYSFS_BUS_ID_SIZE 32 + +/* mount path for sysfs, can be overridden by exporting SYSFS_PATH */ +#define SYSFS_MNT_PATH "/sys" + +enum sysfs_attribute_method { + SYSFS_METHOD_SHOW = 0x01, /* attr can be read by user */ + SYSFS_METHOD_STORE = 0x02, /* attr can be changed by user */ +}; + +/* + * NOTE: + * 1. We have the statically allocated "name" as the first element of all + * the structures. This feature is used in the "sorter" function for dlists + * 2. As is the case with attrlist + * 3. As is the case with path + */ +struct sysfs_attribute { + char name[SYSFS_NAME_LEN]; + char path[SYSFS_PATH_MAX]; + char *value; + unsigned short len; /* value length */ + enum sysfs_attribute_method method; /* show and store */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Function Prototypes + */ +extern int sysfs_get_name_from_path(const char *path, char *name, size_t len); + +/* sysfs directory and file access */ +extern void sysfs_close_attribute(struct sysfs_attribute *sysattr); +extern struct sysfs_attribute *sysfs_open_attribute(const char *path); +extern int sysfs_read_attribute(struct sysfs_attribute *sysattr); +extern int sysfs_write_attribute(struct sysfs_attribute *sysattr, + const char *new_value, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBSYSFS_H_ */ @@ -0,0 +1,64 @@ +/* + * sysfs.h + * + * Internal Header Definitions for libsysfs + * + * Copyright (C) IBM Corp. 2003-2005 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _SYSFS_H_ +#define _SYSFS_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <dirent.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#define safestrcpy(to, from) strncpy(to, from, sizeof(to)-1) +#define safestrcat(to, from) strncat(to, from, sizeof(to) - strlen(to)-1) + +#define safestrcpymax(to, from, max) \ +do { \ + to[max-1] = '\0'; \ + strncpy(to, from, max-1); \ +} while (0) + +#define safestrcatmax(to, from, max) \ +do { \ + to[max-1] = '\0'; \ + strncat(to, from, max - strlen(to)-1); \ +} while (0) + +extern struct sysfs_attribute *get_attribute(void *dev, const char *name); +extern struct dlist *read_dir_subdirs(const char *path); +extern struct dlist *read_dir_links(const char *path); +extern struct dlist *get_dev_attributes_list(void *dev); +extern struct dlist *get_attributes_list(struct dlist *alist, const char *path); + +/* Debugging */ +#ifdef DEBUG +#define dprintf(format, arg...) fprintf(stderr, format, ## arg) +#else +#define dprintf(format, arg...) do { } while (0) +#endif + +#endif /* _SYSFS_H_ */ diff --git a/sysfs_attr.c b/sysfs_attr.c new file mode 100644 index 0000000..6d67711 --- /dev/null +++ b/sysfs_attr.c @@ -0,0 +1,241 @@ +/* + * sysfs_dir.c + * + * Directory utility functions for libsysfs + * + * Copyright (C) IBM Corp. 2003-2005 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "libsysfs.h" +#include "sysfs.h" + +/** + * sysfs_close_attribute: closes and cleans up attribute + * @sysattr: attribute to close. + */ +void sysfs_close_attribute(struct sysfs_attribute *sysattr) +{ + if (sysattr) { + if (sysattr->value) + free(sysattr->value); + free(sysattr); + } +} + +/** + * alloc_attribute: allocates and initializes attribute structure + * returns struct sysfs_attribute with success and NULL with error. + */ +static struct sysfs_attribute *alloc_attribute(void) +{ + return (struct sysfs_attribute *) + calloc(1, sizeof(struct sysfs_attribute)); +} + +/** + * sysfs_open_attribute: creates sysfs_attribute structure + * @path: path to attribute. + * returns sysfs_attribute struct with success and NULL with error. + */ +struct sysfs_attribute *sysfs_open_attribute(const char *path) +{ + struct sysfs_attribute *sysattr = NULL; + struct stat fileinfo; + + if (!path) { + errno = EINVAL; + return NULL; + } + sysattr = alloc_attribute(); + if (!sysattr) { + dprintf("Error allocating attribute at %s\n", path); + return NULL; + } + if (sysfs_get_name_from_path(path, sysattr->name, + SYSFS_NAME_LEN) != 0) { + dprintf("Error retrieving attrib name from path: %s\n", path); + sysfs_close_attribute(sysattr); + return NULL; + } + safestrcpy(sysattr->path, path); + if ((stat(sysattr->path, &fileinfo)) != 0) { + dprintf("Stat failed: No such attribute?\n"); + sysattr->method = 0; + free(sysattr); + sysattr = NULL; + } else { + if (fileinfo.st_mode & S_IRUSR) + sysattr->method |= SYSFS_METHOD_SHOW; + if (fileinfo.st_mode & S_IWUSR) + sysattr->method |= SYSFS_METHOD_STORE; + } + + return sysattr; +} + +/** + * sysfs_read_attribute: reads value from attribute + * @sysattr: attribute to read + * returns 0 with success and -1 with error. + */ +int sysfs_read_attribute(struct sysfs_attribute *sysattr) +{ + char *fbuf = NULL; + char *vbuf = NULL; + ssize_t length = 0; + long pgsize = 0; + int fd; + + if (!sysattr) { + errno = EINVAL; + return -1; + } + if (!(sysattr->method & SYSFS_METHOD_SHOW)) { + dprintf("Show method not supported for attribute %s\n", + sysattr->path); + errno = EACCES; + return -1; + } + pgsize = getpagesize(); + fbuf = (char *)calloc(1, pgsize+1); + if (!fbuf) { + dprintf("calloc failed\n"); + return -1; + } + if ((fd = open(sysattr->path, O_RDONLY)) < 0) { + dprintf("Error reading attribute %s\n", sysattr->path); + free(fbuf); + return -1; + } + length = read(fd, fbuf, pgsize); + if (length < 0) { + dprintf("Error reading from attribute %s\n", sysattr->path); + close(fd); + free(fbuf); + return -1; + } + if (sysattr->len > 0) { + if ((sysattr->len == length) && + (!(strncmp(sysattr->value, fbuf, length)))) { + close(fd); + free(fbuf); + return 0; + } + free(sysattr->value); + } + sysattr->len = length; + close(fd); + vbuf = (char *)realloc(fbuf, length+1); + if (!vbuf) { + dprintf("realloc failed\n"); + free(fbuf); + return -1; + } + sysattr->value = vbuf; + + return 0; +} + +/** + * sysfs_write_attribute: write value to the attribute + * @sysattr: attribute to write + * @new_value: value to write + * @len: length of "new_value" + * returns 0 with success and -1 with error. + */ +int sysfs_write_attribute(struct sysfs_attribute *sysattr, + const char *new_value, size_t len) +{ + int fd; + int length; + + if (!sysattr || !new_value || len == 0) { + errno = EINVAL; + return -1; + } + + if (!(sysattr->method & SYSFS_METHOD_STORE)) { + dprintf ("Store method not supported for attribute %s\n", + sysattr->path); + errno = EACCES; + return -1; + } + if (sysattr->method & SYSFS_METHOD_SHOW) { + /* + * read attribute again to see if we can get an updated value + */ + if ((sysfs_read_attribute(sysattr))) { + dprintf("Error reading attribute\n"); + return -1; + } + if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0 && + (len == sysattr->len)) { + dprintf("Attr %s already has the requested value %s\n", + sysattr->name, new_value); + return 0; + } + } + /* + * open O_WRONLY since some attributes have no "read" but only + * "write" permission + */ + if ((fd = open(sysattr->path, O_WRONLY)) < 0) { + dprintf("Error reading attribute %s\n", sysattr->path); + return -1; + } + + length = write(fd, new_value, len); + if (length < 0) { + dprintf("Error writing to the attribute %s - invalid value?\n", + sysattr->name); + close(fd); + return -1; + } else if ((unsigned int)length != len) { + dprintf("Could not write %zd bytes to attribute %s\n", + len, sysattr->name); + /* + * since we could not write user supplied number of bytes, + * restore the old value if one available + */ + if (sysattr->method & SYSFS_METHOD_SHOW) { + length = write(fd, sysattr->value, sysattr->len); + close(fd); + return -1; + } + } + + /* + * Validate length that has been copied. Alloc appropriate area + * in sysfs_attribute. Verify first if the attribute supports reading + * (show method). If it does not, do not bother + */ + if (sysattr->method & SYSFS_METHOD_SHOW) { + if (length != sysattr->len) { + sysattr->value = (char *)realloc + (sysattr->value, length); + sysattr->len = length; + safestrcpymax(sysattr->value, new_value, length); + } else { + /*"length" of the new value is same as old one */ + safestrcpymax(sysattr->value, new_value, length); + } + } + + close(fd); + return 0; +} + diff --git a/sysfs_utils.c b/sysfs_utils.c new file mode 100644 index 0000000..a0354a8 --- /dev/null +++ b/sysfs_utils.c @@ -0,0 +1,59 @@ +/* + * sysfs_utils.c + * + * System utility functions for libsysfs + * + * Copyright (C) IBM Corp. 2003-2005 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include "libsysfs.h" +#include "sysfs.h" + +/** + * sysfs_get_name_from_path: returns last name from a "/" delimited path + * @path: path to get name from + * @name: where to put name + * @len: size of name + */ +int sysfs_get_name_from_path(const char *path, char *name, size_t len) +{ + char tmp[SYSFS_PATH_MAX]; + char *n = NULL; + + if (!path || !name || len == 0) { + errno = EINVAL; + return -1; + } + memset(tmp, 0, SYSFS_PATH_MAX); + safestrcpy(tmp, path); + n = strrchr(tmp, '/'); + if (n == NULL) { + errno = EINVAL; + return -1; + } + if (*(n+1) == '\0') { + *n = '\0'; + n = strrchr(tmp, '/'); + if (n == NULL) { + errno = EINVAL; + return -1; + } + } + n++; + safestrcpymax(name, n, len); + return 0; +} |