2001-12-11 15:16:58 +03:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the LGPL .
*/
2002-11-18 17:04:08 +03:00
# include "lib.h"
2001-12-11 15:18:56 +03:00
# include "import-export.h"
2001-12-11 15:16:58 +03:00
# include "metadata.h"
# include "hash.h"
# include "pool.h"
2002-07-11 18:21:49 +04:00
# include "display.h"
2002-11-18 17:04:08 +03:00
# include "lvm-string.h"
2001-12-11 15:16:58 +03:00
2001-12-20 14:52:54 +03:00
# include <stdarg.h>
# include <time.h>
2002-11-18 17:04:08 +03:00
# include <sys/utsname.h>
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
struct formatter ;
typedef int ( * out_with_comment_fn ) ( struct formatter * f , const char * comment ,
const char * fmt , va_list ap ) ;
typedef void ( * nl_fn ) ( struct formatter * f ) ;
/*
* The first half of this file deals with
* exporting the vg , ie . writing it to a file .
*/
2001-12-11 15:16:58 +03:00
struct formatter {
struct pool * mem ; /* pv names allocated from here */
2002-04-24 22:20:51 +04:00
struct hash_table * pv_names ; /* dev_name -> pv_name (eg, pv1) */
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
union {
FILE * fp ; /* where we're writing to */
struct {
char * buf ;
uint32_t size ;
uint32_t used ;
} buf ;
} data ;
out_with_comment_fn out_with_comment ;
nl_fn nl ;
2001-12-20 19:05:14 +03:00
2002-11-18 17:04:08 +03:00
int indent ; /* current level of indentation */
2001-12-20 19:05:14 +03:00
int error ;
2002-11-18 17:04:08 +03:00
int header ; /* 1 => comments at start; 0 => end */
2001-12-11 15:16:58 +03:00
} ;
2002-11-18 17:04:08 +03:00
static struct utsname _utsname ;
static void _init ( void )
{
static int _initialised = 0 ;
if ( _initialised )
return ;
if ( uname ( & _utsname ) ) {
log_error ( " uname failed: %s " , strerror ( errno ) ) ;
memset ( & _utsname , 0 , sizeof ( _utsname ) ) ;
}
_initialised = 1 ;
}
2001-12-20 19:05:14 +03:00
/*
* Formatting functions .
*/
2002-11-18 17:04:08 +03:00
static int _out_size ( struct formatter * f , uint64_t size , const char * fmt , . . . )
2002-04-24 22:20:51 +04:00
__attribute__ ( ( format ( printf , 3 , 4 ) ) ) ;
2001-12-20 19:05:14 +03:00
2002-11-18 17:04:08 +03:00
static int _out_hint ( struct formatter * f , const char * fmt , . . . )
2002-04-24 22:20:51 +04:00
__attribute__ ( ( format ( printf , 2 , 3 ) ) ) ;
2001-12-20 19:05:14 +03:00
2002-11-18 17:04:08 +03:00
static int _out ( struct formatter * f , const char * fmt , . . . )
2002-04-24 22:20:51 +04:00
__attribute__ ( ( format ( printf , 2 , 3 ) ) ) ;
2001-12-20 19:05:14 +03:00
2001-12-11 15:16:58 +03:00
# define MAX_INDENT 5
static void _inc_indent ( struct formatter * f )
{
if ( + + f - > indent > MAX_INDENT )
f - > indent = MAX_INDENT ;
}
static void _dec_indent ( struct formatter * f )
{
2001-12-20 19:05:14 +03:00
if ( ! f - > indent - - ) {
2002-01-28 00:30:47 +03:00
log_error ( " Internal error tracking indentation " ) ;
2001-12-11 15:16:58 +03:00
f - > indent = 0 ;
}
}
/*
* Newline function for prettier layout .
*/
2002-11-18 17:04:08 +03:00
static void _nl_file ( struct formatter * f )
2001-12-11 15:16:58 +03:00
{
2002-11-18 17:04:08 +03:00
fprintf ( f - > data . fp , " \n " ) ;
}
static void _nl_raw ( struct formatter * f )
{
if ( f - > data . buf . used > = f - > data . buf . size - 1 )
return ;
* f - > data . buf . buf = ' \n ' ;
f - > data . buf . buf + = 1 ;
f - > data . buf . used + = 1 ;
* f - > data . buf . buf = ' \0 ' ;
return ;
2001-12-11 15:16:58 +03:00
}
# define COMMENT_TAB 6
2002-11-18 17:04:08 +03:00
static int _out_with_comment_file ( struct formatter * f , const char * comment ,
const char * fmt , va_list ap )
2001-12-11 15:16:58 +03:00
{
int i ;
char white_space [ MAX_INDENT + 1 ] ;
2002-11-18 17:04:08 +03:00
if ( ferror ( f - > data . fp ) )
return 0 ;
2001-12-20 19:05:14 +03:00
2001-12-11 15:16:58 +03:00
for ( i = 0 ; i < f - > indent ; i + + )
white_space [ i ] = ' \t ' ;
white_space [ i ] = ' \0 ' ;
2002-11-18 17:04:08 +03:00
fprintf ( f - > data . fp , white_space ) ;
i = vfprintf ( f - > data . fp , fmt , ap ) ;
2001-12-11 15:16:58 +03:00
if ( comment ) {
/*
* line comments up if possible .
*/
i + = 8 * f - > indent ;
i / = 8 ;
i + + ;
do
2002-11-18 17:04:08 +03:00
fputc ( ' \t ' , f - > data . fp ) ;
2001-12-11 15:16:58 +03:00
while ( + + i < COMMENT_TAB ) ;
2002-11-18 17:04:08 +03:00
fprintf ( f - > data . fp , comment ) ;
2001-12-11 15:16:58 +03:00
}
2002-11-18 17:04:08 +03:00
fputc ( ' \n ' , f - > data . fp ) ;
return 1 ;
}
static int _out_with_comment_raw ( struct formatter * f , const char * comment ,
const char * fmt , va_list ap )
{
int n ;
n = vsnprintf ( f - > data . buf . buf , f - > data . buf . size - f - > data . buf . used ,
fmt , ap ) ;
if ( n < 0 | | ( n > f - > data . buf . size - f - > data . buf . used - 1 ) )
return 0 ;
f - > data . buf . buf + = n ;
f - > data . buf . used + = n ;
f - > nl ( f ) ;
return 1 ;
2001-12-11 15:16:58 +03:00
}
/*
* Formats a string , converting a size specified
* in 512 - byte sectors to a more human readable
* form ( eg , megabytes ) . We may want to lift this
* for other code to use .
*/
static int _sectors_to_units ( uint64_t sectors , char * buffer , size_t s )
{
2002-12-20 02:25:55 +03:00
static const char * _units [ ] = {
2001-12-11 15:16:58 +03:00
" Kilobytes " ,
" Megabytes " ,
" Gigabytes " ,
2002-11-18 17:04:08 +03:00
" Terabytes " ,
2001-12-11 15:16:58 +03:00
NULL
2002-04-24 22:20:51 +04:00
} ;
2001-12-11 15:16:58 +03:00
int i ;
double d = ( double ) sectors ;
/* to convert to K */
d / = 2.0 ;
2002-04-24 22:20:51 +04:00
for ( i = 0 ; ( d > 1024.0 ) & & _units [ i ] ; i + + )
2001-12-11 15:16:58 +03:00
d / = 1024.0 ;
2001-12-31 22:09:51 +03:00
return lvm_snprintf ( buffer , s , " # %g %s " , d , _units [ i ] ) > 0 ;
2001-12-11 15:16:58 +03:00
}
/*
* Appends a comment giving a size in more easily
* readable form ( eg , 4 M instead of 8096 ) .
*/
2002-11-18 17:04:08 +03:00
static int _out_size ( struct formatter * f , uint64_t size , const char * fmt , . . . )
2001-12-11 15:16:58 +03:00
{
char buffer [ 64 ] ;
va_list ap ;
2002-11-18 17:04:08 +03:00
int r ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
if ( ! _sectors_to_units ( size , buffer , sizeof ( buffer ) ) )
return 0 ;
2001-12-11 15:16:58 +03:00
va_start ( ap , fmt ) ;
2002-11-18 17:04:08 +03:00
r = f - > out_with_comment ( f , buffer , fmt , ap ) ;
2001-12-11 15:16:58 +03:00
va_end ( ap ) ;
2002-11-18 17:04:08 +03:00
return r ;
2001-12-11 15:16:58 +03:00
}
/*
* Appends a comment indicating that the line is
* only a hint .
*/
2002-11-18 17:04:08 +03:00
static int _out_hint ( struct formatter * f , const char * fmt , . . . )
2001-12-11 15:16:58 +03:00
{
va_list ap ;
2002-11-18 17:04:08 +03:00
int r ;
2001-12-11 15:16:58 +03:00
va_start ( ap , fmt ) ;
2002-11-18 17:04:08 +03:00
r = f - > out_with_comment ( f , " # Hint only " , fmt , ap ) ;
2001-12-11 15:16:58 +03:00
va_end ( ap ) ;
2002-11-18 17:04:08 +03:00
return r ;
2001-12-11 15:16:58 +03:00
}
/*
* The normal output function .
*/
2002-11-18 17:04:08 +03:00
static int _out ( struct formatter * f , const char * fmt , . . . )
2001-12-11 15:16:58 +03:00
{
va_list ap ;
2002-11-18 17:04:08 +03:00
int r ;
2001-12-11 15:16:58 +03:00
va_start ( ap , fmt ) ;
2002-11-18 17:04:08 +03:00
r = f - > out_with_comment ( f , NULL , fmt , ap ) ;
2001-12-11 15:16:58 +03:00
va_end ( ap ) ;
2002-11-18 17:04:08 +03:00
return r ;
2001-12-11 15:16:58 +03:00
}
2002-11-18 17:04:08 +03:00
# define _outf(args...) do {if (!_out(args)) {stack; return 0;}} while (0)
2002-02-08 14:13:47 +03:00
static int _print_header ( struct formatter * f ,
struct volume_group * vg , const char * desc )
2001-12-11 15:16:58 +03:00
{
2001-12-20 14:52:54 +03:00
time_t t ;
t = time ( NULL ) ;
2002-11-18 17:04:08 +03:00
_outf ( f , " # Generated by LVM2: %s " , ctime ( & t ) ) ;
_outf ( f , CONTENTS_FIELD " = \" " CONTENTS_VALUE " \" " ) ;
_outf ( f , FORMAT_VERSION_FIELD " = %d " , FORMAT_VERSION_VALUE ) ;
f - > nl ( f ) ;
2002-02-08 14:13:47 +03:00
2002-11-18 17:04:08 +03:00
_outf ( f , " description = \" %s \" " , desc ) ;
f - > nl ( f ) ;
_outf ( f , " creation_host = \" %s \" \t # %s %s %s %s %s " , _utsname . nodename ,
_utsname . sysname , _utsname . nodename , _utsname . release ,
_utsname . version , _utsname . machine ) ;
_outf ( f , " creation_time = %lu \t # %s " , t , ctime ( & t ) ) ;
2002-02-08 14:13:47 +03:00
2001-12-11 15:16:58 +03:00
return 1 ;
}
static int _print_vg ( struct formatter * f , struct volume_group * vg )
{
char buffer [ 256 ] ;
2001-12-20 14:52:54 +03:00
if ( ! id_write_format ( & vg - > id , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
_outf ( f , " id = \" %s \" " , buffer ) ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
_outf ( f , " seqno = %u " , vg - > seqno ) ;
2001-12-20 14:52:54 +03:00
if ( ! print_flags ( vg - > status , VG_FLAGS , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
_outf ( f , " status = %s " , buffer ) ;
2002-01-29 20:23:33 +03:00
if ( vg - > system_id & & * vg - > system_id )
2002-11-18 17:04:08 +03:00
_outf ( f , " system_id = \" %s \" " , vg - > system_id ) ;
2002-12-20 02:25:55 +03:00
if ( ! _out_size ( f , ( uint64_t ) vg - > extent_size , " extent_size = %u " ,
vg - > extent_size ) ) {
2002-11-18 17:04:08 +03:00
stack ;
return 0 ;
}
_outf ( f , " max_lv = %u " , vg - > max_lv ) ;
_outf ( f , " max_pv = %u " , vg - > max_pv ) ;
2001-12-11 15:16:58 +03:00
return 1 ;
}
/*
* Get the pv % d name from the formatters hash
* table .
*/
2002-04-24 22:20:51 +04:00
static inline const char * _get_pv_name ( struct formatter * f ,
struct physical_volume * pv )
2001-12-11 15:16:58 +03:00
{
2002-02-08 14:13:47 +03:00
return ( pv ) ? ( const char * )
2002-04-24 22:20:51 +04:00
hash_lookup ( f - > pv_names , dev_name ( pv - > dev ) ) : " Missing " ;
2001-12-11 15:16:58 +03:00
}
static int _print_pvs ( struct formatter * f , struct volume_group * vg )
{
2001-12-20 14:52:54 +03:00
struct list * pvh ;
2001-12-11 15:16:58 +03:00
struct physical_volume * pv ;
char buffer [ 256 ] ;
const char * name ;
2002-11-18 17:04:08 +03:00
_outf ( f , " physical_volumes { " ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2002-04-24 22:20:51 +04:00
list_iterate ( pvh , & vg - > pvs ) {
2001-12-11 15:16:58 +03:00
2002-01-21 19:05:23 +03:00
pv = list_item ( pvh , struct pv_list ) - > pv ;
2001-12-20 19:05:14 +03:00
2001-12-11 15:16:58 +03:00
if ( ! ( name = _get_pv_name ( f , pv ) ) ) {
stack ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
f - > nl ( f ) ;
_outf ( f , " %s { " , name ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2001-12-20 14:52:54 +03:00
if ( ! id_write_format ( & pv - > id , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
_outf ( f , " id = \" %s \" " , buffer ) ;
if ( ! _out_hint ( f , " device = \" %s \" " , dev_name ( pv - > dev ) ) ) {
stack ;
return 0 ;
}
f - > nl ( f ) ;
2001-12-11 15:16:58 +03:00
2002-04-24 22:20:51 +04:00
if ( ! print_flags ( pv - > status , PV_FLAGS , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
_outf ( f , " status = %s " , buffer ) ;
_outf ( f , " pe_start = % " PRIu64 , pv - > pe_start ) ;
if ( ! _out_size ( f , vg - > extent_size * ( uint64_t ) pv - > pe_count ,
" pe_count = %u " , pv - > pe_count ) ) {
stack ;
return 0 ;
}
2001-12-11 15:16:58 +03:00
_dec_indent ( f ) ;
2002-11-18 17:04:08 +03:00
_outf ( f , " } " ) ;
2001-12-11 15:16:58 +03:00
}
_dec_indent ( f ) ;
2002-11-18 17:04:08 +03:00
_outf ( f , " } " ) ;
2001-12-11 15:16:58 +03:00
return 1 ;
}
static int _print_segment ( struct formatter * f , struct volume_group * vg ,
2002-11-18 17:04:08 +03:00
int count , struct lv_segment * seg )
2001-12-11 15:16:58 +03:00
{
2002-12-20 02:25:55 +03:00
unsigned int s ;
2001-12-11 15:16:58 +03:00
const char * name ;
2003-04-25 02:23:24 +04:00
const char * type ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
_outf ( f , " segment%u { " , count ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2002-11-18 17:04:08 +03:00
_outf ( f , " start_extent = %u " , seg - > le ) ;
2002-12-20 02:25:55 +03:00
if ( ! _out_size ( f , ( uint64_t ) seg - > len * vg - > extent_size ,
" extent_count = %u " , seg - > len ) ) {
2002-11-18 17:04:08 +03:00
stack ;
return 0 ;
}
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
f - > nl ( f ) ;
_outf ( f , " type = \" %s \" " , get_segtype_string ( seg - > type ) ) ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
switch ( seg - > type ) {
2003-04-25 02:23:24 +04:00
case SEG_SNAPSHOT :
_outf ( f , " chunk_size = %u " , seg - > chunk_size ) ;
_outf ( f , " origin = \" %s \" " , seg - > origin - > name ) ;
_outf ( f , " cow_store = \" %s \" " , seg - > cow - > name ) ;
break ;
case SEG_MIRRORED :
2002-11-18 17:04:08 +03:00
case SEG_STRIPED :
2003-04-25 02:23:24 +04:00
type = ( seg - > type = = SEG_MIRRORED ) ? " mirror " : " stripe " ;
_outf ( f , " %s_count = %u%s " , type , seg - > area_count ,
( seg - > area_count = = 1 ) ? " \t # linear " : " " ) ;
2001-12-11 15:16:58 +03:00
2003-05-06 16:02:36 +04:00
if ( ( seg - > type = = SEG_MIRRORED ) & & ( seg - > status & PVMOVE ) )
_out_size ( f , ( uint64_t ) seg - > extents_moved ,
" extents_moved = %u " , seg - > extents_moved ) ;
2003-04-25 02:23:24 +04:00
if ( ( seg - > type = = SEG_STRIPED ) & & ( seg - > area_count > 1 ) )
2002-12-20 02:25:55 +03:00
_out_size ( f , ( uint64_t ) seg - > stripe_size ,
2002-11-18 17:04:08 +03:00
" stripe_size = %u " , seg - > stripe_size ) ;
f - > nl ( f ) ;
2003-04-25 02:23:24 +04:00
_outf ( f , " %ss = [ " , type ) ;
2002-11-18 17:04:08 +03:00
_inc_indent ( f ) ;
2003-04-25 02:23:24 +04:00
for ( s = 0 ; s < seg - > area_count ; s + + ) {
switch ( seg - > area [ s ] . type ) {
case AREA_PV :
if ( ! ( name = _get_pv_name ( f , seg - >
area [ s ] . u . pv . pv ) ) ) {
stack ;
return 0 ;
}
_outf ( f , " \" %s \" , %u%s " , name ,
seg - > area [ s ] . u . pv . pe ,
( s = = seg - > area_count - 1 ) ? " " : " , " ) ;
break ;
case AREA_LV :
_outf ( f , " \" %s \" , %u%s " ,
seg - > area [ s ] . u . lv . lv - > name ,
seg - > area [ s ] . u . lv . le ,
( s = = seg - > area_count - 1 ) ? " " : " , " ) ;
2002-11-18 17:04:08 +03:00
}
2001-12-11 15:16:58 +03:00
}
2002-11-18 17:04:08 +03:00
_dec_indent ( f ) ;
_outf ( f , " ] " ) ;
break ;
2001-12-11 15:16:58 +03:00
}
_dec_indent ( f ) ;
2002-11-18 17:04:08 +03:00
_outf ( f , " } " ) ;
2001-12-11 15:16:58 +03:00
return 1 ;
}
2001-12-20 14:52:54 +03:00
static int _count_segments ( struct logical_volume * lv )
{
int r = 0 ;
struct list * segh ;
2002-04-24 22:20:51 +04:00
list_iterate ( segh , & lv - > segments )
r + + ;
2001-12-20 14:52:54 +03:00
return r ;
}
2002-11-18 17:04:08 +03:00
static int _print_snapshot ( struct formatter * f , struct snapshot * snap ,
unsigned int count )
{
char buffer [ 256 ] ;
struct lv_segment seg ;
f - > nl ( f ) ;
_outf ( f , " snapshot%u { " , count ) ;
_inc_indent ( f ) ;
if ( ! id_write_format ( & snap - > id , buffer , sizeof ( buffer ) ) ) {
stack ;
return 0 ;
}
_outf ( f , " id = \" %s \" " , buffer ) ;
if ( ! print_flags ( LVM_READ | LVM_WRITE | VISIBLE_LV , LV_FLAGS ,
buffer , sizeof ( buffer ) ) ) {
stack ;
return 0 ;
}
_outf ( f , " status = %s " , buffer ) ;
_outf ( f , " segment_count = 1 " ) ;
f - > nl ( f ) ;
seg . type = SEG_SNAPSHOT ;
seg . le = 0 ;
seg . len = snap - > origin - > le_count ;
seg . origin = snap - > origin ;
seg . cow = snap - > cow ;
seg . chunk_size = snap - > chunk_size ;
if ( ! _print_segment ( f , snap - > origin - > vg , 1 , & seg ) ) {
stack ;
return 0 ;
}
_dec_indent ( f ) ;
_outf ( f , " } " ) ;
return 1 ;
}
static int _print_snapshots ( struct formatter * f , struct volume_group * vg )
{
struct list * sh ;
struct snapshot * s ;
unsigned int count = 0 ;
list_iterate ( sh , & vg - > snapshots ) {
s = list_item ( sh , struct snapshot_list ) - > snapshot ;
if ( ! _print_snapshot ( f , s , count + + ) ) {
stack ;
return 0 ;
}
}
return 1 ;
}
2001-12-11 15:16:58 +03:00
static int _print_lvs ( struct formatter * f , struct volume_group * vg )
{
struct list * lvh , * segh ;
struct logical_volume * lv ;
2002-11-18 17:04:08 +03:00
struct lv_segment * seg ;
2001-12-11 15:16:58 +03:00
char buffer [ 256 ] ;
2002-01-16 14:34:29 +03:00
int seg_count ;
2001-12-11 15:16:58 +03:00
2002-02-13 16:29:16 +03:00
/*
* Don ' t bother with an lv section if there are no lvs .
*/
if ( list_empty ( & vg - > lvs ) )
return 1 ;
2002-11-18 17:04:08 +03:00
_outf ( f , " logical_volumes { " ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2002-04-24 22:20:51 +04:00
list_iterate ( lvh , & vg - > lvs ) {
2002-01-21 19:49:32 +03:00
lv = list_item ( lvh , struct lv_list ) - > lv ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
f - > nl ( f ) ;
_outf ( f , " %s { " , lv - > name ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2002-03-05 23:03:09 +03:00
/* FIXME: Write full lvid */
if ( ! id_write_format ( & lv - > lvid . id [ 1 ] , buffer , sizeof ( buffer ) ) ) {
2002-02-21 18:26:44 +03:00
stack ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
_outf ( f , " id = \" %s \" " , buffer ) ;
2002-02-21 18:26:44 +03:00
2002-11-18 17:04:08 +03:00
if ( ! print_flags ( lv - > status , LV_FLAGS , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
_outf ( f , " status = %s " , buffer ) ;
if ( lv - > alloc ! = ALLOC_DEFAULT )
_outf ( f , " allocation_policy = \" %s \" " ,
get_alloc_string ( lv - > alloc ) ) ;
if ( lv - > read_ahead )
_outf ( f , " read_ahead = %u " , lv - > read_ahead ) ;
2003-04-02 23:14:43 +04:00
if ( lv - > major > = 0 )
_outf ( f , " major = %d " , lv - > major ) ;
2002-02-01 20:54:39 +03:00
if ( lv - > minor > = 0 )
2002-11-18 17:04:08 +03:00
_outf ( f , " minor = %d " , lv - > minor ) ;
_outf ( f , " segment_count = %u " , _count_segments ( lv ) ) ;
f - > nl ( f ) ;
2001-12-11 15:16:58 +03:00
2002-01-16 14:34:29 +03:00
seg_count = 1 ;
2002-04-24 22:20:51 +04:00
list_iterate ( segh , & lv - > segments ) {
2002-11-18 17:04:08 +03:00
seg = list_item ( segh , struct lv_segment ) ;
2001-12-11 15:16:58 +03:00
2002-01-03 15:43:01 +03:00
if ( ! _print_segment ( f , vg , seg_count + + , seg ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
}
_dec_indent ( f ) ;
2002-11-18 17:04:08 +03:00
_outf ( f , " } " ) ;
2001-12-11 15:16:58 +03:00
}
2002-11-18 17:04:08 +03:00
if ( ! _print_snapshots ( f , vg ) ) {
stack ;
return 0 ;
2002-02-13 16:29:16 +03:00
}
_dec_indent ( f ) ;
2002-11-18 17:04:08 +03:00
_outf ( f , " } " ) ;
2002-02-13 16:29:16 +03:00
return 1 ;
}
2001-12-11 15:16:58 +03:00
/*
* In the text format we refer to pv ' s as ' pv1 ' ,
* ' pv2 ' etc . This function builds a hash table
* to enable a quick lookup from device - > name .
*/
2002-04-24 22:20:51 +04:00
static int _build_pv_names ( struct formatter * f , struct volume_group * vg )
2001-12-11 15:16:58 +03:00
{
int count = 0 ;
struct list * pvh ;
struct physical_volume * pv ;
char buffer [ 32 ] , * name ;
if ( ! ( f - > mem = pool_create ( 512 ) ) ) {
stack ;
goto bad ;
}
if ( ! ( f - > pv_names = hash_create ( 128 ) ) ) {
stack ;
goto bad ;
}
2002-04-24 22:20:51 +04:00
list_iterate ( pvh , & vg - > pvs ) {
2002-01-21 19:05:23 +03:00
pv = list_item ( pvh , struct pv_list ) - > pv ;
2001-12-11 15:16:58 +03:00
2003-04-25 02:23:24 +04:00
/* FIXME But skip if there's already an LV called pv%d ! */
2002-04-24 22:20:51 +04:00
if ( lvm_snprintf ( buffer , sizeof ( buffer ) , " pv%d " , count + + ) < 0 ) {
2001-12-11 15:16:58 +03:00
stack ;
goto bad ;
}
if ( ! ( name = pool_strdup ( f - > mem , buffer ) ) ) {
stack ;
goto bad ;
}
2001-12-20 19:05:14 +03:00
if ( ! hash_insert ( f - > pv_names , dev_name ( pv - > dev ) , name ) ) {
2001-12-11 15:16:58 +03:00
stack ;
goto bad ;
}
}
return 1 ;
2002-04-24 22:20:51 +04:00
bad :
2001-12-11 15:16:58 +03:00
if ( f - > mem )
pool_destroy ( f - > mem ) ;
if ( f - > pv_names )
hash_destroy ( f - > pv_names ) ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
static int _text_vg_export ( struct formatter * f ,
struct volume_group * vg , const char * desc )
2001-12-11 15:16:58 +03:00
{
int r = 0 ;
if ( ! _build_pv_names ( f , vg ) ) {
stack ;
goto out ;
}
# define fail do {stack; goto out;} while(0)
2002-11-18 17:04:08 +03:00
if ( f - > header & & ! _print_header ( f , vg , desc ) )
fail ;
if ( ! _out ( f , " %s { " , vg - > name ) )
2001-12-11 15:16:58 +03:00
fail ;
2001-12-20 14:52:54 +03:00
_inc_indent ( f ) ;
2001-12-11 15:16:58 +03:00
if ( ! _print_vg ( f , vg ) )
fail ;
2002-11-18 17:04:08 +03:00
f - > nl ( f ) ;
2001-12-11 15:16:58 +03:00
if ( ! _print_pvs ( f , vg ) )
fail ;
2002-11-18 17:04:08 +03:00
f - > nl ( f ) ;
2001-12-11 15:16:58 +03:00
if ( ! _print_lvs ( f , vg ) )
fail ;
2002-11-18 17:04:08 +03:00
_dec_indent ( f ) ;
if ( ! _out ( f , " } " ) )
2002-02-13 16:29:16 +03:00
fail ;
2002-11-18 17:04:08 +03:00
if ( ! f - > header & & ! _print_header ( f , vg , desc ) )
fail ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
# undef fail
r = 1 ;
2001-12-11 15:16:58 +03:00
2002-04-24 22:20:51 +04:00
out :
2001-12-11 15:16:58 +03:00
if ( f - > mem )
pool_destroy ( f - > mem ) ;
if ( f - > pv_names )
hash_destroy ( f - > pv_names ) ;
2002-11-18 17:04:08 +03:00
return r ;
}
int text_vg_export_file ( struct volume_group * vg , const char * desc , FILE * fp )
{
struct formatter * f ;
int r ;
_init ( ) ;
if ( ! ( f = dbg_malloc ( sizeof ( * f ) ) ) ) {
stack ;
return 0 ;
}
memset ( f , 0 , sizeof ( * f ) ) ;
f - > data . fp = fp ;
f - > indent = 0 ;
f - > header = 1 ;
f - > out_with_comment = & _out_with_comment_file ;
f - > nl = & _nl_file ;
r = _text_vg_export ( f , vg , desc ) ;
if ( r )
r = ! ferror ( f - > data . fp ) ;
2001-12-20 14:52:54 +03:00
dbg_free ( f ) ;
2001-12-11 15:16:58 +03:00
return r ;
}
2002-11-18 17:04:08 +03:00
/* Returns amount of buffer used incl. terminating NUL */
int text_vg_export_raw ( struct volume_group * vg , const char * desc , char * buf ,
uint32_t size )
{
struct formatter * f ;
int r ;
_init ( ) ;
if ( ! ( f = dbg_malloc ( sizeof ( * f ) ) ) ) {
stack ;
return 0 ;
}
memset ( f , 0 , sizeof ( * f ) ) ;
f - > data . buf . buf = buf ;
f - > data . buf . size = size ;
f - > indent = 0 ;
f - > header = 0 ;
f - > out_with_comment = & _out_with_comment_raw ;
f - > nl = & _nl_raw ;
if ( ! _text_vg_export ( f , vg , desc ) ) {
stack ;
r = 0 ;
goto out ;
}
r = f - > data . buf . used + 1 ;
out :
dbg_free ( f ) ;
return r ;
}
# undef _outf