2001-11-21 15:47:42 +03:00
/*
2004-03-30 23:08:57 +04:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2006-10-12 19:42:25 +04:00
* Copyright ( C ) 2004 - 2006 Red Hat , Inc . All rights reserved .
2005-10-16 18:33:22 +04:00
* Copyright ( C ) 2005 NEC Corperation
2001-11-21 15:47:42 +03:00
*
2004-03-30 23:08:57 +04:00
* This file is part of the device - mapper userspace tools .
*
2005-10-16 18:33:22 +04:00
* It includes tree drawing code based on pstree : http : //psmisc.sourceforge.net/
*
2004-03-30 23:08:57 +04:00
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU General Public License v .2 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2001-11-21 15:47:42 +03:00
*/
2005-05-17 00:46:46 +04:00
# define _GNU_SOURCE
# define _FILE_OFFSET_BITS 64
2006-05-10 23:38:25 +04:00
# include <configure.h>
2001-11-21 18:15:37 +03:00
# include "libdevmapper.h"
2004-02-24 21:50:09 +03:00
# include "log.h"
2001-11-21 15:47:42 +03:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
2003-11-13 16:14:28 +03:00
# include <dirent.h>
# include <errno.h>
2003-11-12 20:30:32 +03:00
# include <unistd.h>
2005-03-27 15:37:46 +04:00
# include <libgen.h>
2005-05-17 00:46:46 +04:00
# include <sys/wait.h>
# include <unistd.h>
# include <sys/param.h>
2005-10-16 18:33:22 +04:00
# include <locale.h>
# include <langinfo.h>
2006-10-12 19:42:25 +04:00
# include <fcntl.h>
# include <sys/stat.h>
/* FIXME Unused so far */
# undef HAVE_SYS_STATVFS_H
# ifdef HAVE_SYS_STATVFS_H
# include <sys / statvfs.h>
# endif
2005-10-16 18:33:22 +04:00
# ifdef HAVE_SYS_IOCTL_H
# include <sys / ioctl.h>
# endif
# if HAVE_TERMIOS_H
# include <termios.h>
# endif
2003-11-12 20:30:32 +03:00
# ifdef HAVE_GETOPTLONG
# include <getopt.h>
# define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))
# define OPTIND_INIT 0
# else
struct option {
} ;
extern int optind ;
extern char * optarg ;
# define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))
# define OPTIND_INIT 1
# endif
2005-05-17 00:46:46 +04:00
# ifndef TEMP_FAILURE_RETRY
# define TEMP_FAILURE_RETRY(expression) \
( __extension__ \
( { long int __result ; \
do __result = ( long int ) ( expression ) ; \
while ( __result = = - 1L & & errno = = EINTR ) ; \
__result ; } ) )
# endif
2003-11-12 20:30:32 +03:00
# ifdef linux
2004-07-01 19:14:29 +04:00
# include "kdev_t.h"
2003-11-12 20:30:32 +03:00
# else
# define MAJOR(x) major((x))
# define MINOR(x) minor((x))
# define MKDEV(x,y) makedev((x),(y))
# endif
2001-11-21 15:47:42 +03:00
2006-04-20 00:43:30 +04:00
# define LINE_SIZE 4096
2005-05-17 00:46:46 +04:00
# define ARGS_MAX 256
2006-10-12 19:42:25 +04:00
# define LOOP_TABLE_SIZE (PATH_MAX + 255)
/* FIXME Should be elsewhere */
# define SECTOR_SHIFT 9L
# define DEV_PATH " / dev / "
2001-11-21 15:47:42 +03:00
# 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 ,
2004-06-16 20:44:12 +04:00
COLS_ARG ,
2005-05-17 00:46:46 +04:00
EXEC_ARG ,
2006-06-18 15:35:04 +04:00
FORCE_ARG ,
2006-02-03 17:23:22 +03:00
GID_ARG ,
2003-04-04 17:22:58 +04:00
MAJOR_ARG ,
2002-01-11 15:12:46 +03:00
MINOR_ARG ,
2006-02-03 17:23:22 +03:00
MODE_ARG ,
2006-10-12 19:42:25 +04:00
NOFLUSH_ARG ,
2004-10-12 20:42:40 +04:00
NOHEADINGS_ARG ,
2005-10-05 00:12:32 +04:00
NOLOCKFS_ARG ,
2005-01-13 01:10:14 +03:00
NOOPENCOUNT_ARG ,
2003-11-12 20:30:32 +03:00
NOTABLE_ARG ,
2005-03-27 15:37:46 +04:00
OPTIONS_ARG ,
2006-10-19 19:34:50 +04:00
SHOWKEYS_ARG ,
2006-08-10 18:11:03 +04:00
TABLE_ARG ,
2005-05-16 18:53:23 +04:00
TARGET_ARG ,
2005-10-16 18:33:22 +04:00
TREE_ARG ,
2006-02-03 17:23:22 +03:00
UID_ARG ,
2003-11-12 20:30:32 +03:00
UUID_ARG ,
2003-01-22 00:25:51 +03:00
VERBOSE_ARG ,
2003-07-04 23:38:49 +04:00
VERSION_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 ] ;
2006-06-18 15:35:04 +04:00
static int _num_devices ;
2003-11-12 20:30:32 +03:00
static char * _uuid ;
2005-03-27 15:37:46 +04:00
static char * _fields ;
2006-08-10 18:11:03 +04:00
static char * _table ;
2005-05-16 18:53:23 +04:00
static char * _target ;
2005-05-17 00:46:46 +04:00
static char * _command ;
2005-11-09 17:10:50 +03:00
static struct dm_tree * _dtree ;
2002-01-03 13:39:21 +03:00
/*
* Commands
*/
2006-08-10 18:11:03 +04:00
static int _parse_line ( struct dm_task * dmt , char * buffer , const char * file ,
int line )
{
char ttype [ LINE_SIZE ] , * ptr , * comment ;
unsigned long long start , size ;
int n ;
/* trim trailing space */
for ( ptr = buffer + strlen ( buffer ) - 1 ; ptr > = buffer ; ptr - - )
if ( ! isspace ( ( int ) * ptr ) )
break ;
ptr + + ;
* ptr = ' \0 ' ;
/* trim leading space */
for ( ptr = buffer ; * ptr & & isspace ( ( int ) * ptr ) ; ptr + + )
;
if ( ! * ptr | | * ptr = = ' # ' )
return 1 ;
if ( sscanf ( ptr , " %llu %llu %s %n " ,
& start , & size , ttype , & n ) < 3 ) {
err ( " Invalid format on line %d of table %s " , line , file ) ;
return 0 ;
}
ptr + = n ;
if ( ( comment = strchr ( ptr , ( int ) ' # ' ) ) )
* comment = ' \0 ' ;
if ( ! dm_task_add_target ( dmt , start , size , ttype , ptr ) )
return 0 ;
return 1 ;
}
2001-11-21 15:47:42 +03:00
static int _parse_file ( struct dm_task * dmt , const char * file )
{
2006-05-10 23:38:25 +04:00
char * buffer = NULL ;
size_t buffer_size = 0 ;
2003-11-12 20:30:32 +03:00
FILE * fp ;
2006-08-10 18:11:03 +04:00
int r = 0 , line = 0 ;
2001-11-21 15:47:42 +03:00
2006-08-10 18:11:03 +04:00
/* one-line table on cmdline */
if ( _table )
return _parse_line ( dmt , _table , " " , + + line ) ;
2003-11-12 20:30:32 +03:00
2006-08-10 18:11:03 +04:00
/* OK for empty stdin */
2003-11-12 20:30:32 +03:00
if ( file ) {
if ( ! ( fp = fopen ( file , " r " ) ) ) {
err ( " Couldn't open '%s' for reading " , file ) ;
return 0 ;
}
} else
fp = stdin ;
2001-11-21 15:47:42 +03:00
2006-05-10 23:38:25 +04:00
# ifndef HAVE_GETLINE
buffer_size = LINE_SIZE ;
2006-10-12 19:42:25 +04:00
if ( ! ( buffer = dm_malloc ( buffer_size ) ) ) {
2006-05-10 23:38:25 +04:00
err ( " Failed to malloc line buffer. " ) ;
return 0 ;
}
2006-08-10 18:11:03 +04:00
while ( fgets ( buffer , ( int ) buffer_size , fp ) )
2006-05-10 23:38:25 +04:00
# else
2006-08-10 18:11:03 +04:00
while ( getline ( & buffer , & buffer_size , fp ) > 0 )
2006-05-10 23:38:25 +04:00
# endif
2006-08-10 18:11:03 +04:00
if ( ! _parse_line ( dmt , buffer , file ? : " on stdin " , + + line ) )
2002-03-07 23:56:10 +03:00
goto out ;
2001-11-21 15:47:42 +03:00
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 :
2006-10-19 19:34:50 +04:00
# ifndef HAVE_GETLINE
2006-10-12 19:42:25 +04:00
dm_free ( buffer ) ;
2006-10-19 19:34:50 +04:00
# else
free ( buffer ) ;
# endif
2003-11-12 20:30:32 +03:00
if ( file )
fclose ( fp ) ;
2002-03-07 23:56:10 +03:00
return r ;
2001-11-21 15:47:42 +03:00
}
2004-10-12 20:42:40 +04:00
static void _display_info_cols_noheadings ( struct dm_task * dmt ,
struct dm_info * info )
{
const char * uuid ;
if ( ! info - > exists )
return ;
uuid = dm_task_get_uuid ( dmt ) ;
2005-03-27 15:37:46 +04:00
if ( _switches [ OPTIONS_ARG ] )
printf ( " %s \n " , dm_task_get_name ( dmt ) ) ;
else
printf ( " %s:%d:%d:%s%s%s%s:%d:%d:% " PRIu32 " :%s \n " ,
dm_task_get_name ( dmt ) ,
info - > major , info - > minor ,
info - > live_table ? " L " : " - " ,
info - > inactive_table ? " I " : " - " ,
info - > suspended ? " s " : " - " ,
info - > read_only ? " r " : " w " ,
info - > open_count , info - > target_count , info - > event_nr ,
uuid & & * uuid ? uuid : " " ) ;
2004-10-12 20:42:40 +04:00
}
2004-06-16 20:44:12 +04:00
static void _display_info_cols ( struct dm_task * dmt , struct dm_info * info )
2003-07-02 01:20:58 +04:00
{
2004-06-16 20:44:12 +04:00
static int _headings = 0 ;
2003-07-02 01:20:58 +04:00
const char * uuid ;
2004-06-16 20:44:12 +04:00
if ( ! info - > exists ) {
printf ( " Device does not exist. \n " ) ;
2003-07-02 01:20:58 +04:00
return ;
2004-06-16 20:44:12 +04:00
}
2003-07-02 01:20:58 +04:00
2004-06-16 20:44:12 +04:00
if ( ! _headings ) {
2005-03-27 15:37:46 +04:00
if ( _switches [ OPTIONS_ARG ] )
printf ( " Name \n " ) ;
else
printf ( " Name Maj Min Stat Open Targ "
" Event UUID \n " ) ;
2004-06-16 20:44:12 +04:00
_headings = 1 ;
}
2005-03-27 15:37:46 +04:00
if ( _switches [ OPTIONS_ARG ] )
printf ( " %s \n " , dm_task_get_name ( dmt ) ) ;
else {
printf ( " %-16s %3d %3d %s%s%s%s %4d %4d %6 " PRIu32 " " ,
dm_task_get_name ( dmt ) ,
info - > major , info - > minor ,
info - > live_table ? " L " : " - " ,
info - > inactive_table ? " I " : " - " ,
info - > suspended ? " s " : " - " ,
info - > read_only ? " r " : " w " ,
info - > open_count , info - > target_count , info - > event_nr ) ;
if ( ( uuid = dm_task_get_uuid ( dmt ) ) & & * uuid )
printf ( " %s " , uuid ) ;
2004-06-16 20:44:12 +04:00
2005-03-27 15:37:46 +04:00
printf ( " \n " ) ;
}
2004-06-16 20:44:12 +04:00
}
static void _display_info_long ( struct dm_task * dmt , struct dm_info * info )
{
const char * uuid ;
if ( ! info - > exists ) {
2003-07-02 01:20:58 +04:00
printf ( " Device does not exist. \n " ) ;
return ;
}
printf ( " Name: %s \n " , dm_task_get_name ( dmt ) ) ;
printf ( " State: %s%s \n " ,
2004-06-16 20:44:12 +04:00
info - > suspended ? " SUSPENDED " : " ACTIVE " ,
info - > read_only ? " (READ-ONLY) " : " " ) ;
2003-07-02 01:20:58 +04:00
2004-06-16 20:44:12 +04:00
if ( ! info - > live_table & & ! info - > inactive_table )
2003-07-02 01:20:58 +04:00
printf ( " Tables present: None \n " ) ;
else
printf ( " Tables present: %s%s%s \n " ,
2004-06-16 20:44:12 +04:00
info - > live_table ? " LIVE " : " " ,
info - > live_table & & info - > inactive_table ? " & " : " " ,
info - > inactive_table ? " INACTIVE " : " " ) ;
2003-07-02 01:20:58 +04:00
2004-06-16 20:44:12 +04:00
if ( info - > open_count ! = - 1 )
printf ( " Open count: %d \n " , info - > open_count ) ;
2003-07-02 01:20:58 +04:00
2004-06-16 20:44:12 +04:00
printf ( " Event number: % " PRIu32 " \n " , info - > event_nr ) ;
printf ( " Major, minor: %d, %d \n " , info - > major , info - > minor ) ;
2003-07-02 01:20:58 +04:00
2004-06-16 20:44:12 +04:00
if ( info - > target_count ! = - 1 )
printf ( " Number of targets: %d \n " , info - > target_count ) ;
2003-07-02 01:20:58 +04:00
if ( ( uuid = dm_task_get_uuid ( dmt ) ) & & * uuid )
printf ( " UUID: %s \n " , uuid ) ;
2003-07-04 23:38:49 +04:00
printf ( " \n " ) ;
2003-07-02 01:20:58 +04:00
}
2005-03-27 15:37:46 +04:00
static int _display_info ( struct dm_task * dmt )
2004-06-16 20:44:12 +04:00
{
struct dm_info info ;
if ( ! dm_task_get_info ( dmt , & info ) )
2005-03-27 15:37:46 +04:00
return 0 ;
2004-06-16 20:44:12 +04:00
2004-10-12 20:42:40 +04:00
if ( ! _switches [ COLS_ARG ] )
2004-06-16 20:44:12 +04:00
_display_info_long ( dmt , & info ) ;
2004-10-12 20:42:40 +04:00
else if ( _switches [ NOHEADINGS_ARG ] )
_display_info_cols_noheadings ( dmt , & info ) ;
else
_display_info_cols ( dmt , & info ) ;
2005-03-27 15:37:46 +04:00
return info . exists ? 1 : 0 ;
2004-06-16 20:44:12 +04:00
}
2004-10-01 23:11:37 +04:00
static int _set_task_device ( struct dm_task * dmt , const char * name , int optional )
{
if ( name ) {
if ( ! dm_task_set_name ( dmt , name ) )
return 0 ;
} else if ( _switches [ UUID_ARG ] ) {
if ( ! dm_task_set_uuid ( dmt , _uuid ) )
return 0 ;
} else if ( _switches [ MAJOR_ARG ] & & _switches [ MINOR_ARG ] ) {
if ( ! dm_task_set_major ( dmt , _values [ MAJOR_ARG ] ) | |
! dm_task_set_minor ( dmt , _values [ MINOR_ARG ] ) )
return 0 ;
} else if ( ! optional ) {
fprintf ( stderr , " No device specified. \n " ) ;
return 0 ;
}
return 1 ;
}
2006-05-16 20:20:29 +04:00
static int _load ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2001-11-21 15:47:42 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
2004-10-01 23:11:37 +04:00
const char * file = NULL ;
const char * name = NULL ;
2001-11-21 15:47:42 +03:00
2004-10-01 23:11:37 +04:00
if ( _switches [ NOTABLE_ARG ] ) {
err ( " --notable only available when creating new device \n " ) ;
2001-11-21 15:47:42 +03:00
return 0 ;
2004-10-01 23:11:37 +04:00
}
2001-11-21 15:47:42 +03:00
2004-10-01 23:11:37 +04:00
if ( ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] ) {
if ( argc = = 1 ) {
err ( " Please specify device. \n " ) ;
return 0 ;
}
name = argv [ 1 ] ;
argc - - ;
argv + + ;
} else if ( argc > 2 ) {
err ( " Too many command line arguments. \n " ) ;
return 0 ;
}
2001-11-21 15:47:42 +03:00
2004-10-01 23:11:37 +04:00
if ( argc = = 2 )
file = argv [ 1 ] ;
2002-03-12 01:44:36 +03:00
2004-10-01 23:11:37 +04:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_RELOAD ) ) )
return 0 ;
2003-11-13 16:14:28 +03:00
2004-10-01 23:11:37 +04:00
if ( ! _set_task_device ( dmt , name , 0 ) )
2002-01-03 13:39:21 +03:00
goto out ;
2004-10-01 23:11:37 +04:00
if ( ! _switches [ NOTABLE_ARG ] & & ! _parse_file ( dmt , file ) )
2003-04-04 17:22:58 +04:00
goto out ;
2004-10-01 23:11:37 +04:00
if ( _switches [ READ_ONLY ] & & ! dm_task_set_ro ( dmt ) )
2002-01-11 15:12:46 +03:00
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2001-11-21 15:47:42 +03:00
if ( ! dm_task_run ( dmt ) )
goto out ;
r = 1 ;
2003-07-04 23:38:49 +04:00
if ( _switches [ VERBOSE_ARG ] )
2005-03-27 15:37:46 +04:00
r = _display_info ( dmt ) ;
2003-07-02 01:20:58 +04:00
2002-03-07 23:56:10 +03:00
out :
2001-11-21 15:47:42 +03:00
dm_task_destroy ( dmt ) ;
return r ;
}
2006-05-16 20:20:29 +04:00
static int _create ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2001-11-21 15:47:42 +03:00
{
2004-10-01 23:11:37 +04:00
int r = 0 ;
struct dm_task * dmt ;
const char * file = NULL ;
2001-11-21 15:47:42 +03:00
2004-10-01 23:11:37 +04:00
if ( argc = = 3 )
file = argv [ 2 ] ;
2006-06-18 15:35:04 +04:00
2004-10-01 23:11:37 +04:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_CREATE ) ) )
2003-11-12 20:30:32 +03:00
return 0 ;
2004-10-01 23:11:37 +04:00
if ( ! dm_task_set_name ( dmt , argv [ 1 ] ) )
goto out ;
if ( _switches [ UUID_ARG ] & & ! dm_task_set_uuid ( dmt , _uuid ) )
goto out ;
if ( ! _switches [ NOTABLE_ARG ] & & ! _parse_file ( dmt , file ) )
goto out ;
if ( _switches [ READ_ONLY ] & & ! dm_task_set_ro ( dmt ) )
goto out ;
if ( _switches [ MAJOR_ARG ] & & ! dm_task_set_major ( dmt , _values [ MAJOR_ARG ] ) )
goto out ;
if ( _switches [ MINOR_ARG ] & & ! dm_task_set_minor ( dmt , _values [ MINOR_ARG ] ) )
goto out ;
2006-02-03 17:23:22 +03:00
if ( _switches [ UID_ARG ] & & ! dm_task_set_uid ( dmt , _values [ UID_ARG ] ) )
goto out ;
if ( _switches [ GID_ARG ] & & ! dm_task_set_gid ( dmt , _values [ GID_ARG ] ) )
goto out ;
if ( _switches [ MODE_ARG ] & & ! dm_task_set_mode ( dmt , _values [ MODE_ARG ] ) )
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2004-10-01 23:11:37 +04:00
if ( ! dm_task_run ( dmt ) )
goto out ;
r = 1 ;
if ( _switches [ VERBOSE_ARG ] )
2005-03-27 15:37:46 +04:00
r = _display_info ( dmt ) ;
2004-10-01 23:11:37 +04:00
out :
dm_task_destroy ( dmt ) ;
return r ;
2001-11-21 15:47:42 +03:00
}
2006-05-16 20:20:29 +04:00
static int _rename ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2002-01-11 15:12:46 +03:00
{
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
2004-10-01 23:11:37 +04:00
/* FIXME Kernel doesn't support uuid or device number here yet */
if ( ! _set_task_device ( dmt , ( argc = = 3 ) ? argv [ 1 ] : NULL , 0 ) )
2002-03-07 23:56:10 +03:00
goto out ;
2002-01-11 15:12:46 +03:00
2004-10-01 23:11:37 +04:00
if ( ! dm_task_set_newname ( dmt , argv [ argc - 1 ] ) )
2002-01-11 15:12:46 +03:00
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
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
2006-05-16 20:20:29 +04:00
static int _message ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2004-06-09 00:34:40 +04:00
{
2006-01-31 17:50:38 +03:00
int r = 0 , i ;
size_t sz = 1 ;
2004-06-09 00:34:40 +04:00
struct dm_task * dmt ;
char * str ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_TARGET_MSG ) ) )
return 0 ;
2004-10-01 23:11:37 +04:00
if ( _switches [ UUID_ARG ] | | _switches [ MAJOR_ARG ] ) {
if ( ! _set_task_device ( dmt , NULL , 0 ) )
goto out ;
} else {
if ( ! _set_task_device ( dmt , argv [ 1 ] , 0 ) )
goto out ;
argc - - ;
argv + + ;
}
2004-06-09 00:34:40 +04:00
2006-01-31 17:50:38 +03:00
if ( ! dm_task_set_sector ( dmt , ( uint64_t ) atoll ( argv [ 1 ] ) ) )
2004-06-09 00:34:40 +04:00
goto out ;
2004-10-01 23:11:37 +04:00
argc - = 2 ;
argv + = 2 ;
if ( argc < = 0 )
err ( " No message supplied. \n " ) ;
2004-06-09 00:34:40 +04:00
for ( i = 0 ; i < argc ; i + + )
sz + = strlen ( argv [ i ] ) + 1 ;
2006-10-12 19:42:25 +04:00
str = dm_malloc ( sz ) ;
2004-06-10 20:14:16 +04:00
memset ( str , 0 , sz ) ;
2004-06-09 00:34:40 +04:00
for ( i = 0 ; i < argc ; i + + ) {
if ( i )
strcat ( str , " " ) ;
strcat ( str , argv [ i ] ) ;
}
if ( ! dm_task_set_message ( dmt , str ) )
goto out ;
2006-10-12 19:42:25 +04:00
dm_free ( str ) ;
2004-06-09 00:34:40 +04:00
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2004-06-09 00:34:40 +04:00
if ( ! dm_task_run ( dmt ) )
goto out ;
r = 1 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2006-05-16 20:20:29 +04:00
static int _setgeometry ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2006-02-21 02:55:58 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_SET_GEOMETRY ) ) )
return 0 ;
if ( _switches [ UUID_ARG ] | | _switches [ MAJOR_ARG ] ) {
if ( ! _set_task_device ( dmt , NULL , 0 ) )
goto out ;
} else {
if ( ! _set_task_device ( dmt , argv [ 1 ] , 0 ) )
goto out ;
argc - - ;
argv + + ;
}
if ( ! dm_task_set_geometry ( dmt , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] , argv [ 4 ] ) )
goto out ;
/* run the task */
if ( ! dm_task_run ( dmt ) )
goto out ;
r = 1 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2006-05-16 20:20:29 +04:00
static int _version ( int argc __attribute ( ( unused ) ) , char * * argv __attribute ( ( unused ) ) , void * data __attribute ( ( unused ) ) )
2002-01-15 18:21:57 +03:00
{
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 ) ;
2006-01-03 23:53:57 +03:00
if ( ! dm_driver_version ( version , sizeof ( version ) ) )
2002-01-15 18:21:57 +03:00
return 0 ;
printf ( " Driver version: %s \n " , version ) ;
2005-10-17 22:05:39 +04:00
return 1 ;
2002-01-15 18:21:57 +03:00
}
2004-01-23 17:09:33 +03:00
static int _simple ( int task , const char * name , uint32_t event_nr , int display )
2001-11-21 15:47:42 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
if ( ! ( dmt = dm_task_create ( task ) ) )
return 0 ;
2004-10-01 23:11:37 +04:00
if ( ! _set_task_device ( dmt , name , 0 ) )
2001-11-21 15:47:42 +03:00
goto out ;
2004-01-23 17:09:33 +03:00
if ( event_nr & & ! dm_task_set_event_nr ( dmt , event_nr ) )
goto out ;
2006-10-12 19:42:25 +04:00
if ( _switches [ NOFLUSH_ARG ] & & ! dm_task_no_flush ( dmt ) )
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2005-10-05 00:12:32 +04:00
if ( _switches [ NOLOCKFS_ARG ] & & ! dm_task_skip_lockfs ( dmt ) )
goto out ;
2001-11-21 15:47:42 +03:00
r = dm_task_run ( dmt ) ;
2003-07-04 23:38:49 +04:00
if ( r & & display & & _switches [ VERBOSE_ARG ] )
2005-03-27 15:37:46 +04:00
r = _display_info ( dmt ) ;
2003-07-02 01:20:58 +04:00
2002-03-07 23:56:10 +03:00
out :
2001-11-21 15:47:42 +03:00
dm_task_destroy ( dmt ) ;
return r ;
}
2006-05-16 20:20:29 +04:00
static int _suspend ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2001-11-21 15:47:42 +03:00
{
2004-10-01 23:11:37 +04:00
return _simple ( DM_DEVICE_SUSPEND , argc > 1 ? argv [ 1 ] : NULL , 0 , 1 ) ;
2001-11-21 15:47:42 +03:00
}
2006-05-16 20:20:29 +04:00
static int _resume ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2001-11-21 15:47:42 +03:00
{
2004-10-01 23:11:37 +04:00
return _simple ( DM_DEVICE_RESUME , argc > 1 ? argv [ 1 ] : NULL , 0 , 1 ) ;
2003-07-02 01:20:58 +04:00
}
2006-05-16 20:20:29 +04:00
static int _clear ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2003-07-02 01:20:58 +04:00
{
2004-10-01 23:11:37 +04:00
return _simple ( DM_DEVICE_CLEAR , argc > 1 ? argv [ 1 ] : NULL , 0 , 1 ) ;
2001-11-21 15:47:42 +03:00
}
2006-05-16 20:20:29 +04:00
static int _wait ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2002-05-03 15:55:58 +04:00
{
2004-10-01 23:11:37 +04:00
const char * name = NULL ;
if ( ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] ) {
if ( argc = = 1 ) {
err ( " No device specified. " ) ;
return 0 ;
}
name = argv [ 1 ] ;
argc - - , argv + + ;
}
return _simple ( DM_DEVICE_WAITEVENT , name ,
2006-01-31 17:50:38 +03:00
( argc > 1 ) ? ( uint32_t ) atoi ( argv [ argc - 1 ] ) : 0 , 1 ) ;
2002-05-03 15:55:58 +04:00
}
2006-06-18 15:51:46 +04:00
static int _process_all ( int argc , char * * argv , int silent ,
2003-11-13 16:14:28 +03:00
int ( * fn ) ( int argc , char * * argv , void * data ) )
2003-09-16 18:13:51 +04:00
{
2003-11-13 16:14:28 +03:00
int r = 1 ;
2003-09-16 18:13:51 +04:00
struct dm_names * names ;
unsigned next = 0 ;
struct dm_task * dmt ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_LIST ) ) )
return 0 ;
2003-11-13 16:14:28 +03:00
if ( ! dm_task_run ( dmt ) ) {
r = 0 ;
2003-09-16 18:13:51 +04:00
goto out ;
2003-11-13 16:14:28 +03:00
}
2003-09-16 18:13:51 +04:00
2003-11-13 16:14:28 +03:00
if ( ! ( names = dm_task_get_names ( dmt ) ) ) {
r = 0 ;
2003-09-16 18:13:51 +04:00
goto out ;
2003-11-13 16:14:28 +03:00
}
2003-09-16 18:13:51 +04:00
if ( ! names - > dev ) {
2006-06-18 15:51:46 +04:00
if ( ! silent )
printf ( " No devices found \n " ) ;
2003-09-16 18:13:51 +04:00
goto out ;
}
do {
names = ( void * ) names + next ;
2003-11-13 16:14:28 +03:00
if ( ! fn ( argc , argv , ( void * ) names ) )
2003-09-16 18:13:51 +04:00
r = 0 ;
next = names - > next ;
} while ( next ) ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2006-06-18 15:35:04 +04:00
static uint64_t _get_device_size ( const char * name )
{
uint64_t start , length , size = UINT64_C ( 0 ) ;
struct dm_info info ;
char * target_type , * params ;
struct dm_task * dmt ;
2006-06-18 15:51:46 +04:00
void * next = NULL ;
2006-06-18 15:35:04 +04:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_TABLE ) ) )
return 0 ;
2006-06-18 15:51:46 +04:00
if ( ! _set_task_device ( dmt , name , 0 ) )
goto out ;
2006-06-18 15:35:04 +04:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
if ( ! dm_task_run ( dmt ) )
goto out ;
if ( ! dm_task_get_info ( dmt , & info ) | | ! info . exists )
goto out ;
do {
next = dm_get_next_target ( dmt , next , & start , & length ,
& target_type , & params ) ;
size + = length ;
} while ( next ) ;
out :
dm_task_destroy ( dmt ) ;
return size ;
}
static int _error_device ( int argc __attribute ( ( unused ) ) , char * * argv __attribute ( ( unused ) ) , void * data )
{
struct dm_names * names = ( struct dm_names * ) data ;
struct dm_task * dmt ;
const char * name ;
uint64_t size ;
2006-06-18 15:51:46 +04:00
int r = 0 ;
2006-06-18 15:35:04 +04:00
if ( data )
name = names - > name ;
else
name = argv [ 1 ] ;
size = _get_device_size ( name ) ;
2006-08-10 18:11:03 +04:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_RELOAD ) ) )
return 0 ;
2006-06-18 15:35:04 +04:00
2006-06-18 15:51:46 +04:00
if ( ! _set_task_device ( dmt , name , 0 ) )
2006-10-12 19:42:25 +04:00
goto error ;
2006-06-18 15:51:46 +04:00
2006-08-10 18:11:03 +04:00
if ( ! dm_task_add_target ( dmt , 0 , size , " error " , " " ) )
2006-10-12 19:42:25 +04:00
goto error ;
2006-06-18 15:35:04 +04:00
2006-08-10 18:11:03 +04:00
if ( _switches [ READ_ONLY ] & & ! dm_task_set_ro ( dmt ) )
2006-10-12 19:42:25 +04:00
goto error ;
2006-06-18 15:35:04 +04:00
2006-08-10 18:11:03 +04:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
2006-10-12 19:42:25 +04:00
goto error ;
2006-06-18 15:35:04 +04:00
2006-08-10 18:11:03 +04:00
if ( ! dm_task_run ( dmt ) )
2006-10-12 19:42:25 +04:00
goto error ;
2006-06-18 15:35:04 +04:00
2006-06-18 15:51:46 +04:00
if ( ! _simple ( DM_DEVICE_RESUME , name , 0 , 0 ) ) {
_simple ( DM_DEVICE_CLEAR , name , 0 , 0 ) ;
2006-10-12 19:42:25 +04:00
goto error ;
2006-06-18 15:51:46 +04:00
}
2006-06-18 15:35:04 +04:00
2006-06-18 15:51:46 +04:00
r = 1 ;
2006-06-18 15:35:04 +04:00
2006-10-12 19:42:25 +04:00
error :
2006-06-18 15:35:04 +04:00
dm_task_destroy ( dmt ) ;
2006-06-18 15:51:46 +04:00
return r ;
2006-06-18 15:35:04 +04:00
}
static int _remove ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
{
int r ;
if ( _switches [ FORCE_ARG ] & & argc > 1 )
r = _error_device ( argc , argv , NULL ) ;
return _simple ( DM_DEVICE_REMOVE , argc > 1 ? argv [ 1 ] : NULL , 0 , 0 ) ;
}
static int _count_devices ( int argc __attribute ( ( unused ) ) , char * * argv __attribute ( ( unused ) ) , void * data __attribute ( ( unused ) ) )
{
_num_devices + + ;
return 1 ;
}
static int _remove_all ( int argc __attribute ( ( unused ) ) , char * * argv __attribute ( ( unused ) ) , void * data __attribute ( ( unused ) ) )
{
int r ;
/* Remove all closed devices */
r = _simple ( DM_DEVICE_REMOVE_ALL , " " , 0 , 0 ) | dm_mknodes ( NULL ) ;
if ( ! _switches [ FORCE_ARG ] )
return r ;
_num_devices = 0 ;
2006-06-18 15:51:46 +04:00
r | = _process_all ( argc , argv , 1 , _count_devices ) ;
2006-06-18 15:35:04 +04:00
/* No devices left? */
if ( ! _num_devices )
return r ;
2006-06-18 15:51:46 +04:00
r | = _process_all ( argc , argv , 1 , _error_device ) ;
2006-06-18 15:35:04 +04:00
r | = _simple ( DM_DEVICE_REMOVE_ALL , " " , 0 , 0 ) | dm_mknodes ( NULL ) ;
_num_devices = 0 ;
2006-06-18 15:51:46 +04:00
r | = _process_all ( argc , argv , 1 , _count_devices ) ;
2006-06-18 15:35:04 +04:00
if ( ! _num_devices )
return r ;
2006-06-18 15:51:46 +04:00
fprintf ( stderr , " Unable to remove %d device(s). \n " , _num_devices ) ;
2006-06-18 15:35:04 +04:00
return r ;
}
2006-01-31 17:50:38 +03:00
static void _display_dev ( struct dm_task * dmt , const char * name )
2005-05-16 20:04:34 +04:00
{
struct dm_info info ;
if ( dm_task_get_info ( dmt , & info ) )
printf ( " %s \t (%u, %u) \n " , name , info . major , info . minor ) ;
}
2006-05-16 20:20:29 +04:00
static int _mknodes ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2005-05-17 00:46:46 +04:00
{
2005-10-17 02:57:20 +04:00
return dm_mknodes ( argc > 1 ? argv [ 1 ] : NULL ) ;
2005-05-17 00:46:46 +04:00
}
2006-01-31 17:50:38 +03:00
static int _exec_command ( const char * name )
2005-05-17 00:46:46 +04:00
{
int n ;
static char path [ PATH_MAX ] ;
static char * args [ ARGS_MAX + 1 ] ;
static int argc = 0 ;
char * c ;
pid_t pid ;
if ( argc < 0 )
return 0 ;
2005-10-17 02:57:20 +04:00
if ( ! dm_mknodes ( name ) )
2005-05-17 00:46:46 +04:00
return 0 ;
n = snprintf ( path , sizeof ( path ) , " %s/%s " , dm_dir ( ) , name ) ;
2006-01-31 17:50:38 +03:00
if ( n < 0 | | n > ( int ) sizeof ( path ) - 1 )
2005-05-17 00:46:46 +04:00
return 0 ;
if ( ! argc ) {
c = _command ;
while ( argc < ARGS_MAX ) {
while ( * c & & isspace ( * c ) )
c + + ;
if ( ! * c )
break ;
args [ argc + + ] = c ;
while ( * c & & ! isspace ( * c ) )
c + + ;
if ( * c )
* c + + = ' \0 ' ;
}
if ( ! argc ) {
argc = - 1 ;
return 0 ;
}
if ( argc = = ARGS_MAX ) {
err ( " Too many args to --exec \n " ) ;
argc = - 1 ;
return 0 ;
}
args [ argc + + ] = path ;
args [ argc ] = NULL ;
}
if ( ! ( pid = fork ( ) ) ) {
execvp ( args [ 0 ] , args ) ;
exit ( 127 ) ;
} else if ( pid < ( pid_t ) 0 )
return 0 ;
TEMP_FAILURE_RETRY ( waitpid ( pid , NULL , 0 ) ) ;
return 1 ;
}
2003-09-16 18:13:51 +04:00
static int _status ( int argc , char * * argv , void * data )
2002-05-03 15:55:58 +04:00
{
int r = 0 ;
struct dm_task * dmt ;
void * next = NULL ;
2002-05-10 19:25:38 +04:00
uint64_t start , length ;
2002-05-03 15:55:58 +04:00
char * target_type = NULL ;
2006-10-19 19:34:50 +04:00
char * params , * c ;
2002-05-03 15:55:58 +04:00
int cmd ;
2003-11-13 16:14:28 +03:00
struct dm_names * names = ( struct dm_names * ) data ;
2006-01-31 17:50:38 +03:00
const char * name = NULL ;
2005-05-16 18:53:23 +04:00
int matched = 0 ;
2005-05-16 20:04:34 +04:00
int ls_only = 0 ;
2005-10-26 21:50:15 +04:00
struct dm_info info ;
2003-09-16 18:13:51 +04:00
if ( data )
name = names - > name ;
2004-10-01 23:11:37 +04:00
else {
if ( argc = = 1 & & ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] )
2006-06-18 15:51:46 +04:00
return _process_all ( argc , argv , 0 , _status ) ;
2004-10-01 23:11:37 +04:00
if ( argc = = 2 )
name = argv [ 1 ] ;
}
2002-05-03 15:55:58 +04:00
2003-11-13 16:14:28 +03:00
if ( ! strcmp ( argv [ 0 ] , " table " ) )
2002-05-10 19:25:38 +04:00
cmd = DM_DEVICE_TABLE ;
2003-11-13 16:14:28 +03:00
else
cmd = DM_DEVICE_STATUS ;
2002-05-03 15:55:58 +04:00
2005-05-16 20:04:34 +04:00
if ( ! strcmp ( argv [ 0 ] , " ls " ) )
ls_only = 1 ;
2002-05-03 15:55:58 +04:00
if ( ! ( dmt = dm_task_create ( cmd ) ) )
return 0 ;
2004-10-01 23:11:37 +04:00
if ( ! _set_task_device ( dmt , name , 0 ) )
2002-05-03 15:55:58 +04:00
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2002-05-03 15:55:58 +04:00
if ( ! dm_task_run ( dmt ) )
goto out ;
2005-10-26 21:50:15 +04:00
if ( ! dm_task_get_info ( dmt , & info ) | | ! info . exists )
goto out ;
2005-07-29 20:11:23 +04:00
if ( ! name )
2006-01-31 17:50:38 +03:00
name = dm_task_get_name ( dmt ) ;
2005-07-29 20:11:23 +04:00
2002-05-03 15:55:58 +04:00
/* Fetch targets and print 'em */
do {
2002-05-10 19:25:38 +04:00
next = dm_get_next_target ( dmt , next , & start , & length ,
& target_type , & params ) ;
2005-05-16 18:53:23 +04:00
/* Skip if target type doesn't match */
2005-07-29 20:11:23 +04:00
if ( _switches [ TARGET_ARG ] & &
( ! target_type | | strcmp ( target_type , _target ) ) )
2005-05-16 18:53:23 +04:00
continue ;
2005-05-16 20:04:34 +04:00
if ( ls_only ) {
2005-05-17 00:46:46 +04:00
if ( ! _switches [ EXEC_ARG ] | | ! _command | |
_switches [ VERBOSE_ARG ] )
_display_dev ( dmt , name ) ;
2005-05-16 20:04:34 +04:00
next = NULL ;
2005-05-17 00:46:46 +04:00
} else if ( ! _switches [ EXEC_ARG ] | | ! _command | |
_switches [ VERBOSE_ARG ] ) {
2005-05-16 20:04:34 +04:00
if ( ! matched & & _switches [ VERBOSE_ARG ] )
_display_info ( dmt ) ;
if ( data & & ! _switches [ VERBOSE_ARG ] )
printf ( " %s: " , name ) ;
if ( target_type ) {
2006-10-19 19:34:50 +04:00
/* Suppress encryption key */
if ( ! _switches [ SHOWKEYS_ARG ] & &
! strcmp ( target_type , " crypt " ) ) {
c = params ;
while ( * c & & * c ! = ' ' )
c + + ;
c + + ;
while ( * c & & * c ! = ' ' )
* c + + = ' 0 ' ;
}
2005-05-16 20:04:34 +04:00
printf ( " % " PRIu64 " % " PRIu64 " %s %s " ,
start , length , target_type , params ) ;
}
printf ( " \n " ) ;
2002-05-10 19:25:38 +04:00
}
2005-05-16 18:53:23 +04:00
matched = 1 ;
2002-05-03 15:55:58 +04:00
} while ( next ) ;
2005-05-16 20:04:34 +04:00
if ( data & & _switches [ VERBOSE_ARG ] & & matched & & ! ls_only )
2003-09-16 18:13:51 +04:00
printf ( " \n " ) ;
2005-05-17 00:46:46 +04:00
if ( matched & & _switches [ EXEC_ARG ] & & _command & & ! _exec_command ( name ) )
goto out ;
2002-05-03 15:55:58 +04:00
r = 1 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2004-01-23 17:37:47 +03:00
/* Show target names and their version numbers */
2006-05-16 20:20:29 +04:00
static int _targets ( int argc __attribute ( ( unused ) ) , char * * argv __attribute ( ( unused ) ) , void * data __attribute ( ( unused ) ) )
2004-01-23 17:37:47 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
struct dm_versions * target ;
struct dm_versions * last_target ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_LIST_VERSIONS ) ) )
return 0 ;
if ( ! dm_task_run ( dmt ) )
goto out ;
target = dm_task_get_versions ( dmt ) ;
/* Fetch targets and print 'em */
do {
last_target = target ;
printf ( " %-16s v%d.%d.%d \n " , target - > name , target - > version [ 0 ] ,
target - > version [ 1 ] , target - > version [ 2 ] ) ;
target = ( void * ) target + target - > next ;
} while ( last_target ! = target ) ;
r = 1 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2003-09-16 18:13:51 +04:00
static int _info ( int argc , char * * argv , void * data )
2001-11-21 15:47:42 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
2003-11-13 16:14:28 +03:00
struct dm_names * names = ( struct dm_names * ) data ;
2004-03-30 18:31:58 +04:00
char * name = NULL ;
2003-09-16 18:13:51 +04:00
if ( data )
name = names - > name ;
2004-10-01 23:11:37 +04:00
else {
if ( argc = = 1 & & ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] )
2006-06-18 15:51:46 +04:00
return _process_all ( argc , argv , 0 , _info ) ;
2004-10-01 23:11:37 +04:00
if ( argc = = 2 )
name = argv [ 1 ] ;
}
2001-11-21 15:47:42 +03:00
2004-03-30 18:31:58 +04:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_INFO ) ) )
2001-11-21 15:47:42 +03:00
return 0 ;
2004-10-01 23:11:37 +04:00
if ( ! _set_task_device ( dmt , name , 0 ) )
2001-11-21 15:47:42 +03:00
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2001-11-21 15:47:42 +03:00
if ( ! dm_task_run ( dmt ) )
goto out ;
2005-03-27 15:37:46 +04:00
r = _display_info ( dmt ) ;
2001-11-21 15:47:42 +03:00
2002-03-07 23:56:10 +03:00
out :
2001-11-21 15:47:42 +03:00
dm_task_destroy ( dmt ) ;
return r ;
}
2003-09-16 18:13:51 +04:00
static int _deps ( int argc , char * * argv , void * data )
2002-03-06 17:38:25 +03:00
{
2003-03-28 21:58:59 +03:00
int r = 0 ;
uint32_t i ;
2002-03-06 17:38:25 +03:00
struct dm_deps * deps ;
struct dm_task * dmt ;
struct dm_info info ;
2003-11-13 16:14:28 +03:00
struct dm_names * names = ( struct dm_names * ) data ;
2004-10-01 23:11:37 +04:00
char * name = NULL ;
2003-09-16 18:13:51 +04:00
if ( data )
name = names - > name ;
2004-10-01 23:11:37 +04:00
else {
if ( argc = = 1 & & ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] )
2006-06-18 15:51:46 +04:00
return _process_all ( argc , argv , 0 , _deps ) ;
2004-10-01 23:11:37 +04:00
if ( argc = = 2 )
name = argv [ 1 ] ;
}
2002-03-06 17:38:25 +03:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_DEPS ) ) )
return 0 ;
2004-10-01 23:11:37 +04:00
if ( ! _set_task_device ( dmt , name , 0 ) )
2002-03-06 17:38:25 +03:00
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2002-03-06 17:38:25 +03:00
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 ;
}
2003-07-04 23:38:49 +04:00
if ( _switches [ VERBOSE_ARG ] )
_display_info ( dmt ) ;
2003-07-02 01:20:58 +04:00
2003-09-16 18:13:51 +04:00
if ( data & & ! _switches [ VERBOSE_ARG ] )
printf ( " %s: " , name ) ;
2002-03-06 17:38:25 +03:00
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 " ) ;
2003-09-16 18:13:51 +04:00
if ( data & & _switches [ VERBOSE_ARG ] )
printf ( " \n " ) ;
2002-03-06 17:38:25 +03:00
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 ;
}
2006-05-16 20:20:29 +04:00
static int _display_name ( int argc __attribute ( ( unused ) ) , char * * argv __attribute ( ( unused ) ) , void * data )
2003-07-02 01:20:58 +04:00
{
2003-11-13 16:14:28 +03:00
struct dm_names * names = ( struct dm_names * ) data ;
2003-07-02 01:20:58 +04:00
2003-09-16 18:13:51 +04:00
printf ( " %s \t (%d, %d) \n " , names - > name ,
( int ) MAJOR ( names - > dev ) , ( int ) MINOR ( names - > dev ) ) ;
2003-07-02 01:20:58 +04:00
2003-09-16 18:13:51 +04:00
return 1 ;
}
2003-07-02 01:20:58 +04:00
2005-10-16 18:33:22 +04:00
/*
* Tree drawing code
*/
enum {
TR_DEVICE = 0 , /* display device major:minor number */
TR_TABLE ,
TR_STATUS ,
TR_ACTIVE ,
TR_RW ,
TR_OPENCOUNT ,
TR_UUID ,
TR_COMPACT ,
TR_TRUNCATE ,
TR_BOTTOMUP ,
NUM_TREEMODE ,
} ;
static int _tree_switches [ NUM_TREEMODE ] ;
# define TR_PRINT_ATTRIBUTE ( _tree_switches[TR_ACTIVE] || \
_tree_switches [ TR_RW ] | | \
_tree_switches [ TR_OPENCOUNT ] | | \
_tree_switches [ TR_UUID ] )
# define TR_PRINT_TARGETS ( _tree_switches[TR_TABLE] || \
_tree_switches [ TR_STATUS ] )
/* Compact - fewer newlines */
# define TR_PRINT_COMPACT (_tree_switches[TR_COMPACT] && \
! TR_PRINT_ATTRIBUTE & & \
! TR_PRINT_TARGETS )
/* FIXME Get rid of this */
# define MAX_DEPTH 100
/* Drawing character definition from pstree */
/* [pstree comment] UTF-8 defines by Johan Myreen, updated by Ben Winslow */
# define UTF_V "\342\224\202" /* U+2502, Vertical line drawing char */
# define UTF_VR "\342\224\234" /* U+251C, Vertical and right */
# define UTF_H "\342\224\200" /* U+2500, Horizontal */
# define UTF_UR "\342\224\224" /* U+2514, Up and right */
# define UTF_HD "\342\224\254" /* U+252C, Horizontal and down */
# define VT_BEG "\033(0\017" /* use graphic chars */
# define VT_END "\033(B" /* back to normal char set */
# define VT_V "x" /* see UTF definitions above */
# define VT_VR "t"
# define VT_H "q"
# define VT_UR "m"
# define VT_HD "w"
static struct {
const char * empty_2 ; /* */
const char * branch_2 ; /* |- */
const char * vert_2 ; /* | */
const char * last_2 ; /* `- */
const char * single_3 ; /* --- */
const char * first_3 ; /* -+- */
}
_tsym_ascii = {
" " ,
" |- " ,
" | " ,
" `- " ,
" --- " ,
" -+- "
} ,
_tsym_utf = {
" " ,
UTF_VR UTF_H ,
UTF_V " " ,
UTF_UR UTF_H ,
UTF_H UTF_H UTF_H ,
UTF_H UTF_HD UTF_H
} ,
_tsym_vt100 = {
" " ,
VT_BEG VT_VR VT_H VT_END ,
VT_BEG VT_V VT_END " " ,
VT_BEG VT_UR VT_H VT_END ,
VT_BEG VT_H VT_H VT_H VT_END ,
VT_BEG VT_H VT_HD VT_H VT_END
} ,
* _tsym = & _tsym_ascii ;
/*
* Tree drawing functions .
*/
/* FIXME Get rid of these statics - use dynamic struct */
/* FIXME Explain what these vars are for */
static int _tree_width [ MAX_DEPTH ] , _tree_more [ MAX_DEPTH ] ;
static int _termwidth = 80 ; /* Maximum output width */
static int _cur_x = 1 ; /* Current horizontal output position */
static char _last_char = 0 ;
2006-05-16 20:20:29 +04:00
static void _out_char ( const unsigned c )
2005-10-16 18:33:22 +04:00
{
/* Only first UTF-8 char counts */
_cur_x + = ( ( c & 0xc0 ) ! = 0x80 ) ;
if ( ! _tree_switches [ TR_TRUNCATE ] ) {
2006-05-16 20:20:29 +04:00
putchar ( ( int ) c ) ;
2005-10-16 18:33:22 +04:00
return ;
}
/* Truncation? */
if ( _cur_x < = _termwidth )
2006-05-16 20:20:29 +04:00
putchar ( ( int ) c ) ;
2005-10-16 18:33:22 +04:00
if ( _cur_x = = _termwidth + 1 & & ( ( c & 0xc0 ) ! = 0x80 ) ) {
if ( _last_char | | ( c & 0x80 ) ) {
putchar ( ' . ' ) ;
putchar ( ' . ' ) ;
putchar ( ' . ' ) ;
} else {
_last_char = c ;
_cur_x - - ;
}
}
}
2006-05-16 20:20:29 +04:00
static void _out_string ( const unsigned char * str )
2005-10-16 18:33:22 +04:00
{
while ( * str )
_out_char ( * str + + ) ;
}
/* non-negative integers only */
static unsigned _out_int ( unsigned num )
{
unsigned digits = 0 ;
unsigned divi ;
if ( ! num ) {
_out_char ( ' 0 ' ) ;
return 1 ;
}
/* non zero case */
for ( divi = 1 ; num / divi ; divi * = 10 )
digits + + ;
for ( divi / = 10 ; divi ; divi / = 10 )
_out_char ( ' 0 ' + ( num / divi ) % 10 ) ;
return digits ;
}
static void _out_newline ( void )
{
if ( _last_char & & _cur_x = = _termwidth )
putchar ( _last_char ) ;
_last_char = 0 ;
putchar ( ' \n ' ) ;
_cur_x = 1 ;
}
2006-05-16 20:20:29 +04:00
static void _out_prefix ( unsigned depth )
2005-10-16 18:33:22 +04:00
{
2006-05-16 20:20:29 +04:00
unsigned x , d ;
2005-10-16 18:33:22 +04:00
for ( d = 0 ; d < depth ; d + + ) {
for ( x = _tree_width [ d ] + 1 ; x > 0 ; x - - )
_out_char ( ' ' ) ;
_out_string ( d = = depth - 1 ?
! _tree_more [ depth ] ? _tsym - > last_2 : _tsym - > branch_2
: _tree_more [ d + 1 ] ?
_tsym - > vert_2 : _tsym - > empty_2 ) ;
}
}
/*
* Display tree
*/
2005-11-09 17:10:50 +03:00
static void _display_tree_attributes ( struct dm_tree_node * node )
2005-10-16 18:33:22 +04:00
{
int attr = 0 ;
const char * uuid ;
const struct dm_info * info ;
2005-11-09 17:10:50 +03:00
uuid = dm_tree_node_get_uuid ( node ) ;
info = dm_tree_node_get_info ( node ) ;
2005-10-16 18:33:22 +04:00
if ( ! info - > exists )
return ;
if ( _tree_switches [ TR_ACTIVE ] ) {
_out_string ( attr + + ? " , " : " [ " ) ;
_out_string ( info - > suspended ? " SUSPENDED " : " ACTIVE " ) ;
}
if ( _tree_switches [ TR_RW ] ) {
_out_string ( attr + + ? " , " : " [ " ) ;
_out_string ( info - > read_only ? " RO " : " RW " ) ;
}
if ( _tree_switches [ TR_OPENCOUNT ] ) {
_out_string ( attr + + ? " , " : " [ " ) ;
2006-05-16 20:20:29 +04:00
( void ) _out_int ( ( unsigned ) info - > open_count ) ;
2005-10-16 18:33:22 +04:00
}
if ( _tree_switches [ TR_UUID ] ) {
_out_string ( attr + + ? " , " : " [ " ) ;
_out_string ( uuid & & * uuid ? uuid : " " ) ;
}
if ( attr )
_out_char ( ' ] ' ) ;
}
2005-11-09 17:10:50 +03:00
static void _display_tree_node ( struct dm_tree_node * node , unsigned depth ,
2006-05-16 20:20:29 +04:00
unsigned first_child __attribute ( ( unused ) ) ,
unsigned last_child , unsigned has_children )
2005-10-16 18:33:22 +04:00
{
int offset ;
const char * name ;
const struct dm_info * info ;
int first_on_line = 0 ;
/* Sub-tree for targets has 2 more depth */
if ( depth + 2 > MAX_DEPTH )
return ;
2005-11-09 17:10:50 +03:00
name = dm_tree_node_get_name ( node ) ;
2005-10-16 18:33:22 +04:00
if ( ( ! name | | ! * name ) & & ! _tree_switches [ TR_DEVICE ] )
return ;
/* Indicate whether there are more nodes at this depth */
_tree_more [ depth ] = ! last_child ;
_tree_width [ depth ] = 0 ;
if ( _cur_x = = 1 )
first_on_line = 1 ;
if ( ! TR_PRINT_COMPACT | | first_on_line )
_out_prefix ( depth ) ;
/* Remember the starting point for compact */
offset = _cur_x ;
if ( TR_PRINT_COMPACT & & ! first_on_line )
_out_string ( _tree_more [ depth ] ? _tsym - > first_3 : _tsym - > single_3 ) ;
/* display node */
if ( name )
_out_string ( name ) ;
2005-11-09 17:10:50 +03:00
info = dm_tree_node_get_info ( node ) ;
2005-10-16 18:33:22 +04:00
if ( _tree_switches [ TR_DEVICE ] ) {
_out_string ( name ? " ( " : " ( " ) ;
( void ) _out_int ( info - > major ) ;
_out_char ( ' : ' ) ;
( void ) _out_int ( info - > minor ) ;
_out_char ( ' ) ' ) ;
}
/* display additional info */
if ( TR_PRINT_ATTRIBUTE )
_display_tree_attributes ( node ) ;
if ( TR_PRINT_COMPACT )
_tree_width [ depth ] = _cur_x - offset ;
if ( ! TR_PRINT_COMPACT | | ! has_children )
_out_newline ( ) ;
if ( TR_PRINT_TARGETS ) {
_tree_more [ depth + 1 ] = has_children ;
// FIXME _display_tree_targets(name, depth + 2);
}
}
/*
* Walk the dependency tree
*/
2005-11-09 17:10:50 +03:00
static void _tree_walk_children ( struct dm_tree_node * node , unsigned depth )
2005-10-16 18:33:22 +04:00
{
2005-11-09 17:10:50 +03:00
struct dm_tree_node * child , * next_child ;
2005-10-16 18:33:22 +04:00
void * handle = NULL ;
uint32_t inverted = _tree_switches [ TR_BOTTOMUP ] ;
unsigned first_child = 1 ;
unsigned has_children ;
2005-11-09 17:10:50 +03:00
next_child = dm_tree_next_child ( & handle , node , inverted ) ;
2005-10-16 18:33:22 +04:00
while ( ( child = next_child ) ) {
2005-11-09 17:10:50 +03:00
next_child = dm_tree_next_child ( & handle , node , inverted ) ;
2005-10-16 18:33:22 +04:00
has_children =
2005-11-09 17:10:50 +03:00
dm_tree_node_num_children ( child , inverted ) ? 1 : 0 ;
2005-10-16 18:33:22 +04:00
_display_tree_node ( child , depth , first_child ,
2006-05-16 20:20:29 +04:00
next_child ? 0U : 1U , has_children ) ;
2005-10-16 18:33:22 +04:00
if ( has_children )
_tree_walk_children ( child , depth + 1 ) ;
first_child = 0 ;
}
}
2006-05-16 20:20:29 +04:00
static int _add_dep ( int argc __attribute ( ( unused ) ) , char * * argv __attribute ( ( unused ) ) , void * data )
2005-10-16 18:33:22 +04:00
{
struct dm_names * names = ( struct dm_names * ) data ;
2006-05-16 20:20:29 +04:00
if ( ! dm_tree_add_dev ( _dtree , ( unsigned ) MAJOR ( names - > dev ) , ( unsigned ) MINOR ( names - > dev ) ) )
2005-10-16 18:33:22 +04:00
return 0 ;
return 1 ;
}
/*
* Create and walk dependency tree
*/
2006-05-16 20:20:29 +04:00
static int _tree ( int argc , char * * argv , void * data __attribute ( ( unused ) ) )
2005-10-16 18:33:22 +04:00
{
2005-11-09 17:10:50 +03:00
if ( ! ( _dtree = dm_tree_create ( ) ) )
2005-10-16 18:33:22 +04:00
return 0 ;
2006-06-18 15:51:46 +04:00
if ( ! _process_all ( argc , argv , 0 , _add_dep ) )
2005-10-16 18:33:22 +04:00
return 0 ;
2005-11-09 17:10:50 +03:00
_tree_walk_children ( dm_tree_find_node ( _dtree , 0 , 0 ) , 0 ) ;
2005-10-16 18:33:22 +04:00
2005-11-09 17:10:50 +03:00
dm_tree_free ( _dtree ) ;
2005-10-16 18:33:22 +04:00
return 1 ;
}
/*
* List devices
*/
2003-09-16 18:13:51 +04:00
static int _ls ( int argc , char * * argv , void * data )
{
2005-05-17 00:46:46 +04:00
if ( ( _switches [ TARGET_ARG ] & & _target ) | |
( _switches [ EXEC_ARG ] & & _command ) )
2005-05-16 20:04:34 +04:00
return _status ( argc , argv , data ) ;
2005-10-16 18:33:22 +04:00
else if ( ( _switches [ TREE_ARG ] ) )
return _tree ( argc , argv , data ) ;
2005-05-16 20:04:34 +04:00
else
2006-06-18 15:51:46 +04:00
return _process_all ( argc , argv , 0 , _display_name ) ;
2003-07-02 01:20:58 +04:00
}
2001-11-21 15:47:42 +03:00
/*
* dispatch table
*/
2003-09-16 18:13:51 +04:00
typedef int ( * command_fn ) ( int argc , char * * argv , void * data ) ;
2001-11-21 15:47:42 +03:00
struct command {
2003-01-22 00:25:51 +03:00
const char * name ;
const 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 [ ] = {
2004-10-01 23:11:37 +04:00
{ " create " , " <dev_name> [-j|--major <major> -m|--minor <minor>] \n "
2006-02-03 17:23:22 +03:00
" \t [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>] \n "
2006-10-12 21:09:09 +04:00
" \t [-u|uuid <uuid>] \n "
2006-08-10 18:11:03 +04:00
" \t [--notable | --table <table> | <table_file>] " ,
2003-11-12 20:30:32 +03:00
1 , 2 , _create } ,
2006-06-18 15:35:04 +04:00
{ " remove " , " [-f|--force] <device> " , 0 , 1 , _remove } ,
{ " remove_all " , " [-f|--force] " , 0 , 0 , _remove_all } ,
2006-10-12 21:09:09 +04:00
{ " suspend " , " [--noflush] <device> " , 0 , 1 , _suspend } ,
2004-10-01 23:11:37 +04:00
{ " resume " , " <device> " , 0 , 1 , _resume } ,
{ " load " , " <device> [<table_file>] " , 0 , 2 , _load } ,
{ " clear " , " <device> " , 0 , 1 , _clear } ,
{ " reload " , " <device> [<table_file>] " , 0 , 2 , _load } ,
{ " rename " , " <device> <new_name> " , 1 , 2 , _rename } ,
{ " message " , " <device> <sector> <message> " , 2 , - 1 , _message } ,
2006-04-06 20:20:40 +04:00
{ " ls " , " [--target <target_type>] [--exec <command>] [--tree [-o options]] " , 0 , 0 , _ls } ,
2004-10-01 23:11:37 +04:00
{ " info " , " [<device>] " , 0 , 1 , _info } ,
{ " deps " , " [<device>] " , 0 , 1 , _deps } ,
2005-05-16 18:53:23 +04:00
{ " status " , " [<device>] [--target <target_type>] " , 0 , 1 , _status } ,
2006-10-19 19:34:50 +04:00
{ " table " , " [<device>] [--target <target_type>] [--showkeys] " , 0 , 1 , _status } ,
2004-10-01 23:11:37 +04:00
{ " wait " , " <device> [<event_nr>] " , 0 , 2 , _wait } ,
{ " mknodes " , " [<device>] " , 0 , 1 , _mknodes } ,
2004-01-23 17:37:47 +03:00
{ " targets " , " " , 0 , 0 , _targets } ,
2002-03-12 01:44:36 +03:00
{ " version " , " " , 0 , 0 , _version } ,
2006-02-21 02:55:58 +03:00
{ " setgeometry " , " <device> <cyl> <head> <sect> <start> " , 5 , 5 , _setgeometry } ,
2002-03-12 01:44:36 +03:00
{ NULL , NULL , 0 , 0 , NULL }
2001-11-21 15:47:42 +03:00
} ;
2003-04-04 17:22:58 +04:00
static void _usage ( FILE * out )
2001-11-21 15:47:42 +03:00
{
int i ;
2003-07-04 23:38:49 +04:00
fprintf ( out , " Usage: \n \n " ) ;
fprintf ( out , " dmsetup [--version] [-v|--verbose [-v|--verbose ...]] \n "
2006-10-12 21:09:09 +04:00
" [-r|--readonly] [--noopencount] [--nolockfs] \n \n " ) ;
2001-11-21 15:47:42 +03:00
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 ) ;
2004-10-01 23:11:37 +04:00
fprintf ( out , " \n <device> may be device name or -u <uuid> or "
" -j <major> -m <minor> \n " ) ;
2006-04-06 20:20:40 +04:00
fprintf ( out , " Table_file contents may be supplied on stdin. \n " ) ;
fprintf ( out , " Tree options are: ascii, utf, vt100; compact, inverted, notrunc; \n "
" [no]device, active, open, rw and uuid. \n \n " ) ;
2001-11-21 15:47:42 +03:00
return ;
}
2006-10-12 19:42:25 +04:00
static void _losetup_usage ( FILE * out )
{
fprintf ( out , " Usage: \n \n " ) ;
fprintf ( out , " losetup [-d|-a] [-e encryption] "
" [-o offset] [-f|loop_device] [file] \n \n " ) ;
}
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 ;
}
2005-10-16 18:33:22 +04:00
static int _process_tree_options ( const char * options )
{
const char * s , * end ;
struct winsize winsz ;
int len ;
/* Symbol set default */
if ( ! strcmp ( nl_langinfo ( CODESET ) , " UTF-8 " ) )
_tsym = & _tsym_utf ;
else
_tsym = & _tsym_ascii ;
/* Default */
_tree_switches [ TR_DEVICE ] = 1 ;
_tree_switches [ TR_TRUNCATE ] = 1 ;
/* parse */
for ( s = options ; s & & * s ; s + + ) {
len = 0 ;
for ( end = s ; * end & & * end ! = ' , ' ; end + + , len + + )
;
if ( ! strncmp ( s , " device " , len ) )
_tree_switches [ TR_DEVICE ] = 1 ;
else if ( ! strncmp ( s , " nodevice " , len ) )
_tree_switches [ TR_DEVICE ] = 0 ;
else if ( ! strncmp ( s , " status " , len ) )
_tree_switches [ TR_STATUS ] = 1 ;
else if ( ! strncmp ( s , " table " , len ) )
_tree_switches [ TR_TABLE ] = 1 ;
else if ( ! strncmp ( s , " active " , len ) )
_tree_switches [ TR_ACTIVE ] = 1 ;
else if ( ! strncmp ( s , " open " , len ) )
_tree_switches [ TR_OPENCOUNT ] = 1 ;
else if ( ! strncmp ( s , " uuid " , len ) )
_tree_switches [ TR_UUID ] = 1 ;
else if ( ! strncmp ( s , " rw " , len ) )
_tree_switches [ TR_RW ] = 1 ;
else if ( ! strncmp ( s , " utf " , len ) )
_tsym = & _tsym_utf ;
else if ( ! strncmp ( s , " vt100 " , len ) )
_tsym = & _tsym_vt100 ;
else if ( ! strncmp ( s , " ascii " , len ) )
_tsym = & _tsym_ascii ;
else if ( ! strncmp ( s , " inverted " , len ) )
_tree_switches [ TR_BOTTOMUP ] = 1 ;
else if ( ! strncmp ( s , " compact " , len ) )
_tree_switches [ TR_COMPACT ] = 1 ;
else if ( ! strncmp ( s , " notrunc " , len ) )
_tree_switches [ TR_TRUNCATE ] = 0 ;
else {
fprintf ( stderr , " Tree options not recognised: %s \n " , s ) ;
return 0 ;
}
if ( ! * end )
break ;
s = end ;
}
/* Truncation doesn't work well with vt100 drawing char */
if ( _tsym ! = & _tsym_vt100 )
if ( ioctl ( 1 , TIOCGWINSZ , & winsz ) > = 0 & & winsz . ws_col > 3 )
_termwidth = winsz . ws_col - 3 ;
return 1 ;
}
2006-10-12 19:42:25 +04:00
/*
* Returns the full absolute path , or NULL if the path could
* not be resolved .
*/
static char * _get_abspath ( char * path )
{
char * _path ;
# ifdef HAVE_CANONICALIZE_FILE_NAME
_path = canonicalize_file_name ( path ) ;
# else
/* FIXME Provide alternative */
# endif
return _path ;
}
static char * parse_loop_device_name ( char * dev )
{
char * buf ;
char * device ;
if ( ! ( buf = dm_malloc ( PATH_MAX ) ) ) ;
return NULL ;
if ( dev [ 0 ] = = ' / ' ) {
if ( ! ( device = _get_abspath ( dev ) ) )
goto error ;
if ( strncmp ( device , DEV_PATH , strlen ( DEV_PATH ) ) )
goto error ;
strncpy ( buf , strrchr ( device , ' / ' ) + 1 , PATH_MAX ) ;
dm_free ( device ) ;
} else {
/* check for device number */
if ( ! strncmp ( dev , " loop " , strlen ( " loop " ) ) )
strncpy ( buf , dev , PATH_MAX ) ;
else
goto error ;
}
return buf ;
error :
return NULL ;
}
/*
* create a table for a mapped device using the loop target .
*/
static int _loop_table ( char * table , size_t tlen , char * file , char * dev , off_t off )
{
struct stat fbuf ;
off_t size , sectors ;
int fd = - 1 ;
# ifdef HAVE_SYS_STATVFS_H
struct statvfs fsbuf ;
off_t blksize ;
# endif
if ( ! _switches [ READ_ONLY ] )
fd = open ( file , O_RDWR ) ;
if ( fd < 0 ) {
_switches [ READ_ONLY ] + + ;
fd = open ( file , O_RDONLY ) ;
}
if ( fd < 0 )
goto error ;
if ( fstat ( fd , & fbuf ) )
goto error ;
size = ( fbuf . st_size - off ) ;
sectors = size > > SECTOR_SHIFT ;
if ( _switches [ VERBOSE_ARG ] )
fprintf ( stderr , " losetup: set loop size to %llukB (%llu sectors) \n " ,
sectors > > 1 , sectors ) ;
# ifdef HAVE_SYS_STATVFS_H
if ( fstatvfs ( fd , & fsbuf ) )
goto error ;
/* FIXME Fragment size currently unused */
blksize = fsbuf . f_frsize ;
# endif
close ( fd ) ;
if ( dm_snprintf ( table , tlen , " %llu %llu loop %s %llu \n " , 0ULL ,
( long long unsigned ) sectors , file , off ) < 0 )
return 0 ;
if ( _switches [ VERBOSE_ARG ] > 1 )
fprintf ( stderr , " Table: %s \n " , table ) ;
return 1 ;
error :
if ( fd > - 1 )
close ( fd ) ;
return 0 ;
}
static int _process_losetup_switches ( const char * base , int * argc , char * * * argv )
{
static int ind ;
int c ;
int encrypt_loop = 0 , delete = 0 , find = 0 , show_all = 0 ;
char * device_name = NULL ;
char * loop_file = NULL ;
off_t offset = 0 ;
# ifdef HAVE_GETOPTLONG
static struct option long_options [ ] = {
{ 0 , 0 , 0 , 0 }
} ;
# endif
optarg = 0 ;
optind = OPTIND_INIT ;
while ( ( ind = - 1 , c = GETOPTLONG_FN ( * argc , * argv , " ade:fo:v " ,
long_options , NULL ) ) ! = - 1 ) {
if ( c = = ' : ' | | c = = ' ? ' )
return 0 ;
if ( c = = ' a ' )
show_all + + ;
if ( c = = ' d ' )
delete + + ;
if ( c = = ' e ' )
encrypt_loop + + ;
if ( c = = ' f ' )
find + + ;
if ( c = = ' o ' )
offset = atoi ( optarg ) ;
if ( c = = ' v ' )
_switches [ VERBOSE_ARG ] + + ;
}
* argv + = optind ;
* argc - = optind ;
if ( encrypt_loop ) {
fprintf ( stderr , " %s: Sorry, cryptoloop is not yet implemented "
" in this version. \n " , base ) ;
return 0 ;
}
if ( show_all ) {
fprintf ( stderr , " %s: Sorry, show all is not yet implemented "
" in this version. \n " , base ) ;
return 0 ;
}
if ( find ) {
fprintf ( stderr , " %s: Sorry, find is not yet implemented "
" in this version. \n " , base ) ;
if ( ! * argc )
return 0 ;
}
if ( ! * argc ) {
fprintf ( stderr , " %s: Please specify loop_device. \n " , base ) ;
_losetup_usage ( stderr ) ;
return 0 ;
}
if ( ! ( device_name = parse_loop_device_name ( ( * argv ) [ 0 ] ) ) ) {
fprintf ( stderr , " %s: Could not parse loop_device %s \n " ,
base , ( * argv ) [ 0 ] ) ;
_losetup_usage ( stderr ) ;
return 0 ;
}
if ( delete ) {
* argc = 2 ;
( * argv ) [ 1 ] = device_name ;
( * argv ) [ 0 ] = ( char * ) " remove " ;
return 1 ;
}
if ( * argc ! = 2 ) {
fprintf ( stderr , " %s: Too few arguments \n " , base ) ;
_losetup_usage ( stderr ) ;
return 0 ;
}
/* FIXME move these to make them available to native dmsetup */
if ( ! ( loop_file = _get_abspath ( ( * argv ) [ ( find ) ? 0 : 1 ] ) ) ) {
fprintf ( stderr , " %s: Could not parse loop file name %s \n " ,
base , ( * argv ) [ 1 ] ) ;
_losetup_usage ( stderr ) ;
return 0 ;
}
/* FIXME Missing free */
_table = dm_malloc ( LOOP_TABLE_SIZE ) ;
if ( ! _loop_table ( _table , LOOP_TABLE_SIZE , loop_file , device_name , offset ) ) {
fprintf ( stderr , " Could not build device-mapper table for %s \n " , ( * argv ) [ 0 ] ) ;
return 0 ;
}
_switches [ TABLE_ARG ] + + ;
( * argv ) [ 0 ] = ( char * ) " create " ;
( * argv ) [ 1 ] = device_name ;
return 1 ;
}
2002-01-03 13:39:21 +03:00
static int _process_switches ( int * argc , char * * * argv )
{
2005-03-27 15:37:46 +04:00
char * base , * namebase ;
2005-05-16 18:53:23 +04:00
static int ind ;
2006-10-12 19:42:25 +04:00
int c , r ;
2002-01-03 13:39:21 +03:00
2003-11-12 20:30:32 +03:00
# ifdef HAVE_GETOPTLONG
2002-01-03 13:39:21 +03:00
static struct option long_options [ ] = {
2005-05-16 18:53:23 +04:00
{ " readonly " , 0 , & ind , READ_ONLY } ,
{ " columns " , 0 , & ind , COLS_ARG } ,
2005-05-17 00:46:46 +04:00
{ " exec " , 1 , & ind , EXEC_ARG } ,
2006-06-18 15:35:04 +04:00
{ " force " , 0 , & ind , FORCE_ARG } ,
2006-02-03 17:23:22 +03:00
{ " gid " , 1 , & ind , GID_ARG } ,
2005-05-16 18:53:23 +04:00
{ " major " , 1 , & ind , MAJOR_ARG } ,
{ " minor " , 1 , & ind , MINOR_ARG } ,
2006-02-03 17:23:22 +03:00
{ " mode " , 1 , & ind , MODE_ARG } ,
2006-10-12 19:42:25 +04:00
{ " noflush " , 0 , & ind , NOFLUSH_ARG } ,
2005-05-16 18:53:23 +04:00
{ " noheadings " , 0 , & ind , NOHEADINGS_ARG } ,
2005-10-05 00:12:32 +04:00
{ " nolockfs " , 0 , & ind , NOLOCKFS_ARG } ,
2005-05-16 18:53:23 +04:00
{ " noopencount " , 0 , & ind , NOOPENCOUNT_ARG } ,
{ " notable " , 0 , & ind , NOTABLE_ARG } ,
{ " options " , 1 , & ind , OPTIONS_ARG } ,
2006-10-19 19:34:50 +04:00
{ " showkeys " , 0 , & ind , SHOWKEYS_ARG } ,
2006-08-10 18:11:03 +04:00
{ " table " , 1 , & ind , TABLE_ARG } ,
2005-05-16 18:53:23 +04:00
{ " target " , 1 , & ind , TARGET_ARG } ,
2005-10-16 18:33:22 +04:00
{ " tree " , 0 , & ind , TREE_ARG } ,
2006-02-03 17:23:22 +03:00
{ " uid " , 1 , & ind , UID_ARG } ,
2005-05-16 18:53:23 +04:00
{ " uuid " , 1 , & ind , UUID_ARG } ,
{ " verbose " , 1 , & ind , VERBOSE_ARG } ,
{ " version " , 0 , & ind , VERSION_ARG } ,
2005-08-18 23:40:19 +04:00
{ 0 , 0 , 0 , 0 }
2002-01-03 13:39:21 +03:00
} ;
2003-11-12 20:30:32 +03:00
# else
struct option long_options ;
# endif
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
2005-03-27 15:37:46 +04:00
namebase = strdup ( ( * argv ) [ 0 ] ) ;
base = basename ( namebase ) ;
if ( ! strcmp ( base , " devmap_name " ) ) {
free ( namebase ) ;
_switches [ COLS_ARG ] + + ;
_switches [ NOHEADINGS_ARG ] + + ;
_switches [ OPTIONS_ARG ] + + ;
_switches [ MAJOR_ARG ] + + ;
_switches [ MINOR_ARG ] + + ;
_fields = ( char * ) " name " ;
if ( * argc = = 3 ) {
_values [ MAJOR_ARG ] = atoi ( ( * argv ) [ 1 ] ) ;
_values [ MINOR_ARG ] = atoi ( ( * argv ) [ 2 ] ) ;
* argc - = 2 ;
* argv + = 2 ;
2006-06-18 15:35:04 +04:00
} else if ( ( * argc = = 2 ) & &
2005-03-27 15:37:46 +04:00
( 2 = = sscanf ( ( * argv ) [ 1 ] , " %i:%i " ,
& _values [ MAJOR_ARG ] ,
& _values [ MINOR_ARG ] ) ) ) {
* argc - = 1 ;
* argv + = 1 ;
} else {
fprintf ( stderr , " Usage: devmap_name <major> <minor> \n " ) ;
return 0 ;
}
( * argv ) [ 0 ] = ( char * ) " info " ;
return 1 ;
}
2006-10-12 19:42:25 +04:00
if ( ! strcmp ( base , " losetup " ) | | ! strcmp ( base , " dmlosetup " ) ) {
r = _process_losetup_switches ( base , argc , argv ) ;
free ( namebase ) ;
return r ;
}
2005-03-27 15:37:46 +04:00
free ( namebase ) ;
2003-11-12 20:30:32 +03:00
optarg = 0 ;
optind = OPTIND_INIT ;
2006-06-18 15:35:04 +04:00
while ( ( ind = - 1 , c = GETOPTLONG_FN ( * argc , * argv , " cCfGj:m:Mno:ru:Uv " ,
2005-05-16 18:53:23 +04:00
long_options , NULL ) ) ! = - 1 ) {
2006-08-11 00:53:21 +04:00
if ( c = = ' : ' | | c = = ' ? ' )
2006-08-10 18:11:03 +04:00
return 0 ;
2004-06-16 20:44:12 +04:00
if ( c = = ' c ' | | c = = ' C ' | | ind = = COLS_ARG )
_switches [ COLS_ARG ] + + ;
2006-06-18 15:35:04 +04:00
if ( c = = ' f ' | | ind = = FORCE_ARG )
_switches [ FORCE_ARG ] + + ;
2003-01-22 00:25:51 +03:00
if ( c = = ' r ' | | ind = = READ_ONLY )
2002-01-03 13:39:21 +03:00
_switches [ READ_ONLY ] + + ;
2003-04-04 17:22:58 +04:00
if ( c = = ' j ' | | ind = = MAJOR_ARG ) {
_switches [ MAJOR_ARG ] + + ;
_values [ MAJOR_ARG ] = atoi ( optarg ) ;
}
2003-01-22 00:25:51 +03:00
if ( c = = ' m ' | | ind = = MINOR_ARG ) {
2002-01-11 15:12:46 +03:00
_switches [ MINOR_ARG ] + + ;
_values [ MINOR_ARG ] = atoi ( optarg ) ;
}
2003-11-12 20:30:32 +03:00
if ( c = = ' n ' | | ind = = NOTABLE_ARG )
_switches [ NOTABLE_ARG ] + + ;
2005-03-27 15:37:46 +04:00
if ( c = = ' o ' | | ind = = OPTIONS_ARG ) {
_switches [ OPTIONS_ARG ] + + ;
_fields = optarg ;
}
2003-01-22 00:25:51 +03:00
if ( c = = ' v ' | | ind = = VERBOSE_ARG )
_switches [ VERBOSE_ARG ] + + ;
2003-11-12 20:30:32 +03:00
if ( c = = ' u ' | | ind = = UUID_ARG ) {
_switches [ UUID_ARG ] + + ;
_uuid = optarg ;
}
2006-02-03 17:23:22 +03:00
if ( c = = ' G ' | | ind = = GID_ARG ) {
_switches [ GID_ARG ] + + ;
_values [ GID_ARG ] = atoi ( optarg ) ;
}
if ( c = = ' U ' | | ind = = UID_ARG ) {
_switches [ UID_ARG ] + + ;
_values [ UID_ARG ] = atoi ( optarg ) ;
}
if ( c = = ' M ' | | ind = = MODE_ARG ) {
_switches [ MODE_ARG ] + + ;
/* FIXME Accept modes as per chmod */
_values [ MODE_ARG ] = ( int ) strtol ( optarg , NULL , 8 ) ;
}
2005-05-17 00:46:46 +04:00
if ( ( ind = = EXEC_ARG ) ) {
_switches [ EXEC_ARG ] + + ;
_command = optarg ;
}
2005-05-16 18:53:23 +04:00
if ( ( ind = = TARGET_ARG ) ) {
_switches [ TARGET_ARG ] + + ;
_target = optarg ;
}
2006-10-12 19:42:25 +04:00
if ( ( ind = = NOFLUSH_ARG ) )
_switches [ NOFLUSH_ARG ] + + ;
2004-10-12 20:42:40 +04:00
if ( ( ind = = NOHEADINGS_ARG ) )
_switches [ NOHEADINGS_ARG ] + + ;
2005-10-05 00:12:32 +04:00
if ( ( ind = = NOLOCKFS_ARG ) )
_switches [ NOLOCKFS_ARG ] + + ;
2005-01-13 01:10:14 +03:00
if ( ( ind = = NOOPENCOUNT_ARG ) )
_switches [ NOOPENCOUNT_ARG ] + + ;
2006-10-19 19:34:50 +04:00
if ( ( ind = = SHOWKEYS_ARG ) )
_switches [ SHOWKEYS_ARG ] + + ;
2006-08-10 18:11:03 +04:00
if ( ( ind = = TABLE_ARG ) ) {
_switches [ TABLE_ARG ] + + ;
_table = optarg ;
}
2005-10-16 18:33:22 +04:00
if ( ( ind = = TREE_ARG ) )
_switches [ TREE_ARG ] + + ;
2003-07-04 23:38:49 +04:00
if ( ( ind = = VERSION_ARG ) )
_switches [ VERSION_ARG ] + + ;
2002-01-11 15:12:46 +03:00
}
2002-01-03 13:39:21 +03:00
2003-07-04 23:38:49 +04:00
if ( _switches [ VERBOSE_ARG ] > 1 )
dm_log_init_verbose ( _switches [ VERBOSE_ARG ] - 1 ) ;
2003-01-22 00:25:51 +03:00
2004-10-01 23:11:37 +04:00
if ( ( _switches [ MAJOR_ARG ] & & ! _switches [ MINOR_ARG ] ) | |
( ! _switches [ MAJOR_ARG ] & & _switches [ MINOR_ARG ] ) ) {
fprintf ( stderr , " Please specify both major number and "
" minor number. \n " ) ;
return 0 ;
}
2005-10-16 18:33:22 +04:00
if ( _switches [ COLS_ARG ] & & _switches [ OPTIONS_ARG ] & &
strcmp ( _fields , " name " ) ) {
2005-03-27 15:37:46 +04:00
fprintf ( stderr , " Only -o name is supported so far. \n " ) ;
return 0 ;
}
2005-10-16 18:33:22 +04:00
if ( _switches [ TREE_ARG ] & & ! _process_tree_options ( _fields ) )
return 0 ;
2006-08-10 18:11:03 +04:00
if ( _switches [ TABLE_ARG ] & & _switches [ NOTABLE_ARG ] ) {
fprintf ( stderr , " --table and --notable are incompatible. \n " ) ;
return 0 ;
}
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 ;
2005-10-16 18:33:22 +04:00
int r = 1 ;
2006-08-10 18:11:03 +04:00
( void ) setlocale ( LC_ALL , " " ) ;
2001-11-21 15:47:42 +03:00
2002-01-03 13:39:21 +03:00
if ( ! _process_switches ( & argc , & argv ) ) {
2005-03-27 15:37:46 +04:00
fprintf ( stderr , " Couldn't process command line. \n " ) ;
2005-10-16 18:33:22 +04:00
goto out ;
2002-01-03 13:39:21 +03:00
}
2003-07-04 23:38:49 +04:00
if ( _switches [ VERSION_ARG ] ) {
c = _find_command ( " version " ) ;
goto doit ;
}
2002-01-15 18:21:57 +03:00
if ( argc = = 0 ) {
2001-11-21 15:47:42 +03:00
_usage ( stderr ) ;
2005-10-16 18:33:22 +04:00
goto out ;
2001-11-21 15:47:42 +03:00
}
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 ) ;
2005-10-16 18:33:22 +04:00
goto out ;
2001-11-21 15:47:42 +03:00
}
2004-06-09 00:34:40 +04:00
if ( argc < c - > min_args + 1 | |
( c - > max_args > = 0 & & argc > c - > max_args + 1 ) ) {
2001-11-21 15:47:42 +03:00
fprintf ( stderr , " Incorrect number of arguments \n " ) ;
_usage ( stderr ) ;
2005-10-16 18:33:22 +04:00
goto out ;
2001-11-21 15:47:42 +03:00
}
2003-07-04 23:38:49 +04:00
doit :
2003-09-16 18:13:51 +04:00
if ( ! c - > fn ( argc , argv , NULL ) ) {
2001-12-14 16:30:04 +03:00
fprintf ( stderr , " Command failed \n " ) ;
2005-10-16 18:33:22 +04:00
goto out ;
2001-11-21 15:47:42 +03:00
}
2005-10-16 18:33:22 +04:00
r = 0 ;
out :
return r ;
2001-11-21 15:47:42 +03:00
}