示例#1
0
文件: common.c 项目: bjb/vdev
// find a field in the uevent buffer, using vdev_read_file and vdev_sysfs_uevent_get_key
// return 0 on success, and set *value and *value_len 
// return negative on error
int vdev_sysfs_uevent_read_key( char const* sysfs_device_path, char const* uevent_key, char** uevent_value, size_t* uevent_value_len ) {
   
   int rc = 0;
   
   char* uevent_buf = NULL;
   size_t uevent_len = 0;
   
   char* uevent_path = (char*)calloc( strlen(sysfs_device_path) + strlen("/uevent") + 1, 1 );
   if( uevent_path == NULL ) {
      
      return -ENOMEM;
   }
   
   sprintf( uevent_path, "%s/uevent", sysfs_device_path );
   
   // get uevent 
   rc = vdev_read_file( uevent_path, &uevent_buf, &uevent_len );
   if( rc < 0 ) {
      
      if( DEBUG ) {
         fprintf(stderr, "[WARN]: vdev_read_file('%s') rc = %d\n", uevent_path, rc );
      }
      return rc;
   }
   
   // get devtype 
   rc = vdev_sysfs_uevent_get_key( uevent_buf, uevent_len, uevent_key, uevent_value, uevent_value_len );
   
   free( uevent_buf );
   free( uevent_path );
   
   return rc;
}
示例#2
0
文件: common.c 项目: bjb/vdev
// walk up a sysfs device path to find the ancestor device with the given subsystem and devtype
// if devtype_name is NULL, match any devtype (only match the subsystem)
// return 0 on success
// return -ENOMEM on OOM 
// return -ENOENT if a subsystem or uevent was not found, when one was expected
int vdev_sysfs_get_parent_with_subsystem_devtype( char const* sysfs_device_path, char const* subsystem_name, char const* devtype_name, char** devpath, size_t* devpath_len ) {
   
   char cur_dir[4097];
   char subsystem_path[4097];
   char subsystem_link[4097];
   char uevent_path[4097];
   
   memset( subsystem_path, 0, 4097 );
   memset( subsystem_link, 0, 4097 );
   
   char* tmp = NULL;
   int rc = 0;
   char* uevent_buf = NULL;
   size_t uevent_len = 0;
   char* devtype = NULL;
   size_t devtype_len = 0;
   char* parent_device = NULL;
   size_t parent_device_len = 0;
   
   strcpy( cur_dir, sysfs_device_path );
   
   while( 1 ) {
      
      // get parent device 
      rc = vdev_sysfs_get_parent_device( cur_dir, &parent_device, &parent_device_len );
      if( rc != 0 ) {
         break;
      }
      
      // subsystem?
      sprintf( subsystem_path, "%s/subsystem", parent_device );
      
      memset( subsystem_link, 0, 4096 );
      
      rc = readlink( subsystem_path, subsystem_link, 4096 );
      if( rc < 0 ) {
         
         rc = -errno;
         if( rc != -ENOENT ) {
            fprintf(stderr, "[WARN]: readlink('%s') errno = %d\n", subsystem_path, rc );
         }
         
         free( parent_device );
         parent_device = NULL;
         return rc;
      }
      
      // get subsystem name...
      tmp = rindex( subsystem_link, '/' );
      
      if( tmp != NULL && strcmp( tmp + 1, subsystem_name ) != 0 ) {
         
         // subsystem does not match
         // crawl up to the parent
         strcpy( cur_dir, parent_device );
         
         free( parent_device );
         parent_device = NULL;
         continue;
      }
      
      // subsystem matches...
      *tmp = 0;
      
      if( devtype_name != NULL ) {
         
         // get uevent
         // get DEVTYPE from uevent 
         // make uevent path 
         sprintf( uevent_path, "%s/uevent", parent_device );
         
         // get uevent 
         rc = vdev_read_file( uevent_path, &uevent_buf, &uevent_len );
         if( rc < 0 ) {
            
            fprintf(stderr, "[WARN]: vdev_read_file('%s') rc = %d\n", uevent_path, rc );
            
            free( parent_device );
            parent_device = NULL;
            return rc;
         }
         
         // get devtype 
         rc = vdev_sysfs_uevent_get_key( uevent_buf, uevent_len, "DEVTYPE", &devtype, &devtype_len );
         free( uevent_buf );
         
         if( rc != 0 ) {
            
            if( rc == -ENOENT ) {
               
               // not found 
               // next parent 
               strcpy( cur_dir, parent_device );
               
               free( parent_device );
               parent_device = NULL;
               
               continue;
            }
            else {
               
               free( parent_device );
               parent_device = NULL;
               
               return rc;
            }
         }
         
         // matches?
         if( strcmp( devtype, devtype_name ) == 0 ) {
            
            free( devtype );
            
            // this is the path to the device 
            *devpath = parent_device;
            *devpath_len = strlen( parent_device );
            
            // found!
            rc = 0;
            break;
         }
         else {
            // no match.
            // next device 
            free( devtype );
            
            strcpy( cur_dir, parent_device );
            
            free( parent_device );
            parent_device = NULL;
            continue;
         }
      }
      else {
         
         // match only on subsystem 
         *devpath = parent_device;
         *devpath_len = strlen(parent_device);
         
         rc = 0;
         break;
      }
   }
   
   return rc;
}
示例#3
0
文件: linux.c 项目: 8l/vdev
// get a uevent from a uevent file 
// replace newlines with '\0', making the uevent look like it came from the netlink socket
// (i.e. so it can be parsed by vdev_linux_parse_request)
// return 0 on success
// return -ENOMEM on OOM
// return -errno on failure to stat or read
static int vdev_linux_sysfs_read_uevent( char const* fp_uevent, char** ret_uevent_buf, size_t* ret_uevent_len ) {
   
   int rc = 0;
   struct stat sb;
   char* uevent_buf = NULL;
   size_t uevent_buf_len = 0;
   size_t uevent_len = 0;
   
   // get uevent size  
   rc = stat( fp_uevent, &sb );
   if( rc != 0 ) {
      
      rc = -errno;
      
      vdev_error("stat('%s') rc = %d\n", fp_uevent, rc );
      
      return rc;
   }
   else {
      
      uevent_buf_len = sb.st_size;
   }
   
   // read the uevent
   if( fp_uevent != NULL ) {
      
      uevent_buf = VDEV_CALLOC( char, uevent_buf_len );
      if( uevent_buf == NULL ) {
         
         return -ENOMEM;
      }
      
      rc = vdev_read_file( fp_uevent, uevent_buf, uevent_buf_len );
      if( rc != 0 ) {
         
         // failed in this 
         vdev_error("vdev_read_file('%s') rc = %d\n", fp_uevent, rc );
         free( uevent_buf );
      }
      else {
         
         for( unsigned int i = 0; i < uevent_buf_len; i++ ) {
            
            if( uevent_buf[i] == '\n' ) {
               
               uevent_buf[i] = '\0';
            }
         }
         
         // NOTE: the stat size is an upper-bound.  Find the exact number of bytes.
         for( uevent_len = 0; uevent_len < uevent_buf_len; ) {
            
            if( *(uevent_buf + uevent_len) == '\0' ) {
               break;
            }
            
            uevent_len += strlen( uevent_buf + uevent_len ) + 1;
         }
          
         *ret_uevent_buf = uevent_buf;
         *ret_uevent_len = uevent_len;
      }
   }