2001-11-09 11:48:22 +03:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the LGPL .
*/
2002-02-11 23:50:53 +03:00
# include "fs.h"
# include "log.h"
# include "toolcontext.h"
2002-02-26 14:49:17 +03:00
# include "lvm-string.h"
2002-02-11 23:50:53 +03:00
2001-11-12 14:48:31 +03:00
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
2001-11-09 11:48:22 +03:00
# include <unistd.h>
2001-11-12 14:48:31 +03:00
# include <limits.h>
# include <stdio.h>
# include <string.h>
2001-11-21 22:32:35 +03:00
# include <libdevmapper.h>
2002-03-11 23:43:58 +03:00
# include <dirent.h>
2002-01-11 02:21:07 +03:00
2001-11-09 11:48:22 +03:00
/*
* Lazy programmer : I ' m just going to always try
* and create / remove the vg directory , and not say
* anything if it fails .
*/
2002-01-21 14:06:32 +03:00
static int _mk_dir ( struct volume_group * vg )
2001-11-09 11:48:22 +03:00
{
char vg_path [ PATH_MAX ] ;
2002-02-26 19:08:22 +03:00
if ( lvm_snprintf ( vg_path , sizeof ( vg_path ) , " %s%s " ,
2002-02-26 14:49:17 +03:00
vg - > cmd - > dev_dir , vg - > name ) = = - 1 ) {
log_error ( " Couldn't construct name of volume "
" group directory. " ) ;
2002-01-21 14:06:32 +03:00
return 0 ;
}
2001-12-05 02:20:27 +03:00
log_very_verbose ( " Creating directory %s " , vg_path ) ;
2001-11-09 11:48:22 +03:00
mkdir ( vg_path , 0555 ) ;
2002-01-21 14:06:32 +03:00
return 1 ;
2001-11-09 11:48:22 +03:00
}
2002-03-11 23:43:58 +03:00
static int _is_empty_dir ( const char * dir )
{
int i , count , r = 1 ;
struct dirent * * dirent ;
const char * name ;
count = scandir ( dir , & dirent , NULL , alphasort ) ;
if ( ! count )
return 1 ;
if ( count < 0 ) {
log_err ( " Couldn't scan directory '%s'. " , dir ) ;
return 0 ;
}
/*
* Scan the devices .
*/
for ( i = 0 ; i < count ; i + + ) {
name = dirent [ i ] - > d_name ;
/*
* Ignore dot files .
*/
if ( ! strcmp ( name , " . " ) | | ! strcmp ( name , " .. " ) )
continue ;
r = 0 ;
break ;
}
/*
* Free the directory entries .
*/
for ( i = 0 ; i < count ; i + + )
free ( dirent [ i ] ) ;
free ( dirent ) ;
return r ;
}
2002-01-21 14:06:32 +03:00
static int _rm_dir ( struct volume_group * vg )
2001-11-09 11:48:22 +03:00
{
char vg_path [ PATH_MAX ] ;
2002-02-26 19:08:22 +03:00
if ( lvm_snprintf ( vg_path , sizeof ( vg_path ) , " %s%s " ,
2002-02-26 14:49:17 +03:00
vg - > cmd - > dev_dir , vg - > name ) = = - 1 ) {
log_error ( " Couldn't construct name of volume "
" group directory. " ) ;
2002-01-21 14:06:32 +03:00
return 0 ;
}
2001-12-05 02:20:27 +03:00
log_very_verbose ( " Removing directory %s " , vg_path ) ;
2002-03-11 23:43:58 +03:00
if ( _is_empty_dir ( vg_path ) )
rmdir ( vg_path ) ;
2002-01-21 14:06:32 +03:00
return 1 ;
2001-11-09 11:48:22 +03:00
}
2002-02-26 14:49:17 +03:00
static int _mk_link ( struct logical_volume * lv , const char * dev )
2001-11-09 11:48:22 +03:00
{
char lv_path [ PATH_MAX ] , link_path [ PATH_MAX ] ;
2002-01-22 22:58:37 +03:00
struct stat buf ;
2001-11-09 11:48:22 +03:00
2002-02-26 19:08:22 +03:00
if ( lvm_snprintf ( lv_path , sizeof ( lv_path ) , " %s%s/%s " ,
2002-02-26 14:49:17 +03:00
lv - > vg - > cmd - > dev_dir , lv - > vg - > name , lv - > name ) = = - 1 ) {
log_error ( " Couldn't create source pathname for "
" logical volume link %s " , lv - > name ) ;
2002-01-21 14:06:32 +03:00
return 0 ;
}
2002-02-26 14:49:17 +03: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 14:06:32 +03:00
return 0 ;
}
2001-11-12 14:42:29 +03:00
2002-02-26 14:49:17 +03:00
if ( ! lstat ( lv_path , & buf ) ) {
2002-01-22 22:58:37 +03:00
if ( ! S_ISLNK ( buf . st_mode ) ) {
log_error ( " Symbolic link %s not created: file exists " ,
link_path ) ;
return 0 ;
}
2002-02-26 14:49:17 +03:00
if ( unlink ( lv_path ) < 0 ) {
log_sys_error ( " unlink " , lv_path ) ;
2002-01-22 22:58:37 +03:00
return 0 ;
}
}
2002-02-26 19:08:22 +03:00
log_very_verbose ( " Linking %s -> %s " , lv_path , link_path ) ;
2002-02-26 14:49:17 +03:00
if ( symlink ( link_path , lv_path ) < 0 ) {
log_sys_error ( " symlink " , lv_path ) ;
2001-11-12 14:42:29 +03:00
return 0 ;
}
return 1 ;
}
2002-01-11 02:21:07 +03:00
static int _rm_link ( struct logical_volume * lv , const char * lv_name )
2001-11-12 14:42:29 +03:00
{
2002-01-25 23:17:44 +03:00
struct stat buf ;
2002-02-26 14:49:17 +03:00
char lv_path [ PATH_MAX ] ;
2001-11-12 14:42:29 +03:00
2002-02-26 19:08:22 +03:00
if ( lvm_snprintf ( lv_path , sizeof ( lv_path ) , " %s%s/%s " ,
2002-02-26 14:49:17 +03:00
lv - > vg - > cmd - > dev_dir , lv - > vg - > name , lv_name ) = = - 1 ) {
2002-01-28 00:30:47 +03:00
log_error ( " Couldn't determine link pathname. " ) ;
2002-01-21 14:06:32 +03:00
return 0 ;
}
2001-11-12 14:42:29 +03:00
2002-02-26 14:49:17 +03:00
log_very_verbose ( " Removing link %s " , lv_path ) ;
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 23:17:44 +03:00
}
2002-02-26 14:49:17 +03:00
if ( unlink ( lv_path ) < 0 ) {
log_sys_error ( " unlink " , lv_path ) ;
2001-11-12 14:42:29 +03:00
return 0 ;
}
return 1 ;
2001-11-09 11:48:22 +03:00
}
2002-02-26 14:49:17 +03:00
int fs_add_lv ( struct logical_volume * lv , const char * dev )
2001-11-09 11:48:22 +03:00
{
2002-01-21 14:06:32 +03:00
if ( ! _mk_dir ( lv - > vg ) | |
2002-02-26 14:49:17 +03:00
! _mk_link ( lv , dev ) ) {
2001-11-09 11:48:22 +03:00
stack ;
return 0 ;
}
return 1 ;
}
int fs_del_lv ( struct logical_volume * lv )
{
2002-02-26 14:49:17 +03:00
if ( ! _rm_link ( lv , lv - > name ) | |
2002-01-21 14:06:32 +03:00
! _rm_dir ( lv - > vg ) ) {
2001-11-09 11:48:22 +03:00
stack ;
return 0 ;
}
return 1 ;
}
2002-02-26 14:49:17 +03:00
int fs_rename_lv ( struct logical_volume * lv ,
const char * dev , const char * old_name )
2002-01-11 02:21:07 +03:00
{
if ( ! _rm_link ( lv , old_name ) )
stack ;
2002-02-26 14:49:17 +03:00
if ( ! _mk_link ( lv , dev ) )
2002-01-11 02:21:07 +03:00
stack ;
return 1 ;
}