2001-11-09 08:48:22 +00:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the LGPL .
*/
2002-11-18 14:01:16 +00:00
# include "lib.h"
2002-02-11 20:50:53 +00:00
# include "fs.h"
# include "toolcontext.h"
2002-02-26 11:49:17 +00:00
# include "lvm-string.h"
2002-03-11 22:23:24 +00:00
# include "lvm-file.h"
2002-02-11 20:50:53 +00:00
2001-11-12 11:48:31 +00:00
# include <sys/stat.h>
# include <fcntl.h>
2001-11-09 08:48:22 +00:00
# include <unistd.h>
2001-11-12 11:48:31 +00:00
# include <limits.h>
2003-01-03 13:50:47 +00:00
# include <dirent.h>
2001-11-21 19:32:35 +00:00
# include <libdevmapper.h>
2002-01-10 23:21:07 +00:00
2002-01-21 11:06:32 +00:00
static int _mk_dir ( struct volume_group * vg )
2001-11-09 08:48:22 +00:00
{
char vg_path [ PATH_MAX ] ;
2002-02-26 16:08:22 +00:00
if ( lvm_snprintf ( vg_path , sizeof ( vg_path ) , " %s%s " ,
2002-02-26 11:49:17 +00:00
vg - > cmd - > dev_dir , vg - > name ) = = - 1 ) {
log_error ( " Couldn't construct name of volume "
" group directory. " ) ;
2002-01-21 11:06:32 +00:00
return 0 ;
}
2001-12-04 23:20:27 +00:00
2002-03-11 22:23:24 +00:00
if ( dir_exists ( vg_path ) )
2002-03-11 20:43:58 +00:00
return 1 ;
2002-03-11 22:23:24 +00:00
log_very_verbose ( " Creating directory %s " , vg_path ) ;
if ( mkdir ( vg_path , 0555 ) ) {
log_sys_error ( " mkdir " , vg_path ) ;
2002-03-11 20:43:58 +00:00
return 0 ;
}
2002-03-11 22:23:24 +00:00
return 1 ;
2002-03-11 20:43:58 +00:00
}
2002-01-21 11:06:32 +00:00
static int _rm_dir ( struct volume_group * vg )
2001-11-09 08:48:22 +00:00
{
char vg_path [ PATH_MAX ] ;
2002-02-26 16:08:22 +00:00
if ( lvm_snprintf ( vg_path , sizeof ( vg_path ) , " %s%s " ,
2002-02-26 11:49:17 +00:00
vg - > cmd - > dev_dir , vg - > name ) = = - 1 ) {
log_error ( " Couldn't construct name of volume "
" group directory. " ) ;
2002-01-21 11:06:32 +00:00
return 0 ;
}
2001-12-04 23:20:27 +00:00
log_very_verbose ( " Removing directory %s " , vg_path ) ;
2002-03-11 20:43:58 +00:00
2002-03-11 22:23:24 +00:00
if ( is_empty_dir ( vg_path ) )
2002-03-11 20:43:58 +00:00
rmdir ( vg_path ) ;
2002-01-21 11:06:32 +00:00
return 1 ;
2001-11-09 08:48:22 +00:00
}
2003-01-03 13:50:47 +00:00
static void _rm_blks ( const char * dir )
{
const char * name ;
char path [ PATH_MAX ] ;
struct dirent * dirent ;
struct stat buf ;
DIR * d ;
if ( ! ( d = opendir ( dir ) ) ) {
log_sys_error ( " opendir " , dir ) ;
return ;
}
while ( ( dirent = readdir ( d ) ) ) {
name = dirent - > d_name ;
if ( ! strcmp ( name , " . " ) | | ! strcmp ( name , " .. " ) )
continue ;
if ( lvm_snprintf ( path , sizeof ( path ) , " %s/%s " , dir , name ) = = - 1 ) {
log_error ( " Couldn't create path for %s " , name ) ;
continue ;
}
if ( ! lstat ( path , & buf ) ) {
if ( ! S_ISBLK ( buf . st_mode ) )
continue ;
log_very_verbose ( " Removing %s " , path ) ;
if ( unlink ( path ) < 0 )
log_sys_error ( " unlink " , path ) ;
}
}
}
2002-02-26 11:49:17 +00:00
static int _mk_link ( struct logical_volume * lv , const char * dev )
2001-11-09 08:48:22 +00:00
{
2003-01-03 13:50:47 +00:00
char lv_path [ PATH_MAX ] , link_path [ PATH_MAX ] , lvm1_group_path [ PATH_MAX ] ;
char vg_path [ PATH_MAX ] ;
2002-01-22 19:58:37 +00:00
struct stat buf ;
2001-11-09 08:48:22 +00:00
2003-01-03 13:50:47 +00:00
if ( lvm_snprintf ( vg_path , sizeof ( vg_path ) , " %s%s " ,
lv - > vg - > cmd - > dev_dir , lv - > vg - > name ) = = - 1 ) {
log_error ( " Couldn't create path for volume group dir %s " ,
lv - > vg - > name ) ;
return 0 ;
}
if ( lvm_snprintf ( lv_path , sizeof ( lv_path ) , " %s/%s " , vg_path ,
lv - > name ) = = - 1 ) {
2002-02-26 11:49:17 +00:00
log_error ( " Couldn't create source pathname for "
" logical volume link %s " , lv - > name ) ;
2002-01-21 11:06:32 +00:00
return 0 ;
}
2002-02-26 11:49:17 +00:00
if ( lvm_snprintf ( link_path , sizeof ( link_path ) , " %s/%s " ,
dm_dir ( ) , dev ) = = - 1 ) {
log_error ( " Couldn't create destination pathname for "
" logical volume link for %s " , lv - > name ) ;
2002-01-21 11:06:32 +00:00
return 0 ;
}
2001-11-12 11:42:29 +00:00
2003-01-03 13:50:47 +00:00
if ( lvm_snprintf ( lvm1_group_path , sizeof ( lvm1_group_path ) , " %s/group " ,
vg_path ) = = - 1 ) {
log_error ( " Couldn't create pathname for LVM1 group file for %s " ,
lv - > vg - > name ) ;
return 0 ;
}
/* To reach this point, the VG must have been locked.
* As locking fails if the VG is active under LVM1 , it ' s
* now safe to remove any LVM1 devices we find here
* ( as well as any existing LVM2 symlink ) . */
if ( ! lstat ( lvm1_group_path , & buf ) ) {
if ( ! S_ISCHR ( buf . st_mode ) ) {
log_error ( " Non-LVM1 character device found at %s " ,
lvm1_group_path ) ;
} else {
_rm_blks ( vg_path ) ;
log_very_verbose ( " Removing %s " , lvm1_group_path ) ;
if ( unlink ( lvm1_group_path ) < 0 )
log_sys_error ( " unlink " , lvm1_group_path ) ;
}
}
2002-02-26 11:49:17 +00:00
if ( ! lstat ( lv_path , & buf ) ) {
2003-01-03 13:50:47 +00:00
if ( ! S_ISLNK ( buf . st_mode ) & & ! S_ISBLK ( buf . st_mode ) ) {
2002-01-22 19:58:37 +00:00
log_error ( " Symbolic link %s not created: file exists " ,
link_path ) ;
return 0 ;
}
2002-02-26 11:49:17 +00:00
2003-01-03 13:50:47 +00:00
log_very_verbose ( " Removing %s " , lv_path ) ;
2002-02-26 11:49:17 +00:00
if ( unlink ( lv_path ) < 0 ) {
log_sys_error ( " unlink " , lv_path ) ;
2002-01-22 19:58:37 +00:00
return 0 ;
}
}
2002-02-26 16:08:22 +00:00
log_very_verbose ( " Linking %s -> %s " , lv_path , link_path ) ;
2002-02-26 11:49:17 +00:00
if ( symlink ( link_path , lv_path ) < 0 ) {
log_sys_error ( " symlink " , lv_path ) ;
2001-11-12 11:42:29 +00:00
return 0 ;
}
return 1 ;
}
2002-01-10 23:21:07 +00:00
static int _rm_link ( struct logical_volume * lv , const char * lv_name )
2001-11-12 11:42:29 +00:00
{
2002-01-25 20:17:44 +00:00
struct stat buf ;
2002-02-26 11:49:17 +00:00
char lv_path [ PATH_MAX ] ;
2001-11-12 11:42:29 +00:00
2002-02-26 16:08:22 +00:00
if ( lvm_snprintf ( lv_path , sizeof ( lv_path ) , " %s%s/%s " ,
2002-02-26 11:49:17 +00:00
lv - > vg - > cmd - > dev_dir , lv - > vg - > name , lv_name ) = = - 1 ) {
2002-01-27 21:30:47 +00:00
log_error ( " Couldn't determine link pathname. " ) ;
2002-01-21 11:06:32 +00:00
return 0 ;
}
2001-11-12 11:42:29 +00:00
2002-02-26 11:49:17 +00:00
if ( lstat ( lv_path , & buf ) | | ! S_ISLNK ( buf . st_mode ) ) {
log_error ( " %s not symbolic link - not removing " , lv_path ) ;
return 0 ;
2002-01-25 20:17:44 +00:00
}
2002-02-26 11:49:17 +00:00
2003-01-03 13:50:47 +00:00
log_very_verbose ( " Removing link %s " , lv_path ) ;
2002-02-26 11:49:17 +00:00
if ( unlink ( lv_path ) < 0 ) {
log_sys_error ( " unlink " , lv_path ) ;
2001-11-12 11:42:29 +00:00
return 0 ;
}
return 1 ;
2001-11-09 08:48:22 +00:00
}
2002-02-26 11:49:17 +00:00
int fs_add_lv ( struct logical_volume * lv , const char * dev )
2001-11-09 08:48:22 +00:00
{
2002-03-18 23:25:50 +00:00
if ( ! _mk_dir ( lv - > vg ) | | ! _mk_link ( lv , dev ) ) {
2001-11-09 08:48:22 +00:00
stack ;
return 0 ;
}
return 1 ;
}
int fs_del_lv ( struct logical_volume * lv )
{
2002-03-18 23:25:50 +00:00
if ( ! _rm_link ( lv , lv - > name ) | | ! _rm_dir ( lv - > vg ) ) {
2001-11-09 08:48:22 +00:00
stack ;
return 0 ;
}
return 1 ;
}
2002-03-18 23:25:50 +00:00
/* FIXME Use rename() */
2002-02-26 11:49:17 +00:00
int fs_rename_lv ( struct logical_volume * lv ,
const char * dev , const char * old_name )
2002-01-10 23:21:07 +00:00
{
2002-03-18 23:25:50 +00:00
if ( old_name & & ! _rm_link ( lv , old_name ) )
2002-01-10 23:21:07 +00:00
stack ;
2002-02-26 11:49:17 +00:00
if ( ! _mk_link ( lv , dev ) )
2002-01-10 23:21:07 +00:00
stack ;
return 1 ;
}