/** * sysfs_read_attribute_value: given path to attribute, return its value. * values can be up to a pagesize, if buffer is smaller the value will * be truncated. * @attrpath: sysfs path to attribute * @value: buffer to put value * @vsize: size of value buffer * returns 0 with success and -1 with error. */ int sysfs_read_attribute_value(const char *attrpath, char *value, size_t vsize) { struct sysfs_attribute *attr = NULL; size_t length = 0; if (attrpath == NULL || value == NULL || vsize == 0) { errno = EINVAL; return -1; } attr = sysfs_open_attribute(attrpath); if (attr == NULL) { dprintf("Invalid attribute path %s\n", attrpath); errno = EINVAL; return -1; } if((sysfs_read_attribute(attr)) != 0 || attr->value == NULL) { dprintf("Error reading from attribute %s\n", attrpath); sysfs_close_attribute(attr); return -1; } length = strlen(attr->value); if (length > vsize) dprintf("Value length %d is larger than supplied buffer %d\n", length, vsize); safestrcpymax(value, attr->value, vsize); sysfs_close_attribute(attr); return 0; }
static int br_set(const char *bridge, const char *name, unsigned long value, unsigned long oldcode) { int ret = -1; #ifdef HAVE_LIBSYSFS struct sysfs_class_device *dev; dev = sysfs_get_class_device(br_class_net, bridge); if (dev) { struct sysfs_attribute *attr; char buf[32]; char path[SYSFS_PATH_MAX]; snprintf(buf, sizeof(buf), "%ld\n", value); snprintf(path, SYSFS_PATH_MAX, "%s/bridge/%s", dev->path, name); attr = sysfs_open_attribute(path); if (attr) { ret = sysfs_write_attribute(attr, buf, strlen(buf)); sysfs_close_attribute(attr); } sysfs_close_class_device(dev); } else #endif { struct ifreq ifr; unsigned long args[4] = { oldcode, value, 0, 0 }; strncpy(ifr.ifr_name, bridge, IFNAMSIZ); ifr.ifr_data = (char *)&args; ret = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); } return ret < 0 ? errno : 0; }
// added by zl 2011-2-12 int read_attr_string(struct sysfs_device *dev, char * string, const char * name) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; int ret; int len = STRING_MAXLEN; string[0] = 0; snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, name); attr = sysfs_open_attribute(attrpath); if(!attr) { err("open attr"); return 0; } ret = sysfs_read_attribute(attr); if(ret < 0) { err("read attr"); goto err; } len = (len < attr->len? len: attr->len); if(len > 0) { memcpy(string, attr->value, len); } err: sysfs_close_attribute(attr); return 0; }
int read_attr_value(struct sysfs_device *dev, const char *name, const char *format) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; int num = 0; int ret; snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, name); attr = sysfs_open_attribute(attrpath); if(!attr) { err("open attr %s", attrpath); return 0; } ret = sysfs_read_attribute(attr); if(ret < 0) { err("read attr"); goto err; } ret = sscanf(attr->value, format, &num); if(ret < 1) { err("sscanf"); goto err; } err: sysfs_close_attribute(attr); return num; }
/** * 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 == NULL) { errno = EINVAL; return NULL; } sysattr = alloc_attribute(); if (sysattr == NULL) { 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; }
/** * add_attribute: open and add attribute at path to given directory * @dev: device whose attribute is to be added * @path: path to attribute * returns pointer to attr added with success and NULL with error. */ static struct sysfs_attribute *add_attribute(void *dev, const char *path) { struct sysfs_attribute *attr; attr = sysfs_open_attribute(path); if (!attr) { dprintf("Error opening attribute %s\n", path); return NULL; } if (attr->method & SYSFS_METHOD_SHOW) { if (sysfs_read_attribute(attr)) { dprintf("Error reading attribute %s\n", path); sysfs_close_attribute(attr); return NULL; } } if (!((struct sysfs_device *)dev)->attrlist) { ((struct sysfs_device *)dev)->attrlist = dlist_new_with_delete (sizeof(struct sysfs_attribute), sysfs_del_attribute); } dlist_unshift_sorted(((struct sysfs_device *)dev)->attrlist, attr, sort_list); return attr; }
int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; char sockfd_buff[30]; int ret; if (edev->status != SDEV_ST_AVAILABLE) { info("device not available, %s", edev->udev.busid); switch( edev->status ) { case SDEV_ST_ERROR: info(" status SDEV_ST_ERROR"); break; case SDEV_ST_USED: info(" status SDEV_ST_USED"); break; default: info(" status unknown: 0x%x", edev->status); } return -1; } /* only the first interface is true */ snprintf(attrpath, sizeof(attrpath), "%s/%s:%d.%d/%s", edev->udev.path, edev->udev.busid, edev->udev.bConfigurationValue, 0, "usbip_sockfd"); attr = sysfs_open_attribute(attrpath); if (!attr) { err("open %s", attrpath); return -1; } snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd); dbg("write: %s", sockfd_buff); ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff)); if (ret < 0) { err("write sockfd %s to %s", sockfd_buff, attrpath); goto err_write_sockfd; } info("connect %s", edev->udev.busid); err_write_sockfd: sysfs_close_attribute(attr); return ret; }
int modify_match_busid(char *busid, int add) { char bus_type[] = "usb"; char attr_name[] = "match_busid"; char buff[SYSFS_BUS_ID_SIZE + 4]; char sysfs_mntpath[SYSFS_PATH_MAX]; char match_busid_attr_path[SYSFS_PATH_MAX]; struct sysfs_attribute *match_busid_attr; int rc, ret = 0; if (strnlen(busid, SYSFS_BUS_ID_SIZE) > SYSFS_BUS_ID_SIZE - 1) { dbg("busid is too long"); return -1; } rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); if (rc < 0) { err("sysfs must be mounted: %s", strerror(errno)); return -1; } snprintf(match_busid_attr_path, sizeof(match_busid_attr_path), "%s/%s/%s/%s/%s/%s", sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name); match_busid_attr = sysfs_open_attribute(match_busid_attr_path); if (!match_busid_attr) { dbg("problem getting match_busid attribute: %s", strerror(errno)); return -1; } if (add) snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s", busid); else snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "del %s", busid); dbg("write \"%s\" to %s", buff, match_busid_attr->path); rc = sysfs_write_attribute(match_busid_attr, buff, sizeof(buff)); if (rc < 0) { dbg("failed to write match_busid: %s", strerror(errno)); ret = -1; } sysfs_close_attribute(match_busid_attr); return ret; }
int read_attr_speed(struct sysfs_device *dev) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; char speed[100]; int ret; snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, "speed"); attr = sysfs_open_attribute(attrpath); if(!attr) { err("open attr"); return 0; } ret = sysfs_read_attribute(attr); if(ret < 0) { err("read attr"); goto err; } ret = sscanf(attr->value, "%s\n", speed); if(ret < 1) { err("sscanf"); goto err; } err: sysfs_close_attribute(attr); for(int i=0; speed_strings[i].speed != NULL; i++) { if(!strcmp(speed, speed_strings[i].speed)) return speed_strings[i].num; } return USB_SPEED_UNKNOWN; }
/* only the first interface value is true! */ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) { char attrpath[SYSFS_PATH_MAX]; struct sysfs_attribute *attr; int value = 0; int rc; struct stat s; int retries = SYSFS_OPEN_RETRIES; /* This access is racy! * * Just after detach, our driver removes the sysfs * files and recreates them. * * We may try and fail to open the usbip_status of * an exported device in the (short) window where * it has been removed and not yet recreated. * * This is a bug in the interface. Nothing we can do * except work around it here by polling for the sysfs * usbip_status to reappear. */ snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status", udev->path, udev->busid, udev->bConfigurationValue, 0); while (retries > 0) { if (stat(attrpath, &s) == 0) break; if (errno != ENOENT) { dbg("stat failed: %s", attrpath); return -1; } usleep(10000); /* 10ms */ retries--; } if (retries == 0) dbg("usbip_status not ready after %d retries", SYSFS_OPEN_RETRIES); else if (retries < SYSFS_OPEN_RETRIES) dbg("warning: usbip_status ready after %d retries", SYSFS_OPEN_RETRIES - retries); attr = sysfs_open_attribute(attrpath); if (!attr) { dbg("sysfs_open_attribute failed: %s", attrpath); return -1; } rc = sysfs_read_attribute(attr); if (rc) { dbg("sysfs_read_attribute failed: %s", attrpath); sysfs_close_attribute(attr); return -1; } value = atoi(attr->value); sysfs_close_attribute(attr); return value; }
int main(int argc, char *argv[]) { struct sysfs_class *sf_class; struct sysfs_device *sf_dev; struct sysfs_class_device *sf_cdev; struct dlist *sf_cdev_list = NULL; char buffer[64]; int port; struct sysfs_attribute *sf_attr; struct sysfs_attribute *sf_part; struct dlist *sf_part_list = NULL; sf_class = sysfs_open_class("block"); if (sf_class != NULL) { sf_cdev_list = sysfs_get_class_devices(sf_class); if (sf_cdev_list != NULL) { dlist_for_each_data(sf_cdev_list, sf_cdev, struct sysfs_class_device) { sf_dev = sysfs_get_classdev_device(sf_cdev); if (sf_dev != NULL) { port = *(strstr(sf_dev->path, "/usb1/") + 8) - 48; if ((port != 1) && (port != 2)) { port = -1; } printf("%s, USB port %d\n", sf_cdev->name, port); /* size */ snprintf(buffer, 64, "%s/size", sf_cdev->path); sf_attr = sysfs_open_attribute(buffer); if (sf_attr != NULL) { if (sysfs_read_attribute(sf_attr) == 0) { printf("size: %s", sf_attr->value); } sysfs_close_attribute(sf_attr); } /* vendor */ snprintf(buffer, 64, "%s/device/vendor", sf_cdev->path); sf_attr = sysfs_open_attribute(buffer); if (sf_attr != NULL) { if (sysfs_read_attribute(sf_attr) == 0) { printf("vendor: %s", sf_attr->value); } sysfs_close_attribute(sf_attr); } /* model */ snprintf(buffer, 64, "%s/device/model", sf_cdev->path); sf_attr = sysfs_open_attribute(buffer); if (sf_attr != NULL) { if (sysfs_read_attribute(sf_attr) == 0) { printf("model: %s", sf_attr->value); } sysfs_close_attribute(sf_attr); } sf_part_list = sysfs_open_directory_list(sf_cdev->path); if (sf_part_list != NULL) { dlist_for_each_data(sf_part_list, sf_part, struct sysfs_attribute) { if (strncmp("queue", (char *) sf_part, 5) != 0) { snprintf(buffer, 64, "%s/%s/size", sf_cdev->path, sf_part); sf_attr = sysfs_open_attribute(buffer); if (sf_attr != NULL) { if (sysfs_read_attribute(sf_attr) == 0) { printf("%s - size: %s", sf_part, sf_attr->value); } sysfs_close_attribute(sf_attr); } } } }
/** * sysfs_del_attribute: routine for dlist integration */ static void sysfs_del_attribute(void *attr) { sysfs_close_attribute((struct sysfs_attribute *)attr); }
/* call at unbound state */ static int bind_usbip(char *busid) { char bus_type[] = "usb"; char attr_name[] = "bind"; char sysfs_mntpath[SYSFS_PATH_MAX]; char bind_attr_path[SYSFS_PATH_MAX]; char intf_busid[SYSFS_BUS_ID_SIZE]; struct sysfs_device *busid_dev; struct sysfs_attribute *bind_attr; struct sysfs_attribute *bConfValue; struct sysfs_attribute *bNumIntfs; int i, failed = 0; int rc, ret = -1; rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); if (rc < 0) { err("sysfs must be mounted: %s", strerror(errno)); return -1; } snprintf(bind_attr_path, sizeof(bind_attr_path), "%s/%s/%s/%s/%s/%s", sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name); bind_attr = sysfs_open_attribute(bind_attr_path); if (!bind_attr) { dbg("problem getting bind attribute: %s", strerror(errno)); return -1; } busid_dev = sysfs_open_device(bus_type, busid); if (!busid_dev) { dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); goto err_close_bind_attr; } bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue"); bNumIntfs = sysfs_get_device_attr(busid_dev, "bNumInterfaces"); if (!bConfValue || !bNumIntfs) { dbg("problem getting device attributes: %s", strerror(errno)); goto err_close_busid_dev; } for (i = 0; i < atoi(bNumIntfs->value); i++) { snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid, bConfValue->value, i); rc = sysfs_write_attribute(bind_attr, intf_busid, SYSFS_BUS_ID_SIZE); if (rc < 0) { dbg("bind driver at %s failed", intf_busid); failed = 1; } } if (!failed) ret = 0; err_close_busid_dev: sysfs_close_device(busid_dev); err_close_bind_attr: sysfs_close_attribute(bind_attr); return ret; }