2001-11-09 08:48:22 +00:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the LGPL .
*/
2001-11-12 11:48:31 +00:00
# include <sys/types.h>
# 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>
# include <stdio.h>
# include <string.h>
# include "fs.h"
# include "log.h"
2001-11-09 08:48:22 +00:00
2001-11-12 17:21:25 +00:00
# include <devmapper/libdevmapper.h>
2001-11-09 08:48:22 +00:00
/*
2001-11-12 11:42:29 +00:00
* FIXME : copied straight from LVM1 .
2001-11-09 08:48:22 +00:00
*
* This should run through / proc / mounts once only ,
* storing devfs mount points in a hash table .
*/
static int _check_devfs ( const char * dev_prefix )
{
int r = 0 , len ;
2001-11-12 11:48:31 +00:00
char dir [ PATH_MAX ] , line [ 512 ] ;
2001-11-09 08:48:22 +00:00
char type [ 32 ] ;
FILE * mounts = NULL ;
if ( ! ( mounts = fopen ( " /proc/mounts " , " r " ) ) )
goto out ;
/* trim the trailing slash off the dir prefix, yuck */
len = strlen ( dev_prefix ) - 1 ;
while ( len & & dev_prefix [ len ] = = ' / ' )
len - - ;
while ( ! feof ( mounts ) ) {
fgets ( line , sizeof ( line ) - 1 , mounts ) ;
if ( sscanf ( line , " %*s %s %s %*s " , dir , type ) ! = 2 )
continue ;
if ( ! strcmp ( type , " devfs " ) & & ! strncmp ( dir , dev_prefix , len ) ) {
2001-11-12 11:48:31 +00:00
r = 1 ;
2001-11-09 08:48:22 +00:00
break ;
}
}
fclose ( mounts ) ;
out :
return r ;
}
2001-11-12 11:42:29 +00:00
void _build_lv_path ( char * buffer , size_t len , struct logical_volume * lv )
2001-11-09 08:48:22 +00:00
{
2001-11-13 16:14:54 +00:00
snprintf ( buffer , len , " %s%s/%s_%s " ,
2001-11-12 17:21:25 +00:00
lv - > vg - > cmd - > dev_dir , dm_dir ( ) , lv - > vg - > name , lv - > name ) ;
2001-11-12 11:42:29 +00:00
}
2001-11-09 08:48:22 +00:00
2001-11-12 11:42:29 +00:00
void _build_vg_path ( char * buffer , size_t len , struct volume_group * vg )
{
snprintf ( buffer , len , " %s/%s " , vg - > cmd - > dev_dir , vg - > name ) ;
}
2001-11-09 08:48:22 +00:00
2001-11-12 11:42:29 +00:00
void _build_link_path ( char * buffer , size_t len , struct logical_volume * lv )
{
2001-11-12 11:48:31 +00:00
snprintf ( buffer , len , " %s/%s/%s " , lv - > vg - > cmd - > dev_dir ,
lv - > vg - > name , lv - > name ) ;
2001-11-09 08:48:22 +00:00
}
2001-11-12 11:42:29 +00:00
static int _mk_node ( struct logical_volume * lv )
2001-11-09 08:48:22 +00:00
{
char lv_path [ PATH_MAX ] ;
2001-11-12 17:21:25 +00:00
char dm_path [ PATH_MAX ] ;
2001-11-09 08:48:22 +00:00
dev_t dev ;
2001-11-12 11:42:29 +00:00
const char * dev_dir = lv - > vg - > cmd - > dev_dir ;
2001-11-09 08:48:22 +00:00
2001-11-12 11:42:29 +00:00
if ( _check_devfs ( dev_dir ) )
2001-11-09 08:48:22 +00:00
return 1 ;
2001-11-12 17:21:25 +00:00
snprintf ( dm_path , PATH_MAX , " %s%s " , dev_dir , dm_dir ( ) ) ;
if ( mkdir ( dm_path , 0555 ) & & errno ! = EEXIST ) {
log_sys_error ( " mkdir " , dm_path ) ;
return 0 ;
}
2001-11-09 08:48:22 +00:00
2001-11-12 17:21:25 +00:00
_build_lv_path ( lv_path , sizeof ( lv_path ) , lv ) ;
2001-11-13 16:14:54 +00:00
2001-11-09 08:48:22 +00:00
if ( mknod ( lv_path , S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP , dev ) < 0 ) {
2001-11-12 17:21:25 +00:00
log_sys_error ( " mknod " , lv_path ) ;
2001-11-09 08:48:22 +00:00
return 0 ;
}
return 1 ;
}
2001-11-12 11:42:29 +00:00
static int _rm_node ( struct logical_volume * lv )
2001-11-09 08:48:22 +00:00
{
char lv_path [ PATH_MAX ] ;
2001-11-12 11:42:29 +00:00
const char * dev_dir = lv - > vg - > cmd - > dev_dir ;
2001-11-09 08:48:22 +00:00
2001-11-12 11:42:29 +00:00
if ( _check_devfs ( dev_dir ) )
2001-11-09 08:48:22 +00:00
return 1 ;
2001-11-12 11:42:29 +00:00
_build_lv_path ( lv_path , sizeof ( lv_path ) , lv ) ;
2001-11-09 08:48:22 +00:00
if ( unlink ( lv_path ) < 0 ) {
2001-11-12 17:21:25 +00:00
log_sys_error ( " unlink " , lv_path ) ;
2001-11-09 08:48:22 +00:00
return 0 ;
}
return 1 ;
}
/*
* Lazy programmer : I ' m just going to always try
* and create / remove the vg directory , and not say
* anything if it fails .
*/
2001-11-12 11:42:29 +00:00
static int _mk_dir ( struct volume_group * vg )
2001-11-09 08:48:22 +00:00
{
char vg_path [ PATH_MAX ] ;
2001-11-12 11:42:29 +00:00
_build_vg_path ( vg_path , sizeof ( vg_path ) , vg ) ;
2001-11-09 08:48:22 +00:00
mkdir ( vg_path , 0555 ) ;
return 1 ;
}
2001-11-12 11:42:29 +00:00
static int _rm_dir ( struct volume_group * vg )
2001-11-09 08:48:22 +00:00
{
char vg_path [ PATH_MAX ] ;
2001-11-12 11:42:29 +00:00
_build_vg_path ( vg_path , sizeof ( vg_path ) , vg ) ;
2001-11-09 08:48:22 +00:00
rmdir ( vg_path ) ;
return 1 ;
}
2001-11-12 11:42:29 +00:00
static int _mk_link ( struct logical_volume * lv )
2001-11-09 08:48:22 +00:00
{
char lv_path [ PATH_MAX ] , link_path [ PATH_MAX ] ;
2001-11-12 11:42:29 +00:00
_build_lv_path ( lv_path , sizeof ( lv_path ) , lv ) ;
_build_link_path ( link_path , sizeof ( link_path ) , lv ) ;
if ( symlink ( lv_path , link_path ) < 0 ) {
2001-11-12 17:21:25 +00:00
log_sys_error ( " symlink " , link_path ) ;
2001-11-12 11:42:29 +00:00
return 0 ;
}
return 1 ;
}
static int _rm_link ( struct logical_volume * lv )
{
char link_path [ PATH_MAX ] ;
_build_link_path ( link_path , sizeof ( link_path ) , lv ) ;
if ( unlink ( link_path ) < 0 ) {
2001-11-12 17:21:25 +00:00
log_sys_error ( " unlink " , link_path ) ;
2001-11-12 11:42:29 +00:00
return 0 ;
}
return 1 ;
2001-11-09 08:48:22 +00:00
}
2001-11-12 11:42:29 +00:00
int fs_add_lv ( struct logical_volume * lv )
2001-11-09 08:48:22 +00:00
{
2001-11-12 11:42:29 +00:00
if ( ! _mk_node ( lv ) ) {
2001-11-09 08:48:22 +00:00
stack ;
return 0 ;
}
2001-11-12 11:42:29 +00:00
if ( ! _mk_dir ( lv - > vg ) ) {
2001-11-09 08:48:22 +00:00
stack ;
return 0 ;
}
2001-11-12 11:42:29 +00:00
if ( ! _mk_link ( lv ) ) {
2001-11-09 08:48:22 +00:00
stack ;
return 0 ;
}
return 1 ;
}
int fs_del_lv ( struct logical_volume * lv )
{
2001-11-12 11:42:29 +00:00
if ( ! _rm_link ( lv ) ) {
2001-11-09 08:48:22 +00:00
stack ;
return 0 ;
}
2001-11-12 11:42:29 +00:00
if ( ! _rm_dir ( lv - > vg ) ) {
2001-11-09 08:48:22 +00:00
stack ;
return 0 ;
}
2001-11-12 11:42:29 +00:00
if ( ! _rm_node ( lv ) ) {
2001-11-09 08:48:22 +00:00
stack ;
return 0 ;
}
return 1 ;
}