// read the device major and minor number, using the devpath // return 0 on success, and set *major and *minor // return -ENOMEM on OOM // return -errno on failure to open or read static int vdev_linux_sysfs_read_dev_nums( struct vdev_linux_context* ctx, char const* devpath, unsigned int* major, unsigned int* minor ) { int rc = 0; int fd = 0; ssize_t nr = 0; char devbuf[101]; memset( devbuf, 0, 101 ); char* full_devpath = vdev_linux_sysfs_fullpath( ctx->sysfs_mountpoint, devpath, "dev" ); if( full_devpath == NULL ) { return -ENOMEM; } // open device path fd = open( full_devpath, O_RDONLY ); if( fd < 0 ) { rc = -errno; if( rc != -ENOENT ) { vdev_error("open('%s') rc = %d\n", full_devpath, rc ); } free( full_devpath ); return rc; } nr = vdev_read_uninterrupted( fd, devbuf, 100 ); if( nr < 0 ) { rc = nr; vdev_error("read('%s') rc = %d\n", full_devpath, rc ); free( full_devpath ); close( fd ); return rc; } close( fd ); free( full_devpath ); rc = vdev_linux_sysfs_parse_device_nums( devbuf, major, minor ); if( rc != 0 ) { vdev_error("Failed to parse '%s'\n", devbuf ); rc = -EIO; } return rc; }
// read a whole file into RAM // return 0 on success, and set *file_buf and *file_buf_len // return negative on error int vdev_read_file( char const* path, char** file_buf, size_t* file_buf_len ) { int fd = 0; struct stat sb; char* buf = NULL; int rc = 0; // get size rc = stat( path, &sb ); if( rc != 0 ) { rc = -errno; return rc; } // read the uevent file itself buf = (char*)calloc( sb.st_size, 1 ); if( buf == NULL ) { return -ENOMEM; } fd = open( path, O_RDONLY ); if( fd < 0 ) { rc = -errno; free( buf ); return rc; } rc = vdev_read_uninterrupted( fd, buf, sb.st_size ); if( rc < 0 ) { close( fd ); free( buf ); return rc; } close( fd ); *file_buf = buf; *file_buf_len = rc; return 0; }
// read a sysfs attribute int vdev_sysfs_read_attr( char const* sysfs_device_path, char const* attr_name, char** value, size_t* value_len ) { int rc = 0; int fd = 0; struct stat sb; char attr_path[4097]; sprintf(attr_path, "%s/%s", sysfs_device_path, attr_name ); rc = stat( attr_path, &sb ); if( rc != 0 ) { rc = -errno; return rc; } // regular file? return the contents if( S_ISREG( sb.st_mode ) ) { fd = open( attr_path, O_RDONLY ); if( fd < 0 ) { rc = -errno; fprintf(stderr, "[WARN]: open('%s') errno = %d\n", attr_path, rc ); return rc; } char* ret_value = (char*)calloc( sb.st_size + 1, 1 ); if( ret_value == NULL ) { close( fd ); return -ENOMEM; } rc = vdev_read_uninterrupted( fd, ret_value, sb.st_size ); if( rc < 0 ) { free( ret_value ); close( fd ); return rc; } close( fd ); *value = ret_value; *value_len = sb.st_size; return 0; } // symlink? return the actual link else if( S_ISLNK( sb.st_mode ) ) { char* ret_value = (char*)calloc( sb.st_size + 1, 1 ); if( ret_value == NULL ) { return -ENOMEM; } rc = readlink( attr_path, ret_value, sb.st_size ); if( rc < 0 ) { rc = -errno; fprintf(stderr, "[WARN]: readlink('%s') errno = %d\n", attr_path, rc ); free( ret_value ); return rc; } *value = ret_value; *value_len = sb.st_size + 1; return 0; } // not sure what to do here else { return -EINVAL; } }