2018-06-19 21:43:31 +03:00
# include "configure.h"
2018-04-30 18:16:58 +03:00
# include "target.h"
// For DM_ARRAY_SIZE!
2018-06-08 14:31:45 +03:00
# include "device_mapper/all.h"
2018-04-30 18:16:58 +03:00
2018-05-02 13:15:35 +03:00
# include <ctype.h>
2018-04-30 18:16:58 +03:00
# include <stdlib.h>
2018-05-02 13:15:35 +03:00
# include <string.h>
2018-04-30 18:16:58 +03:00
//----------------------------------------------------------------
static bool _tok_eq ( const char * b , const char * e , const char * str )
{
while ( b ! = e ) {
if ( ! * str | | * b ! = * str )
2018-06-27 17:18:53 +03:00
return false ;
2018-04-30 18:16:58 +03:00
2018-06-27 17:18:53 +03:00
b + + ;
str + + ;
2018-04-30 18:16:58 +03:00
}
return ! * str ;
}
2018-05-02 13:15:35 +03:00
static bool _parse_operating_mode ( const char * b , const char * e , void * context )
2018-04-30 18:16:58 +03:00
{
2018-06-27 17:18:53 +03:00
static const struct {
const char str [ 12 ] ;
enum vdo_operating_mode mode ;
2018-04-30 18:16:58 +03:00
} _table [ ] = {
2018-06-27 17:18:53 +03:00
{ " recovering " , VDO_MODE_RECOVERING } ,
{ " read-only " , VDO_MODE_READ_ONLY } ,
{ " normal " , VDO_MODE_NORMAL }
2018-04-30 18:16:58 +03:00
} ;
2018-06-27 17:18:53 +03:00
enum vdo_operating_mode * r = context ;
2018-04-30 18:16:58 +03:00
unsigned i ;
for ( i = 0 ; i < DM_ARRAY_SIZE ( _table ) ; i + + ) {
2018-06-27 17:18:53 +03:00
if ( _tok_eq ( b , e , _table [ i ] . str ) ) {
* r = _table [ i ] . mode ;
return true ;
}
2018-04-30 18:16:58 +03:00
}
return false ;
}
2018-05-02 13:15:35 +03:00
static bool _parse_compression_state ( const char * b , const char * e , void * context )
2018-04-30 18:16:58 +03:00
{
2018-06-27 17:18:53 +03:00
static const struct {
const char str [ 8 ] ;
enum vdo_compression_state state ;
2018-04-30 18:16:58 +03:00
} _table [ ] = {
2018-06-27 17:18:53 +03:00
{ " online " , VDO_COMPRESSION_ONLINE } ,
{ " offline " , VDO_COMPRESSION_OFFLINE }
2018-04-30 18:16:58 +03:00
} ;
2018-06-27 17:18:53 +03:00
enum vdo_compression_state * r = context ;
2018-04-30 18:16:58 +03:00
unsigned i ;
for ( i = 0 ; i < DM_ARRAY_SIZE ( _table ) ; i + + ) {
2018-06-27 17:18:53 +03:00
if ( _tok_eq ( b , e , _table [ i ] . str ) ) {
* r = _table [ i ] . state ;
return true ;
}
2018-04-30 18:16:58 +03:00
}
return false ;
}
2018-05-02 13:15:35 +03:00
static bool _parse_recovering ( const char * b , const char * e , void * context )
2018-04-30 18:16:58 +03:00
{
2018-06-27 17:18:53 +03:00
bool * r = context ;
2018-05-02 13:15:35 +03:00
2018-04-30 18:16:58 +03:00
if ( _tok_eq ( b , e , " recovering " ) )
* r = true ;
else if ( _tok_eq ( b , e , " - " ) )
2018-06-27 17:18:53 +03:00
* r = false ;
2018-04-30 18:16:58 +03:00
2018-06-27 17:18:53 +03:00
else
return false ;
2018-04-30 18:16:58 +03:00
2018-06-27 17:18:53 +03:00
return true ;
2018-04-30 18:16:58 +03:00
}
2018-05-02 13:15:35 +03:00
static bool _parse_index_state ( const char * b , const char * e , void * context )
2018-04-30 18:16:58 +03:00
{
2018-06-27 17:18:53 +03:00
static const struct {
const char str [ 8 ] ;
enum vdo_index_state state ;
} _table [ ] = {
{ " error " , VDO_INDEX_ERROR } ,
{ " closed " , VDO_INDEX_CLOSED } ,
{ " opening " , VDO_INDEX_OPENING } ,
{ " closing " , VDO_INDEX_CLOSING } ,
{ " offline " , VDO_INDEX_OFFLINE } ,
{ " online " , VDO_INDEX_ONLINE } ,
{ " unknown " , VDO_INDEX_UNKNOWN }
} ;
enum vdo_index_state * r = context ;
2018-04-30 18:16:58 +03:00
unsigned i ;
for ( i = 0 ; i < DM_ARRAY_SIZE ( _table ) ; i + + ) {
2018-06-27 17:18:53 +03:00
if ( _tok_eq ( b , e , _table [ i ] . str ) ) {
* r = _table [ i ] . state ;
return true ;
}
2018-04-30 18:16:58 +03:00
}
2018-06-27 17:18:53 +03:00
return false ;
2018-04-30 18:16:58 +03:00
}
2018-05-02 13:15:35 +03:00
static bool _parse_uint64 ( const char * b , const char * e , void * context )
{
2018-06-27 17:18:53 +03:00
uint64_t * r = context , n ;
2018-05-02 13:15:35 +03:00
n = 0 ;
while ( b ! = e ) {
2018-06-27 17:18:53 +03:00
if ( ! isdigit ( * b ) )
return false ;
2018-05-02 13:15:35 +03:00
2018-05-10 15:01:26 +03:00
n = ( n * 10 ) + ( * b - ' 0 ' ) ;
2018-05-02 13:15:35 +03:00
b + + ;
}
* r = n ;
return true ;
}
2018-04-30 18:16:58 +03:00
static const char * _eat_space ( const char * b , const char * e )
{
while ( b ! = e & & isspace ( * b ) )
2018-06-27 17:18:53 +03:00
b + + ;
2018-04-30 18:16:58 +03:00
2018-06-27 17:18:53 +03:00
return b ;
2018-04-30 18:16:58 +03:00
}
static const char * _next_tok ( const char * b , const char * e )
{
2018-06-27 17:18:53 +03:00
const char * te = b ;
2018-05-10 15:01:26 +03:00
while ( te ! = e & & ! isspace ( * te ) )
2018-06-27 17:18:53 +03:00
te + + ;
2018-04-30 18:16:58 +03:00
2018-06-27 17:18:53 +03:00
return te = = b ? NULL : te ;
2018-04-30 18:16:58 +03:00
}
2018-05-10 15:01:26 +03:00
static void _set_error ( struct vdo_status_parse_result * result , const char * fmt , . . . )
2018-06-27 17:18:53 +03:00
__attribute__ ( ( format ( printf , 2 , 3 ) ) ) ;
2018-05-02 13:15:35 +03:00
2018-05-10 15:01:26 +03:00
static void _set_error ( struct vdo_status_parse_result * result , const char * fmt , . . . )
2018-05-02 13:15:35 +03:00
{
2018-06-27 17:18:53 +03:00
va_list ap ;
2018-05-02 13:15:35 +03:00
2018-06-27 17:18:53 +03:00
va_start ( ap , fmt ) ;
2018-05-02 13:15:35 +03:00
vsnprintf ( result - > error , sizeof ( result - > error ) , fmt , ap ) ;
2018-06-27 17:18:53 +03:00
va_end ( ap ) ;
2018-05-02 13:15:35 +03:00
}
2018-04-30 18:16:58 +03:00
static bool _parse_field ( const char * * b , const char * e ,
2018-06-27 17:18:53 +03:00
bool ( * p_fn ) ( const char * , const char * , void * ) ,
void * field , const char * field_name ,
struct vdo_status_parse_result * result )
2018-04-30 18:16:58 +03:00
{
2018-06-27 17:18:53 +03:00
const char * te ;
2018-04-30 18:16:58 +03:00
2018-06-27 17:18:53 +03:00
te = _next_tok ( * b , e ) ;
if ( ! te ) {
_set_error ( result , " couldn't get token for '%s' " , field_name ) ;
return false ;
}
2018-04-30 18:16:58 +03:00
2018-06-27 17:18:53 +03:00
if ( ! p_fn ( * b , te , field ) ) {
_set_error ( result , " couldn't parse '%s' " , field_name ) ;
return false ;
}
2018-04-30 18:16:58 +03:00
2018-05-02 13:15:35 +03:00
* b = _eat_space ( te , e ) ;
2018-06-27 17:18:53 +03:00
return true ;
2018-04-30 18:16:58 +03:00
}
2018-06-27 17:18:53 +03:00
bool vdo_status_parse ( struct dm_pool * mem , const char * input ,
struct vdo_status_parse_result * result )
2018-04-30 18:16:58 +03:00
{
2018-05-02 13:15:35 +03:00
const char * b = b = input ;
2018-04-30 18:16:58 +03:00
const char * e = input + strlen ( input ) ;
const char * te ;
2018-06-27 17:18:53 +03:00
struct vdo_status * s ;
s = ( ! mem ) ? malloc ( sizeof ( * s ) ) : dm_pool_zalloc ( mem , sizeof ( * s ) ) ;
2018-04-30 18:16:58 +03:00
if ( ! s ) {
2018-06-27 17:18:53 +03:00
_set_error ( result , " out of memory " ) ;
return false ;
2018-04-30 18:16:58 +03:00
}
2018-05-02 13:15:35 +03:00
b = _eat_space ( b , e ) ;
2018-04-30 18:16:58 +03:00
te = _next_tok ( b , e ) ;
if ( ! te ) {
2018-06-27 17:18:53 +03:00
_set_error ( result , " couldn't get token for device " ) ;
goto bad ;
2018-04-30 18:16:58 +03:00
}
2018-06-27 17:18:53 +03:00
if ( ! ( s - > device = ( ! mem ) ? malloc ( ( e - b ) + 1 ) : dm_pool_alloc ( mem , ( e - b ) + 1 ) ) ) {
2018-05-02 13:15:35 +03:00
_set_error ( result , " out of memory " ) ;
2018-06-27 17:18:53 +03:00
goto bad ;
2018-04-30 18:16:58 +03:00
}
2018-06-27 17:18:53 +03:00
dm_strncpy ( s - > device , b , te - b ) ;
2018-04-30 18:16:58 +03:00
2018-05-02 13:15:35 +03:00
b = _eat_space ( te , e ) ;
2018-04-30 18:16:58 +03:00
# define XX(p, f, fn) if (!_parse_field(&b, e, p, f, fn, result)) goto bad;
2018-05-02 13:15:35 +03:00
XX ( _parse_operating_mode , & s - > operating_mode , " operating mode " ) ;
2018-04-30 18:16:58 +03:00
XX ( _parse_recovering , & s - > recovering , " recovering " ) ;
2018-05-02 13:15:35 +03:00
XX ( _parse_index_state , & s - > index_state , " index state " ) ;
2018-04-30 18:16:58 +03:00
XX ( _parse_compression_state , & s - > compression_state , " compression state " ) ;
XX ( _parse_uint64 , & s - > used_blocks , " used blocks " ) ;
XX ( _parse_uint64 , & s - > total_blocks , " total blocks " ) ;
# undef XX
2018-05-10 15:01:26 +03:00
if ( b ! = e ) {
_set_error ( result , " too many tokens " ) ;
goto bad ;
}
2018-06-27 17:18:53 +03:00
result - > status = s ;
return true ;
2018-04-30 18:16:58 +03:00
bad :
2018-06-27 17:18:53 +03:00
if ( s & & ! mem ) {
free ( s - > device ) ;
free ( s ) ;
}
2018-04-30 18:16:58 +03:00
return false ;
}
//----------------------------------------------------------------