2001-11-21 15:47:42 +03:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the GPL .
*/
2001-11-21 18:15:37 +03:00
# include "libdevmapper.h"
2001-11-21 15:47:42 +03:00
# include <stdio.h>
# include <stdlib.h>
# include <stdarg.h>
# include <string.h>
# include <unistd.h>
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <ctype.h>
# include <errno.h>
2002-01-03 13:39:21 +03:00
# include <unistd.h>
# include <getopt.h>
2002-03-06 17:38:25 +03:00
# include <linux/kdev_t.h>
2001-11-21 15:47:42 +03:00
# define LINE_SIZE 1024
# define err(msg, x...) fprintf(stderr, msg "\n", ##x)
2002-01-03 13:39:21 +03:00
/*
* We have only very simple switches ATM .
*/
enum {
READ_ONLY = 0 ,
2002-01-11 15:12:46 +03:00
MINOR_ARG ,
2002-01-03 13:39:21 +03:00
NUM_SWITCHES
} ;
static int _switches [ NUM_SWITCHES ] ;
2002-01-11 15:12:46 +03:00
static int _values [ NUM_SWITCHES ] ;
2002-01-03 13:39:21 +03:00
/*
* Commands
*/
2001-11-21 15:47:42 +03:00
static int _parse_file ( struct dm_task * dmt , const char * file )
{
2002-03-07 23:56:10 +03:00
char buffer [ LINE_SIZE ] , * ttype , * ptr , * comment ;
FILE * fp = fopen ( file , " r " ) ;
unsigned long long start , size ;
int r = 0 , n , line = 0 ;
2001-11-21 15:47:42 +03:00
2002-03-07 23:56:10 +03:00
if ( ! fp ) {
err ( " Couldn't open '%s' for reading " , file ) ;
return 0 ;
}
2001-11-21 15:47:42 +03:00
2002-03-07 23:56:10 +03:00
while ( fgets ( buffer , sizeof ( buffer ) , fp ) ) {
2001-11-21 15:47:42 +03:00
line + + ;
/* trim trailing space */
for ( ptr = buffer + strlen ( buffer ) - 1 ; ptr > = buffer ; ptr - - )
if ( ! isspace ( ( int ) * ptr ) )
break ;
ptr + + ;
* ptr = ' \0 ' ;
/* trim leading space */
2002-03-07 23:56:10 +03:00
for ( ptr = buffer ; * ptr & & isspace ( ( int ) * ptr ) ; ptr + + ) ;
2001-11-21 15:47:42 +03:00
2002-03-07 23:56:10 +03:00
if ( ! * ptr | | * ptr = = ' # ' )
continue ;
2001-11-21 15:47:42 +03:00
2002-03-07 23:56:10 +03:00
if ( sscanf ( ptr , " %llu %llu %as %n " ,
& start , & size , & ttype , & n ) < 3 ) {
err ( " %s:%d Invalid format " , file , line ) ;
goto out ;
}
2001-11-21 15:47:42 +03:00
ptr + = n ;
if ( ( comment = strchr ( ptr , ( int ) ' # ' ) ) )
* comment = ' \0 ' ;
2002-03-07 23:56:10 +03:00
if ( ! dm_task_add_target ( dmt , start , size , ttype , ptr ) )
goto out ;
2001-11-21 15:47:42 +03:00
free ( ttype ) ;
2002-03-07 23:56:10 +03:00
}
r = 1 ;
2001-11-21 15:47:42 +03:00
2002-03-07 23:56:10 +03:00
out :
fclose ( fp ) ;
return r ;
2001-11-21 15:47:42 +03:00
}
2002-03-12 01:44:36 +03:00
static int _load ( int task , const char * name , const char * file , const char * uuid )
2001-11-21 15:47:42 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
if ( ! ( dmt = dm_task_create ( task ) ) )
return 0 ;
if ( ! dm_task_set_name ( dmt , name ) )
goto out ;
2002-03-12 01:44:36 +03:00
if ( uuid & & ! dm_task_set_uuid ( dmt , uuid ) )
goto out ;
2001-11-21 15:47:42 +03:00
if ( ! _parse_file ( dmt , file ) )
goto out ;
2002-01-03 13:39:21 +03:00
if ( _switches [ READ_ONLY ] & & ! dm_task_set_ro ( dmt ) )
goto out ;
2002-01-11 15:12:46 +03:00
if ( _switches [ MINOR_ARG ] & & ! dm_task_set_minor ( dmt , _values [ MINOR_ARG ] ) )
goto out ;
2001-11-21 15:47:42 +03:00
if ( ! dm_task_run ( dmt ) )
goto out ;
r = 1 ;
2002-03-07 23:56:10 +03:00
out :
2001-11-21 15:47:42 +03:00
dm_task_destroy ( dmt ) ;
return r ;
}
static int _create ( int argc , char * * argv )
{
2002-03-12 01:44:36 +03:00
return _load ( DM_DEVICE_CREATE , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] ) ;
2001-11-21 15:47:42 +03:00
}
static int _reload ( int argc , char * * argv )
{
2002-03-12 01:44:36 +03:00
return _load ( DM_DEVICE_RELOAD , argv [ 1 ] , argv [ 2 ] , NULL ) ;
2001-11-21 15:47:42 +03:00
}
2002-01-11 15:12:46 +03:00
static int _rename ( int argc , char * * argv )
{
int r = 0 ;
struct dm_task * dmt ;
2002-03-07 23:56:10 +03:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_RENAME ) ) )
return 0 ;
2002-01-11 15:12:46 +03:00
2002-03-07 23:56:10 +03:00
if ( ! dm_task_set_name ( dmt , argv [ 1 ] ) )
goto out ;
2002-01-11 15:12:46 +03:00
if ( ! dm_task_set_newname ( dmt , argv [ 2 ] ) )
goto out ;
2002-03-07 23:56:10 +03:00
if ( ! dm_task_run ( dmt ) )
goto out ;
2002-01-11 15:12:46 +03:00
2002-03-07 23:56:10 +03:00
r = 1 ;
2002-01-11 15:12:46 +03:00
2002-03-07 23:56:10 +03:00
out :
dm_task_destroy ( dmt ) ;
2002-01-11 15:12:46 +03:00
2002-03-07 23:56:10 +03:00
return r ;
2002-01-11 15:12:46 +03:00
}
2001-11-21 15:47:42 +03:00
2002-01-15 18:21:57 +03:00
static int _version ( int argc , char * * argv )
{
int r = 0 ;
struct dm_task * dmt ;
2002-01-17 16:19:55 +03:00
char version [ 80 ] ;
2002-01-15 18:21:57 +03:00
2002-01-17 17:13:25 +03:00
if ( dm_get_library_version ( version , sizeof ( version ) ) )
printf ( " Library version: %s \n " , version ) ;
2002-01-15 18:21:57 +03:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_VERSION ) ) )
return 0 ;
if ( ! dm_task_run ( dmt ) )
goto out ;
2002-03-07 23:56:10 +03:00
if ( ! dm_task_get_driver_version ( dmt , ( char * ) & version ,
2002-01-15 18:21:57 +03:00
sizeof ( version ) ) )
goto out ;
printf ( " Driver version: %s \n " , version ) ;
r = 1 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2001-11-21 15:47:42 +03:00
static int _simple ( int task , const char * name )
{
int r = 0 ;
/* remove <dev_name> */
struct dm_task * dmt ;
if ( ! ( dmt = dm_task_create ( task ) ) )
return 0 ;
if ( ! dm_task_set_name ( dmt , name ) )
goto out ;
r = dm_task_run ( dmt ) ;
2002-03-07 23:56:10 +03:00
out :
2001-11-21 15:47:42 +03:00
dm_task_destroy ( dmt ) ;
return r ;
}
2002-03-07 23:56:10 +03:00
static int _remove_all ( int argc , char * * argv )
{
return _simple ( DM_DEVICE_REMOVE_ALL , " " ) ;
}
2001-11-21 15:47:42 +03:00
static int _remove ( int argc , char * * argv )
{
return _simple ( DM_DEVICE_REMOVE , argv [ 1 ] ) ;
}
static int _suspend ( int argc , char * * argv )
{
return _simple ( DM_DEVICE_SUSPEND , argv [ 1 ] ) ;
}
static int _resume ( int argc , char * * argv )
{
return _simple ( DM_DEVICE_RESUME , argv [ 1 ] ) ;
}
2002-05-03 15:55:58 +04:00
static int _wait ( int argc , char * * argv )
{
struct dm_task * dmt ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_WAITEVENT ) ) )
return 0 ;
if ( ! dm_task_set_name ( dmt , argv [ 1 ] ) )
goto out ;
if ( ! dm_task_run ( dmt ) )
goto out ;
dm_task_destroy ( dmt ) ;
out :
return 1 ;
}
static int _status ( int argc , char * * argv )
{
int r = 0 ;
struct dm_task * dmt ;
void * next = NULL ;
unsigned long long start , length ;
char * target_type = NULL ;
char * params ;
int cmd ;
if ( strcmp ( argv [ 0 ] , " status " ) = = 0 )
cmd = DM_DEVICE_STATUS ;
else
cmd = DM_DEVICE_TABLE ;
if ( ! ( dmt = dm_task_create ( cmd ) ) )
return 0 ;
if ( ! dm_task_set_name ( dmt , argv [ 1 ] ) )
goto out ;
if ( ! dm_task_run ( dmt ) )
goto out ;
/* Fetch targets and print 'em */
do {
next = dm_get_next_target ( dmt , next , & start , & length ,
& target_type , & params ) ;
if ( target_type ) {
printf ( " %lld %lld %s %s \n " ,
start , length , target_type , params ) ;
}
} while ( next ) ;
r = 1 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2001-11-21 15:47:42 +03:00
static int _info ( int argc , char * * argv )
{
int r = 0 ;
2002-03-19 02:39:42 +03:00
const char * uuid ;
2001-11-21 15:47:42 +03:00
/* remove <dev_name> */
struct dm_task * dmt ;
struct dm_info info ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_INFO ) ) )
return 0 ;
if ( ! dm_task_set_name ( dmt , argv [ 1 ] ) )
goto out ;
if ( ! dm_task_run ( dmt ) )
goto out ;
if ( ! dm_task_get_info ( dmt , & info ) )
goto out ;
if ( ! info . exists ) {
2001-11-21 21:12:41 +03:00
printf ( " Device does not exist. \n " ) ;
2001-11-21 15:47:42 +03:00
r = 1 ;
goto out ;
}
2002-03-14 16:39:33 +03:00
printf ( " Name: %s \n " , argv [ 1 ] ) ;
2001-12-20 23:32:14 +03:00
printf ( " State: %s \n " ,
2001-11-21 21:12:41 +03:00
info . suspended ? " SUSPENDED " : " ACTIVE " ) ;
2001-12-20 23:32:14 +03:00
if ( info . open_count ! = - 1 )
printf ( " Open count: %d \n " , info . open_count ) ;
printf ( " Major, minor: %d, %d \n " , info . major , info . minor ) ;
if ( info . target_count ! = - 1 )
printf ( " Number of targets: %d \n " , info . target_count ) ;
2002-03-13 19:19:17 +03:00
if ( ( uuid = dm_task_get_uuid ( dmt ) ) & & * uuid )
printf ( " UUID: %s \n " , uuid ) ;
2001-11-21 15:47:42 +03:00
r = 1 ;
2002-03-07 23:56:10 +03:00
out :
2001-11-21 15:47:42 +03:00
dm_task_destroy ( dmt ) ;
return r ;
}
2002-03-06 17:38:25 +03:00
static int _deps ( int argc , char * * argv )
{
int r = 0 , i ;
struct dm_deps * deps ;
/* remove <dev_name> */
struct dm_task * dmt ;
struct dm_info info ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_DEPS ) ) )
return 0 ;
if ( ! dm_task_set_name ( dmt , argv [ 1 ] ) )
goto out ;
if ( ! dm_task_run ( dmt ) )
goto out ;
2002-03-06 22:42:23 +03:00
if ( ! dm_task_get_info ( dmt , & info ) )
goto out ;
2002-03-06 17:38:25 +03:00
if ( ! ( deps = dm_task_get_deps ( dmt ) ) )
goto out ;
if ( ! info . exists ) {
printf ( " Device does not exist. \n " ) ;
r = 1 ;
goto out ;
}
printf ( " %d dependencies \t : " , deps - > count ) ;
for ( i = 0 ; i < deps - > count ; i + + )
printf ( " (%d, %d) " ,
( int ) MAJOR ( deps - > device [ i ] ) ,
( int ) MINOR ( deps - > device [ i ] ) ) ;
printf ( " \n " ) ;
r = 1 ;
2002-03-07 23:56:10 +03:00
out :
2002-03-06 17:38:25 +03:00
dm_task_destroy ( dmt ) ;
return r ;
}
2001-11-21 15:47:42 +03:00
/*
* dispatch table
*/
2002-03-07 23:56:10 +03:00
typedef int ( * command_fn ) ( int argc , char * * argv ) ;
2001-11-21 15:47:42 +03:00
struct command {
char * name ;
char * help ;
2002-03-12 01:44:36 +03:00
int min_args ;
int max_args ;
2001-11-21 15:47:42 +03:00
command_fn fn ;
} ;
static struct command _commands [ ] = {
2002-03-12 01:44:36 +03:00
{ " create " , " <dev_name> <table_file> [<uuid>] " , 2 , 3 , _create } ,
{ " remove " , " <dev_name> " , 1 , 1 , _remove } ,
{ " remove_all " , " " , 0 , 0 , _remove_all } ,
{ " suspend " , " <dev_name> " , 1 , 1 , _suspend } ,
{ " resume " , " <dev_name> " , 1 , 1 , _resume } ,
{ " reload " , " <dev_name> <table_file> " , 2 , 2 , _reload } ,
{ " info " , " <dev_name> " , 1 , 1 , _info } ,
{ " deps " , " <dev_name> " , 1 , 1 , _deps } ,
{ " rename " , " <dev_name> <new_name> " , 2 , 2 , _rename } ,
2002-05-03 15:55:58 +04:00
{ " status " , " <dev_name> " , 1 , 1 , _status } ,
{ " table " , " <dev_name> " , 1 , 1 , _status } ,
{ " wait " , " <dev_name> " , 1 , 1 , _wait } ,
2002-03-12 01:44:36 +03:00
{ " version " , " " , 0 , 0 , _version } ,
{ NULL , NULL , 0 , 0 , NULL }
2001-11-21 15:47:42 +03:00
} ;
2002-03-07 23:56:10 +03:00
static void _usage ( FILE * out )
2001-11-21 15:47:42 +03:00
{
int i ;
fprintf ( out , " usage: \n " ) ;
for ( i = 0 ; _commands [ i ] . name ; i + + )
2002-03-07 23:56:10 +03:00
fprintf ( out , " \t %s %s \n " , _commands [ i ] . name , _commands [ i ] . help ) ;
2001-11-21 15:47:42 +03:00
return ;
}
2002-01-03 13:39:21 +03:00
static struct command * _find_command ( const char * name )
2001-11-21 15:47:42 +03:00
{
int i ;
for ( i = 0 ; _commands [ i ] . name ; i + + )
if ( ! strcmp ( _commands [ i ] . name , name ) )
return _commands + i ;
return NULL ;
}
2002-01-03 13:39:21 +03:00
static int _process_switches ( int * argc , char * * * argv )
{
int index ;
char c ;
static struct option long_options [ ] = {
{ " read-only " , 0 , NULL , READ_ONLY } ,
2002-01-11 15:12:46 +03:00
{ " minor " , 1 , NULL , MINOR_ARG } ,
{ " " , 0 , NULL , 0 }
2002-01-03 13:39:21 +03:00
} ;
/*
* Zero all the index counts .
*/
memset ( & _switches , 0 , sizeof ( _switches ) ) ;
2002-01-11 15:12:46 +03:00
memset ( & _values , 0 , sizeof ( _values ) ) ;
2002-01-03 13:39:21 +03:00
2002-01-11 15:12:46 +03:00
while ( ( c = getopt_long ( * argc , * argv , " m:r " ,
long_options , & index ) ) ! = - 1 ) {
2002-01-03 13:39:21 +03:00
if ( c = = ' r ' | | index = = READ_ONLY )
_switches [ READ_ONLY ] + + ;
2002-01-11 15:12:46 +03:00
if ( c = = ' m ' | | index = = MINOR_ARG ) {
_switches [ MINOR_ARG ] + + ;
_values [ MINOR_ARG ] = atoi ( optarg ) ;
}
}
2002-01-03 13:39:21 +03:00
* argv + = optind ;
* argc - = optind ;
return 1 ;
}
2001-11-21 15:47:42 +03:00
int main ( int argc , char * * argv )
{
struct command * c ;
2002-01-03 13:39:21 +03:00
if ( ! _process_switches ( & argc , & argv ) ) {
fprintf ( stderr , " Couldn't process command line switches. \n " ) ;
exit ( 1 ) ;
}
2002-01-15 18:21:57 +03:00
if ( argc = = 0 ) {
2001-11-21 15:47:42 +03:00
_usage ( stderr ) ;
exit ( 1 ) ;
}
2002-01-03 13:39:21 +03:00
if ( ! ( c = _find_command ( argv [ 0 ] ) ) ) {
2001-11-21 15:47:42 +03:00
fprintf ( stderr , " Unknown command \n " ) ;
_usage ( stderr ) ;
exit ( 1 ) ;
}
2002-03-12 01:44:36 +03:00
if ( argc < c - > min_args + 1 | | argc > c - > max_args + 1 ) {
2001-11-21 15:47:42 +03:00
fprintf ( stderr , " Incorrect number of arguments \n " ) ;
_usage ( stderr ) ;
exit ( 1 ) ;
}
2002-01-03 13:39:21 +03:00
if ( ! c - > fn ( argc , argv ) ) {
2001-12-14 16:30:04 +03:00
fprintf ( stderr , " Command failed \n " ) ;
2001-11-21 15:47:42 +03:00
exit ( 1 ) ;
}
return 0 ;
}