2001-11-21 12:20:05 +03:00
/*
2002-02-22 14:44:56 +03:00
* Copyright ( C ) 2001 - 2002 Sistina Software ( UK ) Limited .
2001-11-21 12:20:05 +03:00
*
* This file is released under the LGPL .
*/
# include "format-text.h"
2002-01-07 12:16:20 +03:00
# include "import-export.h"
2001-11-21 12:20:05 +03:00
2002-01-09 22:16:48 +03:00
# include "lvm-file.h"
2001-11-21 12:20:05 +03:00
# include "log.h"
# include "pool.h"
# include "config.h"
# include "hash.h"
2002-02-22 14:44:56 +03:00
# include "display.h"
2002-01-10 19:48:28 +03:00
# include "dbg_malloc.h"
2002-02-11 23:50:53 +03:00
# include "toolcontext.h"
2002-04-24 22:20:51 +04:00
# include "vgcache.h"
# include "lvm-string.h"
2001-11-21 12:20:05 +03:00
2002-01-09 22:16:48 +03:00
# include <unistd.h>
# include <sys/types.h>
# include <sys/file.h>
# include <limits.h>
2002-04-24 22:20:51 +04:00
# include <dirent.h>
2002-01-09 22:16:48 +03:00
2002-02-22 14:44:56 +03:00
/* Arbitrary limits copied from format1/disk_rep.h */
# define MAX_PV 256
# define MAX_LV 256
# define MAX_VG 99
2002-02-25 01:31:55 +03:00
# define MAX_PV_SIZE ((uint32_t) -1) /* 2TB in sectors - 1 */
2002-02-22 14:44:56 +03:00
2002-04-24 22:20:51 +04:00
struct dir_list {
struct list list ;
char dir [ 0 ] ;
} ;
struct text_context {
char * path_live ; /* Path to file holding live metadata */
char * path_edit ; /* Path to file holding edited metadata */
char * desc ; /* Description placed inside file */
} ;
2001-11-21 12:20:05 +03:00
/*
2002-01-07 12:05:31 +03:00
* NOTE : Currently there can be only one vg per file .
2001-11-21 12:20:05 +03:00
*/
2002-02-22 14:44:56 +03:00
static int _pv_setup ( struct format_instance * fi , struct physical_volume * pv ,
struct volume_group * vg )
2001-11-21 12:20:05 +03:00
{
2002-02-22 14:44:56 +03:00
/* setup operations for the PV structure */
if ( pv - > size > MAX_PV_SIZE )
pv - > size - - ;
if ( pv - > size > MAX_PV_SIZE ) {
/* FIXME Limit hardcoded */
log_error ( " Physical volumes cannot be bigger than 2TB " ) ;
return 0 ;
}
2001-11-21 12:20:05 +03:00
2002-02-22 14:44:56 +03:00
return 1 ;
2001-11-21 12:20:05 +03:00
}
2002-02-22 14:44:56 +03:00
static int _vg_setup ( struct format_instance * fi , struct volume_group * vg )
2001-11-21 12:20:05 +03:00
{
2002-02-22 14:44:56 +03:00
/* just check max_pv and max_lv */
if ( vg - > max_lv > = MAX_LV )
vg - > max_lv = MAX_LV - 1 ;
2001-11-21 12:20:05 +03:00
2002-02-25 01:31:55 +03:00
if ( vg - > max_pv > = MAX_PV )
2002-02-22 14:44:56 +03:00
vg - > max_pv = MAX_PV - 1 ;
2001-11-21 12:20:05 +03:00
2002-04-24 22:20:51 +04:00
if ( vg - > extent_size & ( vg - > extent_size - 1 ) ) {
log_error ( " Extent size must be power of 2 " ) ;
return 0 ;
}
2002-02-22 14:44:56 +03:00
return 1 ;
2001-11-21 12:20:05 +03:00
}
2002-02-22 14:44:56 +03:00
static int _lv_setup ( struct format_instance * fi , struct logical_volume * lv )
2001-11-21 12:20:05 +03:00
{
2002-02-22 14:44:56 +03:00
uint64_t max_size = UINT_MAX ;
2001-11-21 12:20:05 +03:00
2002-04-24 22:20:51 +04:00
if ( ! * lv - > lvid . s )
lvid_create ( & lv - > lvid , & lv - > vg - > id ) ;
2002-02-22 14:44:56 +03:00
if ( lv - > size > max_size ) {
2002-02-25 01:31:55 +03:00
char * dummy = display_size ( max_size , SIZE_SHORT ) ;
2002-02-22 14:44:56 +03:00
log_error ( " logical volumes cannot be larger than %s " , dummy ) ;
dbg_free ( dummy ) ;
return 0 ;
}
return 1 ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +03:00
static struct volume_group * _vg_read ( struct format_instance * fi ,
2002-04-24 22:20:51 +04:00
const char * vgname , void * mdl )
2001-11-21 12:20:05 +03:00
{
2002-04-24 22:20:51 +04:00
struct text_context * tc = ( struct text_context * ) mdl ;
2002-01-10 17:27:47 +03:00
struct volume_group * vg ;
2002-02-11 14:43:17 +03:00
time_t when ;
char * desc ;
2002-01-10 17:27:47 +03:00
2002-04-24 22:20:51 +04:00
if ( ! ( vg = text_vg_import ( fi , tc - > path_live , fi - > fmt - > cmd - > um , & when ,
& desc ) ) ) {
2002-01-10 17:27:47 +03:00
stack ;
return NULL ;
}
/*
* Currently you can only have a single volume group per
* text file ( this restriction may remain ) . We need to
* check that it contains the correct volume group .
*/
2002-04-24 22:20:51 +04:00
if ( strcmp ( vgname , vg - > name ) ) {
pool_free ( fi - > fmt - > cmd - > mem , vg ) ;
2002-01-10 17:27:47 +03:00
log_err ( " '%s' does not contain volume group '%s'. " ,
2002-04-24 22:20:51 +04:00
tc - > path_live , vgname ) ;
2002-01-10 17:27:47 +03:00
return NULL ;
}
return vg ;
2001-11-21 12:20:05 +03:00
}
2002-04-24 22:20:51 +04:00
static int _vg_write ( struct format_instance * fi , struct volume_group * vg ,
void * mdl )
2001-11-21 12:20:05 +03:00
{
2002-04-24 22:20:51 +04:00
struct text_context * tc = ( struct text_context * ) mdl ;
2002-01-15 20:37:23 +03:00
2002-01-07 12:05:31 +03:00
FILE * fp ;
2002-01-10 17:27:47 +03:00
int fd ;
2002-01-09 22:16:48 +03:00
char * slash ;
char temp_file [ PATH_MAX ] , temp_dir [ PATH_MAX ] ;
2002-04-24 22:20:51 +04:00
slash = rindex ( tc - > path_edit , ' / ' ) ;
2001-11-21 12:20:05 +03:00
2002-01-09 22:16:48 +03:00
if ( slash = = 0 )
strcpy ( temp_dir , " . " ) ;
2002-04-24 22:20:51 +04:00
else if ( slash - tc - > path_edit < PATH_MAX ) {
strncpy ( temp_dir , tc - > path_edit , slash - tc - > path_edit ) ;
temp_dir [ slash - tc - > path_edit ] = ' \0 ' ;
2002-01-10 17:27:47 +03:00
2002-01-09 22:16:48 +03:00
} else {
log_error ( " Text format failed to determine directory. " ) ;
return 0 ;
}
2002-02-25 01:31:55 +03:00
if ( ! create_temp_name ( temp_dir , temp_file , sizeof ( temp_file ) , & fd ) ) {
log_err ( " Couldn't create temporary text file name. " ) ;
return 0 ;
}
2002-01-09 22:16:48 +03:00
if ( ! ( fp = fdopen ( fd , " w " ) ) ) {
log_sys_error ( " fdopen " , temp_file ) ;
close ( fd ) ;
2002-01-07 12:05:31 +03:00
return 0 ;
}
2001-11-21 12:20:05 +03:00
2002-02-08 14:13:47 +03:00
if ( ! text_vg_export ( fp , vg , tc - > desc ) ) {
2002-01-09 22:16:48 +03:00
log_error ( " Failed to write metadata to %s. " , temp_file ) ;
2002-01-09 16:07:03 +03:00
fclose ( fp ) ;
return 0 ;
}
2002-04-24 22:20:51 +04:00
if ( fsync ( fd ) ) {
log_sys_error ( " fsync " , tc - > path_edit ) ;
fclose ( fp ) ;
return 0 ;
}
2002-01-09 22:16:48 +03:00
if ( fclose ( fp ) ) {
2002-04-24 22:20:51 +04:00
log_sys_error ( " fclose " , tc - > path_edit ) ;
return 0 ;
}
if ( rename ( temp_file , tc - > path_edit ) ) {
log_error ( " %s: rename to %s failed: %s " , temp_file ,
tc - > path_edit , strerror ( errno ) ) ;
return 0 ;
}
return 1 ;
}
static int _pv_commit ( struct format_instance * fi , struct physical_volume * pv ,
void * mdl )
{
// struct text_context *tc = (struct text_context *) mdl;
return 1 ;
}
static int _vg_commit ( struct format_instance * fi , struct volume_group * vg ,
void * mdl )
{
struct text_context * tc = ( struct text_context * ) mdl ;
if ( rename ( tc - > path_edit , tc - > path_live ) ) {
log_error ( " %s: rename to %s failed: %s " , tc - > path_edit ,
tc - > path_edit , strerror ( errno ) ) ;
2002-01-07 12:05:31 +03:00
return 0 ;
}
2001-11-21 12:20:05 +03:00
2002-04-24 22:20:51 +04:00
sync ( ) ;
return 1 ;
}
static int _vg_remove ( struct format_instance * fi , struct volume_group * vg ,
void * mdl )
{
struct text_context * tc = ( struct text_context * ) mdl ;
if ( path_exists ( tc - > path_edit ) & & unlink ( tc - > path_edit ) ) {
log_sys_error ( " unlink " , tc - > path_edit ) ;
2002-01-09 22:16:48 +03:00
return 0 ;
}
2002-04-24 22:20:51 +04:00
if ( path_exists ( tc - > path_live ) & & unlink ( tc - > path_live ) ) {
log_sys_error ( " unlink " , tc - > path_live ) ;
return 0 ;
}
sync ( ) ;
2002-01-07 12:05:31 +03:00
return 1 ;
2001-11-21 12:20:05 +03:00
}
2002-04-24 22:20:51 +04:00
/* Add vgname to list if it's not already there */
static int _add_vgname ( struct format_type * fmt , struct list * names ,
char * vgname )
2002-02-22 14:44:56 +03:00
{
2002-04-24 22:20:51 +04:00
struct list * nlh ;
2002-02-22 14:44:56 +03:00
struct name_list * nl ;
2002-04-24 22:20:51 +04:00
list_iterate ( nlh , names ) {
nl = list_item ( nlh , struct name_list ) ;
if ( ! strcmp ( vgname , nl - > name ) )
return 1 ;
2002-02-22 14:44:56 +03:00
}
2002-04-24 22:20:51 +04:00
vgcache_add ( vgname , NULL , NULL , fmt ) ;
2002-02-22 14:44:56 +03:00
2002-04-24 22:20:51 +04:00
if ( ! ( nl = pool_alloc ( fmt - > cmd - > mem , sizeof ( * nl ) ) ) ) {
stack ;
return 0 ;
2002-02-22 14:44:56 +03:00
}
2002-04-24 22:20:51 +04:00
if ( ! ( nl - > name = pool_strdup ( fmt - > cmd - > mem , vgname ) ) ) {
log_error ( " strdup %s failed " , vgname ) ;
return 0 ;
}
2002-02-22 14:44:56 +03:00
2002-04-24 22:20:51 +04:00
list_add ( names , & nl - > list ) ;
return 1 ;
}
2002-02-22 14:44:56 +03:00
2002-04-24 22:20:51 +04:00
static struct list * _get_vgs ( struct format_type * fmt , struct list * names )
{
struct dirent * dirent ;
struct dir_list * dl ;
struct list * dlh , * dir_list ;
char * tmp ;
DIR * d ;
dir_list = ( struct list * ) fmt - > private ;
list_iterate ( dlh , dir_list ) {
dl = list_item ( dlh , struct dir_list ) ;
if ( ! ( d = opendir ( dl - > dir ) ) ) {
log_sys_error ( " opendir " , dl - > dir ) ;
continue ;
}
while ( ( dirent = readdir ( d ) ) )
if ( strcmp ( dirent - > d_name , " . " ) & &
strcmp ( dirent - > d_name , " .. " ) & &
( ! ( tmp = strstr ( dirent - > d_name , " .tmp " ) ) | |
tmp ! = dirent - > d_name + strlen ( dirent - > d_name )
- 4 ) )
if ( ! _add_vgname ( fmt , names , dirent - > d_name ) )
return NULL ;
if ( closedir ( d ) )
log_sys_error ( " closedir " , dl - > dir ) ;
2002-02-22 14:44:56 +03:00
}
return names ;
}
2002-04-24 22:20:51 +04:00
static struct list * _get_pvs ( struct format_type * fmt , struct list * results )
2002-02-22 14:44:56 +03:00
{
2002-04-24 22:20:51 +04:00
struct pv_list * pvl , * rhl ;
2002-02-22 14:44:56 +03:00
struct list * vgh ;
struct list * pvh ;
2002-04-24 22:20:51 +04:00
struct list * names = pool_alloc ( fmt - > cmd - > mem , sizeof ( * names ) ) ;
struct list * rh ;
struct name_list * nl ;
struct volume_group * vg ;
2002-02-22 14:44:56 +03:00
2002-04-24 22:20:51 +04:00
list_init ( names ) ;
if ( ! _get_vgs ( fmt , names ) ) {
stack ;
return NULL ;
}
2002-02-22 14:44:56 +03:00
2002-04-24 22:20:51 +04:00
list_iterate ( vgh , names ) {
2002-02-25 01:31:55 +03:00
nl = list_item ( vgh , struct name_list ) ;
2002-04-24 22:20:51 +04:00
if ( ! ( vg = vg_read ( fmt - > cmd , nl - > name ) ) ) {
log_error ( " format_text: _get_pvs failed to read VG %s " ,
nl - > name ) ;
continue ;
}
/* FIXME Use temp hash! */
list_iterate ( pvh , & vg - > pvs ) {
pvl = list_item ( pvh , struct pv_list ) ;
/* If in use, remove from list of orphans */
list_iterate ( rh , results ) {
rhl = list_item ( rh , struct pv_list ) ;
if ( id_equal ( & rhl - > pv - > id , & pvl - > pv - > id ) ) {
if ( * rhl - > pv - > vg_name )
log_err ( " PV %s in two VGs "
" %s and %s " ,
dev_name ( rhl - > pv - > dev ) ,
rhl - > pv - > vg_name ,
vg - > name ) ;
else
memcpy ( & rhl - > pv , & pvl - > pv ,
sizeof ( struct
physical_volume ) ) ;
2002-02-25 01:31:55 +03:00
}
}
2002-02-22 14:44:56 +03:00
}
}
2002-04-24 22:20:51 +04:00
pool_free ( fmt - > cmd - > mem , names ) ;
return results ;
2002-02-22 14:44:56 +03:00
}
2002-04-24 22:20:51 +04:00
static int _pv_write ( struct format_instance * fi , struct physical_volume * pv ,
void * mdl )
2002-02-22 14:44:56 +03:00
{
2002-04-24 22:20:51 +04:00
/* No on-disk PV structure change required! */
/* FIXME vgcache could be wrong */
return 1 ;
//return (fi->fmt->cmd->fmt1->ops->pv_write(fi, pv, NULL));
/*** FIXME Not required?
2002-02-25 01:31:55 +03:00
struct volume_group * vg ;
2002-02-22 14:44:56 +03:00
struct list * pvh ;
vg = _vg_read ( fi , pv - > vg_name ) ;
2002-04-24 22:20:51 +04:00
// Find the PV in this VG
2002-02-22 14:44:56 +03:00
if ( vg ) {
2002-02-25 01:31:55 +03:00
list_iterate ( pvh , & vg - > pvs ) {
struct pv_list * vgpv = list_item ( pvh , struct pv_list ) ;
if ( id_equal ( & pv - > id , & vgpv - > pv - > id ) ) {
vgpv - > pv - > status = pv - > status ;
vgpv - > pv - > size = pv - > size ;
2002-04-24 22:20:51 +04:00
// Not sure if it's worth doing these
2002-02-25 01:31:55 +03:00
vgpv - > pv - > pe_size = pv - > pe_size ;
vgpv - > pv - > pe_count = pv - > pe_count ;
vgpv - > pv - > pe_start = pv - > pe_start ;
2002-04-24 22:20:51 +04:00
vgpv - > pv - > pe_alloc_count = pv - > pe_alloc_count ;
2002-02-25 01:31:55 +03:00
2002-04-24 22:20:51 +04:00
// Write it back
2002-02-25 01:31:55 +03:00
_vg_write ( fi , vg ) ;
2002-04-24 22:20:51 +04:00
pool_free ( fi - > fmt - > cmd - > mem , vg ) ;
2002-02-25 01:31:55 +03:00
return 1 ;
}
2002-02-22 14:44:56 +03:00
}
2002-04-24 22:20:51 +04:00
pool_free ( fi - > fmt - > cmd - > mem , vg ) ;
2002-02-22 14:44:56 +03:00
}
2002-04-24 22:20:51 +04:00
// Can't handle PVs not in a VG
2002-02-22 14:44:56 +03:00
return 0 ;
2002-04-24 22:20:51 +04:00
* * */
2002-02-22 14:44:56 +03:00
}
2002-04-24 22:20:51 +04:00
static int _pv_read ( struct format_type * fmt , const char * pv_name ,
struct physical_volume * pv )
2002-02-22 14:44:56 +03:00
{
2002-04-24 22:20:51 +04:00
struct pv_list * pvl ;
2002-02-22 14:44:56 +03:00
struct list * vgh ;
struct list * pvh ;
2002-04-24 22:20:51 +04:00
struct list * names = pool_alloc ( fmt - > cmd - > mem , sizeof ( * names ) ) ;
struct name_list * nl ;
struct volume_group * vg ;
struct id * id ;
/* FIXME Push up to pv_read */
if ( ! ( id = uuid_map_lookup_label ( fmt - > cmd - > mem , fmt - > cmd - > um , pv_name ) ) ) {
stack ;
return 0 ;
}
list_init ( names ) ;
if ( ! _get_vgs ( fmt , names ) ) {
stack ;
return 0 ;
}
2002-02-22 14:44:56 +03:00
2002-04-24 22:20:51 +04:00
list_iterate ( vgh , names ) {
2002-02-25 01:31:55 +03:00
nl = list_item ( vgh , struct name_list ) ;
2002-04-24 22:20:51 +04:00
if ( ! ( vg = vg_read ( fmt - > cmd , nl - > name ) ) ) {
log_error ( " format_text: _pv_read failed to read VG %s " ,
nl - > name ) ;
return 0 ;
}
list_iterate ( pvh , & vg - > pvs ) {
pvl = list_item ( pvh , struct pv_list ) ;
if ( id_equal ( & pvl - > pv - > id , id ) ) {
memcpy ( pv , pvl - > pv , sizeof ( * pv ) ) ;
break ;
2002-02-22 14:44:56 +03:00
}
}
}
2002-04-24 22:20:51 +04:00
pool_free ( fmt - > cmd - > mem , names ) ;
return 1 ;
2002-02-22 14:44:56 +03:00
}
2002-04-24 22:20:51 +04:00
static void _destroy_instance ( struct format_instance * fid )
2001-11-21 12:20:05 +03:00
{
2002-04-24 22:20:51 +04:00
return ;
}
static void _free_dirs ( struct list * dir_list )
{
struct list * dl , * tmp ;
list_iterate_safe ( dl , tmp , dir_list ) {
list_del ( dl ) ;
dbg_free ( dl ) ;
}
}
static void _destroy ( struct format_type * fmt )
{
if ( fmt - > private ) {
_free_dirs ( ( struct list * ) fmt - > private ) ;
dbg_free ( fmt - > private ) ;
}
dbg_free ( fmt ) ;
}
static struct format_instance * _create_text_instance ( struct format_type * fmt ,
const char * vgname ,
void * context )
{
struct format_instance * fid ;
struct metadata_area * mda ;
struct dir_list * dl ;
struct list * dlh , * dir_list ;
char path [ PATH_MAX ] ;
if ( ! ( fid = pool_alloc ( fmt - > cmd - > mem , sizeof ( * fid ) ) ) ) {
log_error ( " Couldn't allocate format instance object. " ) ;
return NULL ;
}
fid - > fmt = fmt ;
list_init ( & fid - > metadata_areas ) ;
if ( ! vgname ) {
if ( ! ( mda = pool_alloc ( fmt - > cmd - > mem , sizeof ( * mda ) ) ) ) {
stack ;
return NULL ;
}
mda - > metadata_locn = context ;
list_add ( & fid - > metadata_areas , & mda - > list ) ;
} else {
dir_list = ( struct list * ) fmt - > private ;
list_iterate ( dlh , dir_list ) {
dl = list_item ( dlh , struct dir_list ) ;
if ( lvm_snprintf ( path , PATH_MAX , " %s/%s " ,
dl - > dir , vgname ) < 0 ) {
log_error ( " Name too long %s/%s " , dl - > dir ,
vgname ) ;
return NULL ;
}
context = create_text_context ( fmt , path , NULL ) ;
if ( ! ( mda = pool_alloc ( fmt - > cmd - > mem , sizeof ( * mda ) ) ) ) {
stack ;
return NULL ;
}
mda - > metadata_locn = context ;
list_add ( & fid - > metadata_areas , & mda - > list ) ;
}
}
return fid ;
2002-01-15 20:37:23 +03:00
2002-04-24 22:20:51 +04:00
}
void * create_text_context ( struct format_type * fmt , const char * path ,
const char * desc )
{
struct text_context * tc ;
char * tmp ;
if ( ( tmp = strstr ( path , " .tmp " ) ) & & ( tmp = = path + strlen ( path ) - 4 ) ) {
log_error ( " %s: Volume group filename may not end in .tmp " ,
path ) ;
return NULL ;
}
if ( ! ( tc = pool_alloc ( fmt - > cmd - > mem , sizeof ( * tc ) ) ) ) {
stack ;
return NULL ;
}
if ( ! ( tc - > path_live = pool_strdup ( fmt - > cmd - > mem , path ) ) ) {
stack ;
goto no_mem ;
}
if ( ! ( tc - > path_edit = pool_alloc ( fmt - > cmd - > mem , strlen ( path ) + 5 ) ) ) {
stack ;
goto no_mem ;
}
sprintf ( tc - > path_edit , " %s.tmp " , path ) ;
if ( ! desc )
desc = " " ;
if ( ! ( tc - > desc = pool_strdup ( fmt - > cmd - > mem , desc ) ) ) {
stack ;
goto no_mem ;
}
return ( void * ) tc ;
no_mem :
pool_free ( fmt - > cmd - > mem , tc ) ;
log_err ( " Couldn't allocate text format context object. " ) ;
return NULL ;
2001-11-21 12:20:05 +03:00
}
static struct format_handler _text_handler = {
2002-02-25 01:31:55 +03:00
get_vgs : _get_vgs ,
get_pvs : _get_pvs ,
pv_read : _pv_read ,
pv_setup : _pv_setup ,
pv_write : _pv_write ,
2002-04-24 22:20:51 +04:00
pv_commit : _pv_commit ,
2002-02-25 01:31:55 +03:00
vg_setup : _vg_setup ,
lv_setup : _lv_setup ,
vg_read : _vg_read ,
vg_write : _vg_write ,
2002-04-24 22:20:51 +04:00
vg_remove : _vg_remove ,
vg_commit : _vg_commit ,
create_instance : _create_text_instance ,
destroy_instance : _destroy_instance ,
2002-02-25 01:31:55 +03:00
destroy : _destroy
2001-11-21 12:20:05 +03:00
} ;
2002-04-24 22:20:51 +04:00
static int _add_dir ( const char * dir , struct list * dir_list )
2001-11-21 12:20:05 +03:00
{
2002-04-24 22:20:51 +04:00
struct dir_list * dl ;
2001-11-21 12:20:05 +03:00
2002-04-24 22:20:51 +04:00
if ( create_dir ( dir ) ) {
if ( ! ( dl = dbg_malloc ( sizeof ( struct list ) + strlen ( dir ) + 1 ) ) ) {
log_error ( " _add_dir allocation failed " ) ;
return 0 ;
}
strcpy ( dl - > dir , dir ) ;
list_add ( dir_list , & dl - > list ) ;
return 1 ;
2001-11-21 12:20:05 +03:00
}
2002-04-24 22:20:51 +04:00
return 0 ;
}
2002-02-08 14:13:47 +03:00
2002-04-24 22:20:51 +04:00
struct format_type * create_text_format ( struct cmd_context * cmd )
{
struct format_type * fmt ;
struct config_node * cn ;
struct config_value * cv ;
struct list * dir_list ;
if ( ! ( fmt = dbg_malloc ( sizeof ( * fmt ) ) ) ) {
2002-02-08 14:13:47 +03:00
stack ;
2002-04-24 22:20:51 +04:00
return NULL ;
2001-11-21 12:20:05 +03:00
}
2002-04-24 22:20:51 +04:00
fmt - > cmd = cmd ;
fmt - > ops = & _text_handler ;
fmt - > name = FMT_TEXT_NAME ;
fmt - > features = FMT_SEGMENTS ;
if ( ! ( dir_list = dbg_malloc ( sizeof ( struct list ) ) ) ) {
log_error ( " Failed to allocate dir_list " ) ;
return NULL ;
2002-01-15 20:37:23 +03:00
}
2002-04-24 22:20:51 +04:00
list_init ( dir_list ) ;
fmt - > private = ( void * ) dir_list ;
2002-01-15 20:37:23 +03:00
2002-04-24 22:20:51 +04:00
if ( ! ( cn = find_config_node ( cmd - > cf - > root , " metadata/dirs " , ' / ' ) ) ) {
log_verbose ( " metadata/dirs not in config file: Defaulting "
" to /etc/lvm/metadata " ) ;
_add_dir ( " /etc/lvm/metadata " , dir_list ) ;
return fmt ;
}
2001-11-21 12:20:05 +03:00
2002-04-24 22:20:51 +04:00
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
if ( cv - > type ! = CFG_STRING ) {
log_error ( " Invalid string in config file: "
" metadata/dirs " ) ;
goto err ;
}
2002-02-08 14:13:47 +03:00
2002-04-24 22:20:51 +04:00
if ( ! _add_dir ( cv - > v . str , dir_list ) ) {
log_error ( " Failed to add %s to internal device cache " ,
cv - > v . str ) ;
goto err ;
}
}
2002-02-08 14:13:47 +03:00
2002-04-24 22:20:51 +04:00
return fmt ;
2002-02-08 14:13:47 +03:00
2002-04-24 22:20:51 +04:00
err :
_free_dirs ( dir_list ) ;
2002-02-08 14:13:47 +03:00
2002-04-24 22:20:51 +04:00
dbg_free ( fmt ) ;
2002-02-08 14:13:47 +03:00
return NULL ;
2001-11-21 12:20:05 +03:00
}