2001-11-21 12:20:05 +03:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* 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-01-10 19:48:28 +03:00
# include "dbg_malloc.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>
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-01-15 20:37:23 +03:00
struct text_c {
char * path ;
2002-02-08 14:13:47 +03:00
char * desc ;
2002-01-15 20:37:23 +03:00
struct uuid_map * um ;
} ;
2002-01-07 12:05:31 +03:00
static void _not_written ( const char * cmd )
2001-11-21 12:20:05 +03:00
{
2002-01-07 12:05:31 +03:00
log_err ( " The text format is lacking an implementation for '%s' " , cmd ) ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +03:00
static struct list * _get_vgs ( struct format_instance * fi )
2001-11-21 12:20:05 +03:00
{
2002-01-07 12:05:31 +03:00
_not_written ( " _get_vgs " ) ;
return NULL ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +03:00
static struct list * _get_pvs ( struct format_instance * fi )
2001-11-21 12:20:05 +03:00
{
2002-01-07 12:05:31 +03:00
_not_written ( " _get_vgs " ) ;
return NULL ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +03:00
static struct physical_volume * _pv_read ( struct format_instance * fi ,
const char * pv_name )
2001-11-21 12:20:05 +03:00
{
2002-01-07 12:05:31 +03:00
_not_written ( " _get_vgs " ) ;
return NULL ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +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-01-07 12:05:31 +03:00
_not_written ( " _get_vgs " ) ;
2002-01-07 12:16:20 +03:00
return 0 ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +03:00
static int _pv_write ( struct format_instance * fi , struct physical_volume * pv )
2001-11-21 12:20:05 +03:00
{
2002-01-07 12:05:31 +03:00
_not_written ( " _get_vgs " ) ;
2002-01-07 12:16:20 +03:00
return 0 ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +03:00
static int _vg_setup ( struct format_instance * fi , struct volume_group * vg )
2001-11-21 12:20:05 +03:00
{
2002-01-07 12:05:31 +03:00
_not_written ( " _get_vgs " ) ;
2002-01-07 12:16:20 +03:00
return 0 ;
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 ,
const char * vg_name )
2001-11-21 12:20:05 +03:00
{
2002-01-15 20:37:23 +03:00
struct text_c * tc = ( struct text_c * ) fi - > private ;
2002-01-10 17:27:47 +03:00
struct volume_group * vg ;
2002-01-15 20:37:23 +03:00
if ( ! ( vg = text_vg_import ( fi - > cmd , tc - > path , tc - > um ) ) ) {
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 .
*/
if ( strcmp ( vg_name , vg - > name ) ) {
pool_free ( fi - > cmd - > mem , vg ) ;
log_err ( " '%s' does not contain volume group '%s'. " ,
2002-01-15 20:37:23 +03:00
tc - > path , vg_name ) ;
2002-01-10 17:27:47 +03:00
return NULL ;
}
return vg ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +03:00
static int _vg_write ( struct format_instance * fi , struct volume_group * vg )
2001-11-21 12:20:05 +03:00
{
2002-01-15 20:37:23 +03:00
struct text_c * tc = ( struct text_c * ) fi - > private ;
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-01-15 20:37:23 +03:00
slash = rindex ( tc - > path , ' / ' ) ;
2001-11-21 12:20:05 +03:00
2002-01-09 22:16:48 +03:00
if ( slash = = 0 )
strcpy ( temp_dir , " . " ) ;
2002-01-15 20:37:23 +03:00
else if ( slash - tc - > path < PATH_MAX ) {
strncpy ( temp_dir , tc - > path , slash - tc - > path ) ;
temp_dir [ slash - tc - > path ] = ' \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 ;
}
if ( ! create_temp_name ( temp_dir , temp_file , sizeof ( temp_file ) , & fd ) ) {
log_err ( " Couldn't create temporary text file name. " ) ;
return 0 ;
}
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-01-09 22:16:48 +03:00
if ( fclose ( fp ) ) {
2002-01-15 20:37:23 +03:00
log_sys_error ( " fclose " , tc - > path ) ;
2002-01-07 12:05:31 +03:00
return 0 ;
}
2001-11-21 12:20:05 +03:00
2002-01-15 20:37:23 +03:00
if ( rename ( temp_file , tc - > path ) ) {
log_error ( " %s: rename to %s failed: %s " , temp_file , tc - > path ,
2002-01-09 22:16:48 +03:00
strerror ( errno ) ) ;
return 0 ;
}
2002-01-07 12:05:31 +03:00
return 1 ;
2001-11-21 12:20:05 +03:00
}
2002-01-07 14:12:11 +03:00
static void _destroy ( struct format_instance * fi )
2001-11-21 12:20:05 +03:00
{
2002-01-15 20:37:23 +03:00
struct text_c * tc = ( struct text_c * ) fi - > private ;
dbg_free ( tc - > path ) ;
dbg_free ( tc ) ;
2002-01-10 17:27:47 +03:00
dbg_free ( fi ) ;
2001-11-21 12:20:05 +03:00
}
static struct format_handler _text_handler = {
get_vgs : _get_vgs ,
get_pvs : _get_pvs ,
pv_read : _pv_read ,
pv_setup : _pv_setup ,
pv_write : _pv_write ,
vg_setup : _vg_setup ,
vg_read : _vg_read ,
vg_write : _vg_write ,
destroy : _destroy
} ;
2002-01-07 12:05:31 +03:00
struct format_instance * text_format_create ( struct cmd_context * cmd ,
2002-01-15 20:37:23 +03:00
const char * file ,
2002-02-08 14:13:47 +03:00
struct uuid_map * um ,
const char * desc )
2001-11-21 12:20:05 +03:00
{
struct format_instance * fi ;
2002-02-08 14:13:47 +03:00
char * path , * d ;
2002-01-15 20:37:23 +03:00
struct text_c * tc ;
2001-11-21 12:20:05 +03:00
2002-01-10 17:27:47 +03:00
if ( ! ( fi = dbg_malloc ( sizeof ( * fi ) ) ) ) {
2002-02-08 14:13:47 +03:00
stack ;
goto no_mem ;
2001-11-21 12:20:05 +03:00
}
2002-01-10 17:27:47 +03:00
if ( ! ( path = dbg_strdup ( file ) ) ) {
2002-02-08 14:13:47 +03:00
stack ;
goto no_mem ;
}
if ( ! ( d = dbg_strdup ( desc ) ) ) {
stack ;
goto no_mem ;
2001-11-21 12:20:05 +03:00
}
2002-01-15 20:37:23 +03:00
if ( ! ( tc = dbg_malloc ( sizeof ( * tc ) ) ) ) {
2002-02-08 14:13:47 +03:00
stack ;
goto no_mem ;
2002-01-15 20:37:23 +03:00
}
tc - > path = path ;
2002-02-08 14:13:47 +03:00
tc - > desc = d ;
2002-01-15 20:37:23 +03:00
tc - > um = um ;
2001-11-21 12:20:05 +03:00
fi - > cmd = cmd ;
2002-01-07 12:16:20 +03:00
fi - > ops = & _text_handler ;
2002-01-15 20:37:23 +03:00
fi - > private = tc ;
2001-11-21 12:20:05 +03:00
return fi ;
2002-02-08 14:13:47 +03:00
no_mem :
if ( fi )
dbg_free ( fi ) ;
if ( path )
dbg_free ( path ) ;
if ( d )
dbg_free ( path ) ;
log_err ( " Couldn't allocate text format object. " ) ;
return NULL ;
2001-11-21 12:20:05 +03:00
}