/** * sysfs_get_class_device: get specific class device using the device's id * @cls: sysfs_class to find the device on * @name: name of the class device to look for * * Returns sysfs_class_device * on success and NULL on failure */ struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *cls, const char *name) { char path[SYSFS_PATH_MAX]; struct sysfs_class_device *cdev = NULL; if (!cls || !name) { errno = EINVAL; return NULL; } if (cls->devices) { cdev = (struct sysfs_class_device *)dlist_find_custom (cls->devices, (void *)name, cdev_name_equal); if (cdev) return cdev; } safestrcpy(path, cls->path); safestrcat(path, "/"); safestrcat(path, name); cdev = sysfs_open_class_device_path(path); if (!cdev) { dprintf("Error opening class device at %s\n", path); return NULL; } if (!cls->devices) cls->devices = dlist_new_with_delete (sizeof(struct sysfs_class_device), sysfs_close_cls_dev); dlist_unshift_sorted(cls->devices, cdev, sort_list); return cdev; }
/** * Add class devices to list */ static void add_cdevs_to_classlist(struct sysfs_class *cls, struct dlist *list) { char path[SYSFS_PATH_MAX], *cdev_name; struct sysfs_class_device *cdev = NULL; if (cls == NULL || list == NULL) return; dlist_for_each_data(list, cdev_name, char) { if (cls->devices) { cdev = (struct sysfs_class_device *) dlist_find_custom(cls->devices, (void *)cdev_name, cdev_name_equal); if (cdev) continue; } safestrcpy(path, cls->path); safestrcat(path, "/"); safestrcat(path, cdev_name); cdev = sysfs_open_class_device_path(path); if (cdev) { if (!cls->devices) cls->devices = dlist_new_with_delete (sizeof(struct sysfs_class_device), sysfs_close_cls_dev); dlist_unshift_sorted(cls->devices, cdev, sort_list); } } }
/** * read_dir_subdirs: grabs subdirs in a specific directory * @sysdir: sysfs directory to read * returns list of directory names with success and NULL with error. */ struct sysfs_device *sysfs_read_dir_subdirs(const char *path) { DIR *dir = NULL; struct dirent *dirent = NULL; char file_path[SYSFS_PATH_MAX]; struct sysfs_device *dev = NULL; if (!path) { errno = EINVAL; return NULL; } dev = sysfs_open_device_path(path); dir = opendir(path); if (!dir) { dprintf("Error opening directory %s\n", path); return NULL; } while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); if (!sysfs_path_is_dir(file_path)) add_subdirectory(dev, file_path); } closedir(dir); return dev; }
/** * sysfs_get_bus_driver: Get specific driver on bus using driver name * @bus: bus to find driver on * @drvname: name of driver * returns struct sysfs_driver reference or NULL if not found. */ struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, const char *drvname) { struct sysfs_driver *drv; char drvpath[SYSFS_PATH_MAX]; if (!bus || !drvname) { errno = EINVAL; return NULL; } if (bus->drivers) { drv = (struct sysfs_driver *)dlist_find_custom (bus->drivers, (void *)drvname, name_equal); if (drv) return drv; } safestrcpy(drvpath, bus->path); safestrcat(drvpath, "/"); safestrcat(drvpath, SYSFS_DRIVERS_NAME); safestrcat(drvpath, "/"); safestrcat(drvpath, drvname); drv = sysfs_open_driver_path(drvpath); if (!drv) { dprintf("Error opening driver at %s\n", drvpath); return NULL; } if (!bus->drivers) bus->drivers = dlist_new_with_delete (sizeof(struct sysfs_driver), sysfs_close_drv); dlist_unshift_sorted(bus->drivers, drv, sort_list); return drv; }
/** * sysfs_get_bus_devices: gets all devices for bus * @bus: bus to get devices for * returns dlist of devices with success and NULL with failure */ struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus) { struct sysfs_device *dev; struct dlist *linklist; char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; char target[SYSFS_PATH_MAX]; char *curlink; if (!bus) { errno = EINVAL; return NULL; } memset(path, 0, SYSFS_PATH_MAX); safestrcpy(path, bus->path); safestrcat(path, "/"); safestrcat(path, SYSFS_DEVICES_NAME); linklist = read_dir_links(path); if (linklist) { dlist_for_each_data(linklist, curlink, char) { if (bus->devices) { dev = (struct sysfs_device *) dlist_find_custom(bus->devices, (void *)curlink, name_equal); if (dev) continue; } safestrcpy(devpath, path); safestrcat(devpath, "/"); safestrcat(devpath, curlink); if (sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) { dprintf("Error getting link - %s\n", devpath); continue; } dev = sysfs_open_device_path(target); if (!dev) { dprintf("Error opening device at %s\n", target); continue; } if (!bus->devices) bus->devices = dlist_new_with_delete (sizeof(struct sysfs_device), sysfs_close_dev); dlist_unshift_sorted(bus->devices, dev, sort_list); } sysfs_close_list(linklist); } return (bus->devices); }
/** * sysfs_open_class: opens specific class and all its devices on system * returns sysfs_class structure with success or NULL with error. */ struct sysfs_class *sysfs_open_class(const char *name) { struct sysfs_class *cls = NULL; char *c, classpath[SYSFS_PATH_MAX]; if (!name) { errno = EINVAL; return NULL; } memset(classpath, 0, SYSFS_PATH_MAX); if ((sysfs_get_mnt_path(classpath, SYSFS_PATH_MAX)) != 0) { dprintf("Sysfs not supported on this system\n"); return NULL; } safestrcat(classpath, "/"); if (strcmp(name, SYSFS_BLOCK_NAME) == 0) { safestrcat(classpath, SYSFS_BLOCK_NAME); if (!sysfs_path_is_dir(classpath)) goto done; c = strrchr(classpath, '/'); *(c+1) = '\0'; } safestrcat(classpath, SYSFS_CLASS_NAME); safestrcat(classpath, "/"); safestrcat(classpath, name); done: if (sysfs_path_is_dir(classpath)) { dprintf("Class %s not found on the system\n", name); return NULL; } cls = alloc_class(); if (cls == NULL) { dprintf("calloc failed\n"); return NULL; } safestrcpy(cls->name, name); safestrcpy(cls->path, classpath); if ((sysfs_remove_trailing_slash(cls->path)) != 0) { dprintf("Invalid path to class device %s\n", cls->path); sysfs_close_class(cls); return NULL; } return cls; }
/** * sysfs_get_bus_drivers: gets all drivers for bus * @bus: bus to get devices for * returns dlist of devices with success and NULL with failure */ struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus) { struct sysfs_driver *drv; struct dlist *dirlist; char path[SYSFS_PATH_MAX], drvpath[SYSFS_PATH_MAX]; char *curdir; if (!bus) { errno = EINVAL; return NULL; } memset(path, 0, SYSFS_PATH_MAX); safestrcpy(path, bus->path); safestrcat(path, "/"); safestrcat(path, SYSFS_DRIVERS_NAME); dirlist = read_dir_subdirs(path); if (dirlist) { dlist_for_each_data(dirlist, curdir, char) { if (bus->drivers) { drv = (struct sysfs_driver *) dlist_find_custom(bus->drivers, (void *)curdir, name_equal); if (drv) continue; } safestrcpy(drvpath, path); safestrcat(drvpath, "/"); safestrcat(drvpath, curdir); drv = sysfs_open_driver_path(drvpath); if (!drv) { dprintf("Error opening driver at %s\n", drvpath); continue; } if (!bus->drivers) bus->drivers = dlist_new_with_delete (sizeof(struct sysfs_driver), sysfs_close_drv); dlist_unshift_sorted(bus->drivers, drv, sort_list); } sysfs_close_list(dirlist); } return (bus->drivers); }
/** * get_dev_attributes_list: build a list of attributes for the given device * @dev: devices whose attributes list is required * returns dlist of attributes on success and NULL on failure */ struct dlist *get_dev_attributes_list(void *dev) { DIR *dir = NULL; struct dirent *dirent = NULL; struct sysfs_attribute *attr = NULL; char file_path[SYSFS_PATH_MAX], path[SYSFS_PATH_MAX]; if (!dev) { errno = EINVAL; return NULL; } memset(path, 0, SYSFS_PATH_MAX); safestrcpy(path, ((struct sysfs_device *)dev)->path); dir = opendir(path); if (!dir) { dprintf("Error opening directory %s\n", path); return NULL; } while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); if (!sysfs_path_is_file(file_path)) { if (((struct sysfs_device *)dev)->attrlist) { /* check if attr is already in the list */ attr = (struct sysfs_attribute *) dlist_find_custom ((((struct sysfs_device *)dev)->attrlist), (void *)dirent->d_name, attr_name_equal); if (attr) continue; else add_attribute(dev, file_path); } else attr = add_attribute(dev, file_path); } } closedir(dir); return ((struct sysfs_device *)dev)->attrlist; }
/** * read_dir_subdirs: grabs subdirs in a specific directory * @sysdir: sysfs directory to read * returns list of directory names with success and NULL with error. */ struct dlist *read_dir_subdirs(const char *path) { DIR *dir = NULL; struct dirent *dirent = NULL; char file_path[SYSFS_PATH_MAX], *dir_name; struct dlist *dirlist = NULL; if (!path) { errno = EINVAL; return NULL; } dir = opendir(path); if (!dir) { dprintf("Error opening directory %s\n", path); return NULL; } while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); if (!sysfs_path_is_dir(file_path)) { if (!dirlist) { dirlist = dlist_new_with_delete (SYSFS_NAME_LEN, sysfs_del_name); if (!dirlist) { dprintf("Error creating list\n"); return NULL; } } dir_name = (char *)calloc(1, SYSFS_NAME_LEN); safestrcpymax(dir_name, dirent->d_name, SYSFS_NAME_LEN); dlist_unshift_sorted(dirlist, dir_name, sort_char); } } closedir(dir); return dirlist; }
/** * sysfs_get_driver_module: gets the module being used by this driver * @drv: sysfs_driver whose "module" is needed * Returns sysfs_module on success and NULL on failure */ struct sysfs_module *sysfs_get_driver_module(struct sysfs_driver *drv) { char path[SYSFS_PATH_MAX], mod_path[SYSFS_PATH_MAX]; if (!drv) { errno = EINVAL; return NULL; } memset(path, 0, SYSFS_PATH_MAX); safestrcpy(path, drv->path); safestrcat(path, "/"); safestrcat(path, SYSFS_MODULE_NAME); if (!sysfs_path_is_link(path)) { memset(mod_path, 0, SYSFS_PATH_MAX); if (!sysfs_get_link(path, mod_path, SYSFS_PATH_MAX)) drv->module = sysfs_open_module_path(mod_path); } return drv->module; }
/* ###### Get textual description ######################################## */ void poolHandleGetDescription(const struct PoolHandle* poolHandle, char* buffer, const size_t bufferSize) { char result[8]; size_t i; buffer[0] = 0x00; for(i = 0;i < ((poolHandle->Size <= MAX_POOLHANDLESIZE) ? poolHandle->Size : MAX_POOLHANDLESIZE);i++) { if(!iscntrl(poolHandle->Handle[i])) { result[0] = poolHandle->Handle[i]; result[1] = 0x00; safestrcat(buffer, result, bufferSize); } else { snprintf((char*)&result, sizeof(result), "{%02x}", poolHandle->Handle[i]); safestrcat(buffer, result, bufferSize); } } }
/** * get_attributes_list: build a list of attributes for the given path * @path: grab attributes at the given path * returns dlist of attributes on success and NULL on failure */ struct dlist *get_attributes_list(struct dlist *alist, const char *path) { DIR *dir = NULL; struct dirent *dirent = NULL; char file_path[SYSFS_PATH_MAX]; if (!path) { errno = EINVAL; return NULL; } dir = opendir(path); if (!dir) { dprintf("Error opening directory %s\n", path); return NULL; } while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); if (!sysfs_path_is_file(file_path)) { if (!alist) { alist = dlist_new_with_delete (sizeof(struct sysfs_attribute), sysfs_del_attribute); if (!alist) { dprintf("Error creating list\n"); return NULL; } } add_attribute_to_list(alist, file_path); } } closedir(dir); return alist; }
/** * sysfs_get_bus_device: Get specific device on bus using device's id * @bus: bus to find device on * @id: bus_id for device * returns struct sysfs_device reference or NULL if not found. */ struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, const char *id) { struct sysfs_device *dev = NULL; char devpath[SYSFS_PATH_MAX], target[SYSFS_PATH_MAX]; if (!bus || !id) { errno = EINVAL; return NULL; } if (bus->devices) { dev = (struct sysfs_device *)dlist_find_custom (bus->devices, (void *)id, name_equal); if (dev) return dev; } safestrcpy(devpath, bus->path); safestrcat(devpath, "/"); safestrcat(devpath, SYSFS_DEVICES_NAME); safestrcat(devpath, "/"); safestrcat(devpath, id); if (sysfs_path_is_link(devpath)) { dprintf("No such device %s on bus %s?\n", id, bus->name); return NULL; } if (!sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) { dev = sysfs_open_device_path(target); if (!dev) { dprintf("Error opening device at %s\n", target); return NULL; } if (!bus->devices) bus->devices = dlist_new_with_delete (sizeof(struct sysfs_device), sysfs_close_dev); dlist_unshift_sorted(bus->devices, dev, sort_list); } return dev; }
/** * sysfs_open_bus: opens specific bus and all its devices on system * returns sysfs_bus structure with success or NULL with error. */ struct sysfs_bus *sysfs_open_bus(const char *name) { struct sysfs_bus *bus; char buspath[SYSFS_PATH_MAX]; if (!name) { errno = EINVAL; return NULL; } memset(buspath, 0, SYSFS_PATH_MAX); if (sysfs_get_mnt_path(buspath, SYSFS_PATH_MAX)) { dprintf("Sysfs not supported on this system\n"); return NULL; } safestrcat(buspath, "/"); safestrcat(buspath, SYSFS_BUS_NAME); safestrcat(buspath, "/"); safestrcat(buspath, name); if (sysfs_path_is_dir(buspath)) { dprintf("Invalid path to bus: %s\n", buspath); return NULL; } bus = alloc_bus(); if (!bus) { dprintf("calloc failed\n"); return NULL; } safestrcpy(bus->name, name); safestrcpy(bus->path, buspath); if (sysfs_remove_trailing_slash(bus->path)) { dprintf("Incorrect path to bus %s\n", bus->path); sysfs_close_bus(bus); return NULL; } return bus; }
/** * sysfs_get_classdev_device: gets the sysfs_device associated with the * given sysfs_class_device * @clsdev: class device whose associated sysfs_device is needed * returns struct sysfs_device * on success or NULL on error */ struct sysfs_device *sysfs_get_classdev_device (struct sysfs_class_device *clsdev) { char linkpath[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; if (!clsdev) { errno = EINVAL; return NULL; } if (clsdev->sysdevice) return clsdev->sysdevice; memset(linkpath, 0, SYSFS_PATH_MAX); safestrcpy(linkpath, clsdev->path); safestrcat(linkpath, "/device"); if (!sysfs_path_is_link(linkpath)) { memset(devpath, 0, SYSFS_PATH_MAX); if (!sysfs_get_link(linkpath, devpath, SYSFS_PATH_MAX)) clsdev->sysdevice = sysfs_open_device_path(devpath); } return clsdev->sysdevice; }