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 .
2012-01-18 22:52:02 +04:00
* Copyright ( C ) 2004 - 2012 Red Hat , Inc . All rights reserved .
2007-08-21 20:26:07 +04:00
* Copyright ( C ) 2005 - 2007 NEC Corporation
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
2007-04-27 22:01:45 +04:00
# include "configure.h"
2006-05-10 23:38:25 +04:00
2008-10-30 20:24:04 +03:00
# include "dm-logging.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>
2009-08-06 19:05:10 +04:00
# include <time.h>
2005-10-16 18:33:22 +04:00
2006-10-12 19:42:25 +04:00
# include <fcntl.h>
# include <sys/stat.h>
2009-08-06 19:04:30 +04:00
# ifdef UDEV_SYNC_SUPPORT
# include <sys / types.h>
# include <sys / ipc.h>
# include <sys / sem.h>
2010-02-15 19:21:33 +03:00
# include <libudev.h>
# endif
2009-08-06 19:04:30 +04:00
2006-10-12 19:42:25 +04:00
/* 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)
2010-02-15 19:21:33 +03:00
# define DEFAULT_DM_DEV_DIR " / dev / "
# define DM_DEV_DIR_ENV_VAR_NAME "DM_DEV_DIR"
# define DM_UDEV_COOKIE_ENV_VAR_NAME "DM_UDEV_COOKIE"
2007-10-09 16:14:48 +04:00
2007-06-15 22:20:28 +04:00
/* FIXME Should be imported */
# ifndef DM_MAX_TYPE_NAME
# define DM_MAX_TYPE_NAME 16
# endif
2006-10-12 19:42:25 +04:00
/* FIXME Should be elsewhere */
# define SECTOR_SHIFT 9L
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 ,
2011-07-01 18:09:19 +04:00
ADD_NODE_ON_CREATE_ARG ,
ADD_NODE_ON_RESUME_ARG ,
CHECKS_ARG ,
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 ,
2010-03-08 19:05:07 +03:00
HELP_ARG ,
2009-11-06 03:43:08 +03:00
INACTIVE_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 ,
2008-06-06 22:53:08 +04:00
NAMEPREFIXES_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 ,
2010-02-15 19:21:33 +03:00
UDEVCOOKIE_ARG ,
2010-01-07 22:45:12 +03:00
NOUDEVRULES_ARG ,
2009-07-31 21:51:45 +04:00
NOUDEVSYNC_ARG ,
2005-03-27 15:37:46 +04:00
OPTIONS_ARG ,
2007-11-27 23:57:05 +03:00
READAHEAD_ARG ,
2011-09-22 21:12:28 +04:00
RETRY_ARG ,
2008-06-25 02:53:48 +04:00
ROWS_ARG ,
2007-01-18 20:47:58 +03:00
SEPARATOR_ARG ,
2010-10-15 05:10:27 +04:00
SETUUID_ARG ,
2006-10-19 19:34:50 +04:00
SHOWKEYS_ARG ,
2007-01-18 20:47:58 +03:00
SORT_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 ,
2007-06-15 22:20:28 +04:00
UNBUFFERED_ARG ,
2008-06-25 00:16:47 +04:00
UNQUOTED_ARG ,
2003-11-12 20:30:32 +03:00
UUID_ARG ,
2003-01-22 00:25:51 +03:00
VERBOSE_ARG ,
2011-06-28 01:43:58 +04:00
VERIFYUDEV_ARG ,
2003-07-04 23:38:49 +04:00
VERSION_ARG ,
2009-09-11 19:53:57 +04:00
YES_ARG ,
2002-01-03 13:39:21 +03:00
NUM_SWITCHES
} ;
2007-06-11 17:20:29 +04:00
typedef enum {
DR_TASK = 1 ,
DR_INFO = 2 ,
2007-06-15 22:20:28 +04:00
DR_DEPS = 4 ,
2009-06-03 22:35:39 +04:00
DR_TREE = 8 , /* Complete dependency tree required */
DR_NAME = 16
2007-06-11 17:20:29 +04:00
} report_type_t ;
2012-01-11 16:46:19 +04:00
typedef enum {
DN_DEVNO , /* Major and minor number pair */
DN_BLK , /* Block device name (e.g. dm-0) */
DN_MAP /* Map name (for dm devices only, equal to DN_BLK otherwise) */
} dev_name_t ;
2002-01-03 13:39:21 +03:00
static int _switches [ NUM_SWITCHES ] ;
2007-01-18 20:47:58 +03:00
static int _int_args [ NUM_SWITCHES ] ;
static char * _string_args [ 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 ;
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 ;
2007-11-29 17:44:28 +03:00
static uint32_t _read_ahead_flags ;
2010-02-15 19:21:33 +03:00
static uint32_t _udev_cookie ;
static int _udev_only ;
2005-11-09 17:10:50 +03:00
static struct dm_tree * _dtree ;
2007-01-24 21:09:07 +03:00
static struct dm_report * _report ;
2007-06-11 17:20:29 +04:00
static report_type_t _report_type ;
2012-01-11 16:46:19 +04:00
static dev_name_t _dev_name_type ;
2002-01-03 13:39:21 +03:00
/*
* Commands
*/
2007-01-24 21:09:07 +03:00
2011-03-02 05:44:56 +03:00
struct command ;
# define CMD_ARGS const struct command *cmd, int argc, char **argv, struct dm_names *names, int multiple_devices
typedef int ( * command_fn ) ( CMD_ARGS ) ;
2007-01-24 21:09:07 +03:00
struct command {
const char * name ;
const char * help ;
int min_args ;
int max_args ;
2011-03-02 05:44:56 +03:00
int repeatable_cmd ; /* Repeat to process device list? */
2007-01-24 21:09:07 +03:00
command_fn fn ;
} ;
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 :
2010-04-07 19:57:20 +04:00
memset ( buffer , 0 , buffer_size ) ;
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
2007-01-25 17:16:20 +03:00
if ( file & & fclose ( fp ) )
fprintf ( stderr , " %s: fclose failed: %s " , file , strerror ( errno ) ) ;
2002-03-07 23:56:10 +03:00
return r ;
2001-11-21 15:47:42 +03:00
}
2009-06-03 22:35:39 +04:00
struct dm_split_name {
char * subsystem ;
char * vg_name ;
char * lv_name ;
char * lv_layer ;
} ;
2007-01-24 21:09:07 +03:00
struct dmsetup_report_obj {
struct dm_task * task ;
struct dm_info * info ;
2007-06-15 22:20:28 +04:00
struct dm_task * deps_task ;
2007-06-11 17:20:29 +04:00
struct dm_tree_node * tree_node ;
2009-06-03 22:35:39 +04:00
struct dm_split_name * split_name ;
2007-01-24 21:09:07 +03:00
} ;
2004-10-12 20:42:40 +04:00
2007-06-15 22:20:28 +04:00
static struct dm_task * _get_deps_task ( int major , int minor )
{
struct dm_task * dmt ;
struct dm_info info ;
if ( ! ( dmt = dm_task_create ( DM_DEVICE_DEPS ) ) )
return NULL ;
if ( ! dm_task_set_major ( dmt , major ) | |
! dm_task_set_minor ( dmt , minor ) )
goto err ;
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto err ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto err ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto err ;
2007-06-15 22:20:28 +04:00
if ( ! dm_task_run ( dmt ) )
goto err ;
if ( ! dm_task_get_info ( dmt , & info ) )
goto err ;
if ( ! info . exists )
goto err ;
return dmt ;
err :
dm_task_destroy ( dmt ) ;
return NULL ;
}
2009-06-04 00:44:42 +04:00
static char * _extract_uuid_prefix ( const char * uuid , const int separator )
2009-06-03 22:35:39 +04:00
{
char * ptr = NULL ;
char * uuid_prefix = NULL ;
size_t len ;
if ( uuid )
2009-06-04 00:44:42 +04:00
ptr = strchr ( uuid , separator ) ;
2009-06-03 22:35:39 +04:00
len = ptr ? ptr - uuid : 0 ;
if ( ! ( uuid_prefix = dm_malloc ( len + 1 ) ) ) {
log_error ( " Failed to allocate memory to extract uuid prefix. " ) ;
return NULL ;
}
2010-12-01 01:53:37 +03:00
if ( uuid )
memcpy ( uuid_prefix , uuid , len ) ;
2009-06-03 22:35:39 +04:00
uuid_prefix [ len ] = ' \0 ' ;
return uuid_prefix ;
}
2009-06-04 00:44:42 +04:00
static struct dm_split_name * _get_split_name ( const char * uuid , const char * name ,
int separator )
2009-06-03 22:35:39 +04:00
{
struct dm_split_name * split_name ;
if ( ! ( split_name = dm_malloc ( sizeof ( * split_name ) ) ) ) {
log_error ( " Failed to allocate memory to split device name "
" into components. " ) ;
return NULL ;
}
2009-06-04 00:44:42 +04:00
split_name - > subsystem = _extract_uuid_prefix ( uuid , separator ) ;
2009-06-03 22:35:39 +04:00
split_name - > vg_name = split_name - > lv_name =
split_name - > lv_layer = ( char * ) " " ;
if ( ! strcmp ( split_name - > subsystem , " LVM " ) & &
( ! ( split_name - > vg_name = dm_strdup ( name ) ) | |
! dm_split_lvm_name ( NULL , NULL , & split_name - > vg_name ,
& split_name - > lv_name , & split_name - > lv_layer ) ) )
log_error ( " Failed to allocate memory to split LVM name "
" into components. " ) ;
return split_name ;
}
static void _destroy_split_name ( struct dm_split_name * split_name )
{
/*
* lv_name and lv_layer are allocated within the same block
* of memory as vg_name so don ' t need to be freed separately .
*/
if ( ! strcmp ( split_name - > subsystem , " LVM " ) )
dm_free ( split_name - > vg_name ) ;
dm_free ( split_name - > subsystem ) ;
dm_free ( split_name ) ;
}
2007-01-24 21:09:07 +03:00
static int _display_info_cols ( struct dm_task * dmt , struct dm_info * info )
2003-07-02 01:20:58 +04:00
{
2007-01-24 21:09:07 +03:00
struct dmsetup_report_obj obj ;
2007-06-11 17:20:29 +04:00
int r = 0 ;
2003-07-02 01:20:58 +04:00
2004-06-16 20:44:12 +04:00
if ( ! info - > exists ) {
2007-01-24 21:09:07 +03:00
fprintf ( stderr , " Device does not exist. \n " ) ;
return 0 ;
2004-06-16 20:44:12 +04:00
}
2003-07-02 01:20:58 +04:00
2007-01-24 21:09:07 +03:00
obj . task = dmt ;
obj . info = info ;
2007-06-15 22:20:28 +04:00
obj . deps_task = NULL ;
2009-06-03 22:35:39 +04:00
obj . split_name = NULL ;
2004-06-16 20:44:12 +04:00
2007-06-11 17:20:29 +04:00
if ( _report_type & DR_TREE )
obj . tree_node = dm_tree_find_node ( _dtree , info - > major , info - > minor ) ;
2007-06-15 22:20:28 +04:00
if ( _report_type & DR_DEPS )
obj . deps_task = _get_deps_task ( info - > major , info - > minor ) ;
2009-06-03 22:35:39 +04:00
if ( _report_type & DR_NAME )
2009-06-04 00:44:42 +04:00
obj . split_name = _get_split_name ( dm_task_get_uuid ( dmt ) , dm_task_get_name ( dmt ) , ' - ' ) ;
2009-06-03 22:35:39 +04:00
2007-01-24 21:09:07 +03:00
if ( ! dm_report_object ( _report , & obj ) )
2007-06-11 17:20:29 +04:00
goto out ;
2004-06-16 20:44:12 +04:00
2007-06-11 17:20:29 +04:00
r = 1 ;
out :
2007-06-15 22:20:28 +04:00
if ( obj . deps_task )
dm_task_destroy ( obj . deps_task ) ;
2009-06-03 22:35:39 +04:00
if ( obj . split_name )
_destroy_split_name ( obj . split_name ) ;
2007-06-11 17:20:29 +04:00
return r ;
2004-06-16 20:44:12 +04:00
}
static void _display_info_long ( struct dm_task * dmt , struct dm_info * info )
{
const char * uuid ;
2007-11-30 17:59:57 +03:00
uint32_t read_ahead ;
2004-06-16 20:44:12 +04:00
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
2007-12-04 01:53:04 +03:00
/* FIXME Old value is being printed when it's being changed. */
2007-11-30 17:59:57 +03:00
if ( dm_task_get_read_ahead ( dmt , & read_ahead ) )
2007-12-04 01:48:36 +03:00
printf ( " Read Ahead: % " PRIu32 " \n " , read_ahead ) ;
2007-11-27 23:57:05 +03: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
2007-01-24 21:09:07 +03:00
/* FIXME return code */
2004-10-12 20:42:40 +04:00
_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 ] ) {
2007-01-18 20:47:58 +03:00
if ( ! dm_task_set_major ( dmt , _int_args [ MAJOR_ARG ] ) | |
! dm_task_set_minor ( dmt , _int_args [ MINOR_ARG ] ) )
2004-10-01 23:11:37 +04:00
return 0 ;
} else if ( ! optional ) {
fprintf ( stderr , " No device specified. \n " ) ;
return 0 ;
}
return 1 ;
}
2011-02-05 01:17:54 +03:00
static int _set_task_add_node ( struct dm_task * dmt )
{
if ( ! dm_task_set_add_node ( dmt , DEFAULT_DM_ADD_NODE ) )
return 0 ;
if ( _switches [ ADD_NODE_ON_RESUME_ARG ] & &
! dm_task_set_add_node ( dmt , DM_ADD_NODE_ON_RESUME ) )
return 0 ;
if ( _switches [ ADD_NODE_ON_CREATE_ARG ] & &
! dm_task_set_add_node ( dmt , DM_ADD_NODE_ON_CREATE ) )
return 0 ;
return 1 ;
}
2011-03-02 05:44:56 +03:00
static int _load ( CMD_ARGS )
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 ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( 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 ;
}
2011-03-02 05:44:56 +03:00
static int _create ( CMD_ARGS )
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 ;
2009-07-31 21:51:45 +04:00
uint32_t cookie = 0 ;
2010-01-07 22:45:12 +03:00
uint16_t udev_flags = 0 ;
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 ;
2007-01-18 20:47:58 +03:00
if ( _switches [ MAJOR_ARG ] & & ! dm_task_set_major ( dmt , _int_args [ MAJOR_ARG ] ) )
2004-10-01 23:11:37 +04:00
goto out ;
2007-01-18 20:47:58 +03:00
if ( _switches [ MINOR_ARG ] & & ! dm_task_set_minor ( dmt , _int_args [ MINOR_ARG ] ) )
2004-10-01 23:11:37 +04:00
goto out ;
2007-01-18 20:47:58 +03:00
if ( _switches [ UID_ARG ] & & ! dm_task_set_uid ( dmt , _int_args [ UID_ARG ] ) )
2006-02-03 17:23:22 +03:00
goto out ;
2007-01-18 20:47:58 +03:00
if ( _switches [ GID_ARG ] & & ! dm_task_set_gid ( dmt , _int_args [ GID_ARG ] ) )
2006-02-03 17:23:22 +03:00
goto out ;
2007-01-18 20:47:58 +03:00
if ( _switches [ MODE_ARG ] & & ! dm_task_set_mode ( dmt , _int_args [ MODE_ARG ] ) )
2006-02-03 17:23:22 +03:00
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2007-11-27 23:57:05 +03:00
if ( _switches [ READAHEAD_ARG ] & &
2007-11-29 17:44:28 +03:00
! dm_task_set_read_ahead ( dmt , _int_args [ READAHEAD_ARG ] ,
_read_ahead_flags ) )
2007-11-27 23:57:05 +03:00
goto out ;
2009-07-31 21:51:45 +04:00
if ( _switches [ NOTABLE_ARG ] )
dm_udev_set_sync_support ( 0 ) ;
2010-01-07 22:45:12 +03:00
if ( _switches [ NOUDEVRULES_ARG ] )
udev_flags | = DM_UDEV_DISABLE_DM_RULES_FLAG |
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto out ;
2011-02-04 22:33:53 +03:00
2011-02-05 01:17:54 +03:00
if ( ! _set_task_add_node ( dmt ) )
goto out ;
2011-02-04 22:33:53 +03:00
2011-06-17 18:55:51 +04:00
if ( _udev_cookie )
2010-02-15 19:21:33 +03:00
cookie = _udev_cookie ;
2011-06-17 18:55:51 +04:00
if ( _udev_only )
udev_flags | = DM_UDEV_DISABLE_LIBRARY_FALLBACK ;
2010-02-15 19:21:33 +03:00
2010-01-07 22:45:12 +03:00
if ( ! dm_task_set_cookie ( dmt , & cookie , udev_flags ) | |
2009-08-03 22:01:45 +04:00
! dm_task_run ( dmt ) )
2004-10-01 23:11:37 +04:00
goto out ;
r = 1 ;
2011-03-02 03:29:57 +03:00
out :
2010-08-03 17:04:32 +04:00
if ( ! _udev_cookie )
( void ) dm_udev_wait ( cookie ) ;
2011-03-02 03:29:57 +03:00
if ( r & & _switches [ VERBOSE_ARG ] )
2005-03-27 15:37:46 +04:00
r = _display_info ( dmt ) ;
2004-10-01 23:11:37 +04:00
2010-08-03 17:04:32 +04:00
dm_task_destroy ( dmt ) ;
2004-10-01 23:11:37 +04:00
return r ;
2001-11-21 15:47:42 +03:00
}
2011-03-02 05:44:56 +03:00
static int _rename ( CMD_ARGS )
2002-01-11 15:12:46 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
2009-07-31 21:51:45 +04:00
uint32_t cookie = 0 ;
2010-01-07 22:45:12 +03:00
uint16_t udev_flags = 0 ;
2002-01-11 15:12:46 +03:00
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
2010-10-15 05:10:27 +04:00
if ( _switches [ SETUUID_ARG ] ) {
if ( ! dm_task_set_newuuid ( dmt , argv [ argc - 1 ] ) )
goto out ;
} else 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 ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto out ;
2010-01-07 22:45:12 +03:00
if ( _switches [ NOUDEVRULES_ARG ] )
udev_flags | = DM_UDEV_DISABLE_DM_RULES_FLAG |
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG ;
2011-06-17 18:55:51 +04:00
if ( _udev_cookie )
2010-02-15 19:21:33 +03:00
cookie = _udev_cookie ;
2011-06-17 18:55:51 +04:00
if ( _udev_only )
udev_flags | = DM_UDEV_DISABLE_LIBRARY_FALLBACK ;
2010-02-15 19:21:33 +03:00
2010-01-07 22:45:12 +03:00
if ( ! dm_task_set_cookie ( dmt , & cookie , udev_flags ) | |
2009-08-03 22:01:45 +04:00
! dm_task_run ( dmt ) )
2002-03-07 23:56:10 +03:00
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 :
2010-02-15 19:21:33 +03:00
if ( ! _udev_cookie )
( void ) dm_udev_wait ( cookie ) ;
2011-03-02 03:29:57 +03:00
2002-03-07 23:56:10 +03:00
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
2011-03-02 05:44:56 +03:00
static int _message ( CMD_ARGS )
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 ;
2010-10-01 01:06:50 +04:00
if ( ! ( str = dm_zalloc ( sz ) ) ) {
2007-01-16 01:05:50 +03:00
err ( " message string allocation failed " ) ;
goto out ;
}
2004-06-09 00:34:40 +04:00
for ( i = 0 ; i < argc ; i + + ) {
if ( i )
strcat ( str , " " ) ;
strcat ( str , argv [ i ] ) ;
}
2011-08-04 16:40:24 +04:00
i = dm_task_set_message ( dmt , str ) ;
2004-06-09 00:34:40 +04:00
2006-10-12 19:42:25 +04:00
dm_free ( str ) ;
2004-06-09 00:34:40 +04:00
2011-08-04 16:40:24 +04:00
if ( ! i )
goto out ;
2005-01-13 01:10:14 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( 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 ;
}
2011-03-02 05:44:56 +03:00
static int _setgeometry ( CMD_ARGS )
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 ;
2009-11-06 03:43:08 +03:00
if ( _switches [ NOOPENCOUNT_ARG ] & & ! dm_task_no_open_count ( dmt ) )
goto out ;
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto out ;
2006-02-21 02:55:58 +03:00
/* run the task */
if ( ! dm_task_run ( dmt ) )
goto out ;
r = 1 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2011-03-02 05:44:56 +03:00
static int _splitname ( CMD_ARGS )
2009-06-04 00:44:42 +04:00
{
struct dmsetup_report_obj obj ;
int r = 1 ;
obj . task = NULL ;
obj . info = NULL ;
obj . deps_task = NULL ;
obj . tree_node = NULL ;
obj . split_name = _get_split_name ( ( argc = = 3 ) ? argv [ 2 ] : " LVM " ,
argv [ 1 ] , ' \0 ' ) ;
r = dm_report_object ( _report , & obj ) ;
_destroy_split_name ( obj . split_name ) ;
return r ;
}
2010-02-15 19:21:33 +03:00
static uint32_t _get_cookie_value ( const char * str_value )
2009-07-31 21:51:45 +04:00
{
2009-10-22 16:55:47 +04:00
unsigned long int value ;
2009-07-31 21:51:45 +04:00
char * p ;
2009-10-22 16:55:47 +04:00
if ( ! ( value = strtoul ( str_value , & p , 0 ) ) | |
* p | |
( value = = ULONG_MAX & & errno = = ERANGE ) | |
value > 0xFFFFFFFF ) {
2009-07-31 21:51:45 +04:00
err ( " Incorrect cookie value " ) ;
return 0 ;
}
2009-10-22 16:55:47 +04:00
else
return ( uint32_t ) value ;
}
2011-03-02 05:44:56 +03:00
static int _udevflags ( CMD_ARGS )
2009-10-22 16:55:47 +04:00
{
uint32_t cookie ;
uint16_t flags ;
int i ;
2009-10-26 17:29:33 +03:00
static const char * dm_flag_names [ ] = { " DISABLE_DM_RULES " ,
" DISABLE_SUBSYSTEM_RULES " ,
2009-10-22 16:55:47 +04:00
" DISABLE_DISK_RULES " ,
2009-10-26 17:29:33 +03:00
" DISABLE_OTHER_RULES " ,
2009-10-22 16:55:47 +04:00
" LOW_PRIORITY " ,
2010-02-15 19:21:33 +03:00
" DISABLE_LIBRARY_FALLBACK " ,
2010-04-28 17:37:36 +04:00
" PRIMARY_SOURCE " ,
0 } ;
2009-10-22 16:55:47 +04:00
if ( ! ( cookie = _get_cookie_value ( argv [ 1 ] ) ) )
return 0 ;
flags = cookie > > DM_UDEV_FLAGS_SHIFT ;
for ( i = 0 ; i < DM_UDEV_FLAGS_SHIFT ; i + + )
if ( 1 < < i & flags ) {
if ( i < DM_UDEV_FLAGS_SHIFT / 2 & & dm_flag_names [ i ] )
printf ( " DM_UDEV_%s_FLAG='1' \n " , dm_flag_names [ i ] ) ;
else if ( i < DM_UDEV_FLAGS_SHIFT / 2 )
/*
* This is just a fallback . Each new DM flag
* should have its symbolic name assigned .
*/
printf ( " DM_UDEV_FLAG%d='1' \n " , i ) ;
else
/*
* We can ' t assign symbolic names to subsystem
* flags . Their semantics vary based on the
* subsystem that is currently used .
*/
printf ( " DM_SUBSYSTEM_UDEV_FLAG%d='1' \n " ,
i - DM_UDEV_FLAGS_SHIFT / 2 ) ;
}
return 1 ;
}
2011-03-02 05:44:56 +03:00
static int _udevcomplete ( CMD_ARGS )
2009-10-22 16:55:47 +04:00
{
uint32_t cookie ;
if ( ! ( cookie = _get_cookie_value ( argv [ 1 ] ) ) )
return 0 ;
2009-11-13 15:43:21 +03:00
/*
* Strip flags from the cookie and use cookie magic instead .
* If the cookie has non - zero prefix and the base is zero then
* this one carries flags to control udev rules only and it is
* not meant to be for notification . Return with success in this
* situation .
*/
if ( ! ( cookie & = ~ DM_UDEV_FLAGS_MASK ) )
return 1 ;
cookie | = DM_COOKIE_MAGIC < < DM_UDEV_FLAGS_SHIFT ;
2009-07-31 21:51:45 +04:00
return dm_udev_complete ( cookie ) ;
}
2009-08-06 19:04:30 +04:00
# ifndef UDEV_SYNC_SUPPORT
2009-09-11 19:53:57 +04:00
static const char _cmd_not_supported [ ] = " Command not supported. Recompile with \" --enable-udev-sync \" to enable. " ;
2011-03-02 05:44:56 +03:00
static int _udevcreatecookie ( CMD_ARGS )
2010-02-15 19:21:33 +03:00
{
log_error ( _cmd_not_supported ) ;
return 0 ;
}
2011-03-02 05:44:56 +03:00
static int _udevreleasecookie ( CMD_ARGS )
2010-02-15 19:21:33 +03:00
{
log_error ( _cmd_not_supported ) ;
return 0 ;
}
2011-03-02 05:44:56 +03:00
static int _udevcomplete_all ( CMD_ARGS )
2009-08-06 19:04:30 +04:00
{
2009-09-11 19:53:57 +04:00
log_error ( _cmd_not_supported ) ;
return 0 ;
2009-08-06 19:04:30 +04:00
}
2011-03-02 05:44:56 +03:00
static int _udevcookies ( CMD_ARGS )
2009-08-06 19:56:50 +04:00
{
2009-09-11 19:53:57 +04:00
log_error ( _cmd_not_supported ) ;
return 0 ;
2009-08-06 19:56:50 +04:00
}
2009-09-11 19:53:57 +04:00
# else /* UDEV_SYNC_SUPPORT */
2010-02-15 19:21:33 +03:00
static int _set_up_udev_support ( const char * dev_dir )
{
struct udev * udev ;
const char * udev_dev_dir ;
size_t udev_dev_dir_len ;
int dirs_diff ;
const char * env ;
if ( _switches [ NOUDEVSYNC_ARG ] )
dm_udev_set_sync_support ( 0 ) ;
if ( ! _udev_cookie ) {
env = getenv ( DM_UDEV_COOKIE_ENV_VAR_NAME ) ;
if ( env & & * env & & ( _udev_cookie = _get_cookie_value ( env ) ) )
log_debug ( " Using udev transaction 0x%08 " PRIX32
" defined by %s environment variable. " ,
_udev_cookie ,
DM_UDEV_COOKIE_ENV_VAR_NAME ) ;
}
else if ( _switches [ UDEVCOOKIE_ARG ] )
log_debug ( " Using udev transaction 0x%08 " PRIX32
" defined by --udevcookie option. " ,
_udev_cookie ) ;
if ( ! ( udev = udev_new ( ) ) | |
! ( udev_dev_dir = udev_get_dev_path ( udev ) ) | |
! * udev_dev_dir ) {
log_error ( " Could not get udev dev path. " ) ;
return 0 ;
}
udev_dev_dir_len = strlen ( udev_dev_dir ) ;
/*
* Normally , there ' s always a fallback action by libdevmapper if udev
* has not done its job correctly , e . g . the nodes were not created .
* If using udev transactions by specifying existing cookie value ,
* we need to disable node creation by libdevmapper completely ,
* disabling any fallback actions , since any synchronisation happens
* at the end of the transaction only . We need to do this to prevent
* races between udev and libdevmapper but only in case udev " dev path "
* is the same as " dev path " used by libdevmapper .
*/
/* There's always a slash at the end of dev_dir. But check udev_dev_dir! */
if ( udev_dev_dir [ udev_dev_dir_len - 1 ] ! = ' / ' )
dirs_diff = strncmp ( dev_dir , udev_dev_dir , udev_dev_dir_len ) ;
else
dirs_diff = strcmp ( dev_dir , udev_dev_dir ) ;
2011-06-28 01:43:58 +04:00
_udev_only = ! dirs_diff & & ( _udev_cookie | | ! _switches [ VERIFYUDEV_ARG ] ) ;
2010-02-15 19:21:33 +03:00
if ( dirs_diff ) {
log_debug ( " The path %s used for creating device nodes that is "
" set via DM_DEV_DIR environment variable differs from "
" the path %s that is used by udev. All warnings "
" about udev not working correctly while processing "
" particular nodes will be suppressed. These nodes "
" and symlinks will be managed in each directory "
" separately. " , dev_dir , udev_dev_dir ) ;
dm_udev_set_checking ( 0 ) ;
}
udev_unref ( udev ) ;
return 1 ;
}
2011-03-02 05:44:56 +03:00
static int _udevcreatecookie ( CMD_ARGS )
2010-02-15 19:21:33 +03:00
{
uint32_t cookie ;
if ( ! dm_udev_create_cookie ( & cookie ) )
return 0 ;
2010-03-23 17:43:18 +03:00
if ( cookie )
printf ( " 0x%08 " PRIX32 " \n " , cookie ) ;
2010-02-15 19:21:33 +03:00
return 1 ;
}
2011-03-02 05:44:56 +03:00
static int _udevreleasecookie ( CMD_ARGS )
2010-02-15 19:21:33 +03:00
{
if ( argv [ 1 ] & & ! ( _udev_cookie = _get_cookie_value ( argv [ 1 ] ) ) )
return 0 ;
if ( ! _udev_cookie ) {
log_error ( " No udev transaction cookie given. " ) ;
return 0 ;
}
return dm_udev_wait ( _udev_cookie ) ;
}
2009-08-06 19:04:30 +04:00
2011-03-30 01:56:53 +04:00
__attribute__ ( ( format ( printf , 1 , 2 ) ) )
2009-08-06 19:56:50 +04:00
static char _yes_no_prompt ( const char * prompt , . . . )
{
int c = 0 , ret = 0 ;
va_list ap ;
do {
if ( c = = ' \n ' | | ! c ) {
va_start ( ap , prompt ) ;
vprintf ( prompt , ap ) ;
va_end ( ap ) ;
}
if ( ( c = getchar ( ) ) = = EOF ) {
ret = ' n ' ;
break ;
}
c = tolower ( c ) ;
if ( ( c = = ' y ' ) | | ( c = = ' n ' ) )
ret = c ;
} while ( ! ret | | c ! = ' \n ' ) ;
if ( c ! = ' \n ' )
printf ( " \n " ) ;
return ret ;
}
2011-03-02 05:44:56 +03:00
static int _udevcomplete_all ( CMD_ARGS )
2009-08-06 19:04:30 +04:00
{
int max_id , id , sid ;
struct seminfo sinfo ;
struct semid_ds sdata ;
int counter = 0 ;
2011-06-30 01:56:46 +04:00
int skipped = 0 ;
unsigned age = 0 ;
time_t t ;
if ( argc = = 2 & & ( sscanf ( argv [ 1 ] , " %i " , & age ) ! = 1 ) ) {
log_error ( " Failed to read age_in_minutes parameter. " ) ;
return 0 ;
}
2009-08-06 19:04:30 +04:00
2009-09-11 19:53:57 +04:00
if ( ! _switches [ YES_ARG ] ) {
2011-06-30 01:56:46 +04:00
log_warn ( " This operation will destroy all semaphores %s%.0d%swith keys "
2009-09-11 19:53:57 +04:00
" that have a prefix % " PRIu16 " (0x% " PRIx16 " ). " ,
2011-06-30 01:56:46 +04:00
age ? " older than " : " " , age , age ? " minutes " : " " ,
2009-09-11 19:53:57 +04:00
DM_COOKIE_MAGIC , DM_COOKIE_MAGIC ) ;
2009-08-06 19:04:30 +04:00
2009-09-11 19:53:57 +04:00
if ( _yes_no_prompt ( " Do you really want to continue? [y/n]: " ) = = ' n ' ) {
log_print ( " Semaphores with keys prefixed by % " PRIu16
" (0x% " PRIx16 " ) NOT destroyed. " ,
DM_COOKIE_MAGIC , DM_COOKIE_MAGIC ) ;
return 1 ;
}
2009-08-06 19:04:30 +04:00
}
if ( ( max_id = semctl ( 0 , 0 , SEM_INFO , & sinfo ) ) < 0 ) {
log_sys_error ( " semctl " , " SEM_INFO " ) ;
return 0 ;
}
for ( id = 0 ; id < = max_id ; id + + ) {
if ( ( sid = semctl ( id , 0 , SEM_STAT , & sdata ) ) < 0 )
continue ;
if ( sdata . sem_perm . __key > > 16 = = DM_COOKIE_MAGIC ) {
2011-06-30 01:56:46 +04:00
t = time ( NULL ) ;
if ( sdata . sem_ctime + age * 60 > t | |
sdata . sem_otime + age * 60 > t ) {
skipped + + ;
continue ;
}
2009-08-06 19:04:30 +04:00
if ( semctl ( sid , 0 , IPC_RMID , 0 ) < 0 ) {
log_error ( " Could not cleanup notification semaphore "
" with semid %d and cookie value "
" % " PRIu32 " (0x% " PRIx32 " ) " , sid ,
sdata . sem_perm . __key , sdata . sem_perm . __key ) ;
continue ;
}
counter + + ;
}
}
log_print ( " %d semaphores with keys prefixed by "
2011-06-30 01:56:46 +04:00
" % " PRIu16 " (0x% " PRIx16 " ) destroyed. %d skipped. " ,
counter , DM_COOKIE_MAGIC , DM_COOKIE_MAGIC , skipped ) ;
2009-08-06 19:04:30 +04:00
return 1 ;
}
2011-03-02 05:44:56 +03:00
static int _udevcookies ( CMD_ARGS )
2009-08-06 19:05:10 +04:00
{
int max_id , id , sid ;
struct seminfo sinfo ;
struct semid_ds sdata ;
int val ;
2011-06-30 01:56:46 +04:00
char otime_str [ 26 ] , ctime_str [ 26 ] ;
char * otimes , * ctimes ;
2009-08-06 19:05:10 +04:00
if ( ( max_id = semctl ( 0 , 0 , SEM_INFO , & sinfo ) ) < 0 ) {
log_sys_error ( " sem_ctl " , " SEM_INFO " ) ;
return 0 ;
}
2011-06-30 01:56:46 +04:00
printf ( " Cookie Semid Value Last semop time Last change time \n " ) ;
2009-08-06 19:05:10 +04:00
for ( id = 0 ; id < = max_id ; id + + ) {
if ( ( sid = semctl ( id , 0 , SEM_STAT , & sdata ) ) < 0 )
continue ;
if ( sdata . sem_perm . __key > > 16 = = DM_COOKIE_MAGIC ) {
if ( ( val = semctl ( sid , 0 , GETVAL ) ) < 0 ) {
log_error ( " semid %d: sem_ctl failed for "
" cookie 0x% " PRIx32 " : %s " ,
sid , sdata . sem_perm . __key ,
strerror ( errno ) ) ;
continue ;
}
2011-06-30 01:56:46 +04:00
if ( ( otimes = ctime_r ( ( const time_t * ) & sdata . sem_otime , ( char * ) & otime_str ) ) )
otime_str [ strlen ( otimes ) - 1 ] = ' \0 ' ;
if ( ( ctimes = ctime_r ( ( const time_t * ) & sdata . sem_ctime , ( char * ) & ctime_str ) ) )
ctime_str [ strlen ( ctimes ) - 1 ] = ' \0 ' ;
2009-08-06 19:05:10 +04:00
2011-06-30 01:56:46 +04:00
printf ( " 0x%-10x %-10d %-10d %s %s \n " , sdata . sem_perm . __key ,
sid , val , otimes ? : " unknown " ,
ctimes ? : " unknown " ) ;
2009-08-06 19:05:10 +04:00
}
}
return 1 ;
}
2009-09-11 19:53:57 +04:00
# endif /* UDEV_SYNC_SUPPORT */
2009-08-06 19:05:10 +04:00
2011-03-02 05:44:56 +03:00
static int _version ( CMD_ARGS )
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
{
2009-07-31 21:51:45 +04:00
uint32_t cookie = 0 ;
2010-01-07 22:45:12 +03:00
uint16_t udev_flags = 0 ;
2009-07-31 21:51:45 +04:00
int udev_wait_flag = task = = DM_DEVICE_RESUME | |
task = = DM_DEVICE_REMOVE ;
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 ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2005-10-05 00:12:32 +04:00
if ( _switches [ NOLOCKFS_ARG ] & & ! dm_task_skip_lockfs ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto out ;
2011-02-05 01:17:54 +03:00
/* FIXME: needs to coperate with udev */
if ( ! _set_task_add_node ( dmt ) )
goto out ;
2007-11-27 23:57:05 +03:00
if ( _switches [ READAHEAD_ARG ] & &
2007-11-29 17:44:28 +03:00
! dm_task_set_read_ahead ( dmt , _int_args [ READAHEAD_ARG ] ,
_read_ahead_flags ) )
2007-11-27 23:57:05 +03:00
goto out ;
2010-01-07 22:45:12 +03:00
if ( _switches [ NOUDEVRULES_ARG ] )
udev_flags | = DM_UDEV_DISABLE_DM_RULES_FLAG |
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG ;
2011-06-17 18:55:51 +04:00
if ( _udev_cookie )
2010-02-15 19:21:33 +03:00
cookie = _udev_cookie ;
2011-06-17 18:55:51 +04:00
if ( _udev_only )
udev_flags | = DM_UDEV_DISABLE_LIBRARY_FALLBACK ;
2010-02-15 19:21:33 +03:00
2010-01-07 22:45:12 +03:00
if ( udev_wait_flag & & ! dm_task_set_cookie ( dmt , & cookie , udev_flags ) )
2009-07-31 21:51:45 +04:00
goto out ;
2011-09-22 21:12:28 +04:00
if ( _switches [ RETRY_ARG ] & & task = = DM_DEVICE_REMOVE )
dm_task_retry_remove ( dmt ) ;
2001-11-21 15:47:42 +03:00
r = dm_task_run ( dmt ) ;
2002-03-07 23:56:10 +03:00
out :
2010-02-15 19:21:33 +03:00
if ( ! _udev_cookie & & udev_wait_flag )
2009-08-03 22:01:45 +04:00
( void ) dm_udev_wait ( cookie ) ;
2011-03-02 03:29:57 +03:00
if ( r & & display & & _switches [ VERBOSE_ARG ] )
r = _display_info ( dmt ) ;
2001-11-21 15:47:42 +03:00
dm_task_destroy ( dmt ) ;
2011-03-02 03:29:57 +03:00
2001-11-21 15:47:42 +03:00
return r ;
}
2011-03-02 05:44:56 +03:00
static int _suspend ( CMD_ARGS )
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
}
2011-03-02 05:44:56 +03:00
static int _resume ( CMD_ARGS )
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
}
2011-03-02 05:44:56 +03:00
static int _clear ( CMD_ARGS )
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
}
2011-03-02 05:44:56 +03:00
static int _wait ( CMD_ARGS )
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
}
2011-03-02 05:44:56 +03:00
static int _process_all ( const struct command * cmd , int argc , char * * argv , int silent ,
int ( * fn ) ( CMD_ARGS ) )
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 ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto out ;
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 {
2010-12-20 16:37:26 +03:00
names = ( struct dm_names * ) ( ( char * ) names + next ) ;
2011-03-02 05:44:56 +03:00
if ( ! fn ( cmd , argc , argv , names , 1 ) )
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 ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto out ;
2006-06-18 15:35:04 +04:00
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 ;
}
2011-03-02 05:44:56 +03:00
static int _error_device ( CMD_ARGS )
2006-06-18 15:35:04 +04:00
{
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
2011-07-08 21:08:19 +04:00
name = names ? names - > name : argv [ 1 ] ;
2006-06-18 15:35:04 +04:00
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
2007-04-27 18:52:41 +04:00
if ( ! dm_task_add_target ( dmt , UINT64_C ( 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
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto error ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto error ;
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
}
2011-03-02 05:44:56 +03:00
static int _remove ( CMD_ARGS )
2006-06-18 15:35:04 +04:00
{
if ( _switches [ FORCE_ARG ] & & argc > 1 )
2011-03-02 05:44:56 +03:00
( void ) _error_device ( cmd , argc , argv , NULL , 0 ) ;
2006-06-18 15:35:04 +04:00
return _simple ( DM_DEVICE_REMOVE , argc > 1 ? argv [ 1 ] : NULL , 0 , 0 ) ;
}
2011-03-02 05:44:56 +03:00
static int _count_devices ( CMD_ARGS )
2006-06-18 15:35:04 +04:00
{
_num_devices + + ;
return 1 ;
}
2011-03-02 05:44:56 +03:00
static int _remove_all ( CMD_ARGS )
2006-06-18 15:35:04 +04:00
{
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 ;
2011-03-02 05:44:56 +03:00
r | = _process_all ( cmd , argc , argv , 1 , _count_devices ) ;
2006-06-18 15:35:04 +04:00
/* No devices left? */
if ( ! _num_devices )
return r ;
2011-03-02 05:44:56 +03:00
r | = _process_all ( cmd , 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 ;
2011-03-02 05:44:56 +03:00
r | = _process_all ( cmd , 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 ) ;
}
2011-03-02 05:44:56 +03:00
static int _mknodes ( CMD_ARGS )
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 ) ;
2009-07-14 01:26:41 +04:00
_exit ( 127 ) ;
2005-05-17 00:46:46 +04:00
} else if ( pid < ( pid_t ) 0 )
return 0 ;
TEMP_FAILURE_RETRY ( waitpid ( pid , NULL , 0 ) ) ;
return 1 ;
}
2011-03-02 05:44:56 +03:00
static int _status ( CMD_ARGS )
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 ;
2011-03-02 05:44:56 +03:00
int cmdno ;
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
2011-03-02 05:44:56 +03:00
if ( names )
2003-09-16 18:13:51 +04:00
name = names - > name ;
2004-10-01 23:11:37 +04:00
else {
if ( argc = = 1 & & ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] )
2011-03-02 05:44:56 +03:00
return _process_all ( cmd , argc , argv , 0 , _status ) ;
2011-07-08 21:08:19 +04:00
name = argv [ 1 ] ;
2004-10-01 23:11:37 +04:00
}
2002-05-03 15:55:58 +04:00
2011-03-02 05:44:56 +03:00
if ( ! strcmp ( cmd - > name , " table " ) )
cmdno = DM_DEVICE_TABLE ;
2003-11-13 16:14:28 +03:00
else
2011-03-02 05:44:56 +03:00
cmdno = DM_DEVICE_STATUS ;
2002-05-03 15:55:58 +04:00
2011-03-02 05:44:56 +03:00
if ( ! strcmp ( cmd - > name , " ls " ) )
2005-05-16 20:04:34 +04:00
ls_only = 1 ;
2011-03-02 05:44:56 +03:00
if ( ! ( dmt = dm_task_create ( cmdno ) ) )
2002-05-03 15:55:58 +04:00
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 ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( 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 ) ;
2011-03-02 05:44:56 +03:00
if ( multiple_devices & & ! _switches [ VERBOSE_ARG ] )
2005-05-16 20:04:34 +04:00
printf ( " %s: " , name ) ;
if ( target_type ) {
2007-04-27 19:12:26 +04:00
/* Suppress encryption key */
if ( ! _switches [ SHOWKEYS_ARG ] & &
2011-03-02 05:44:56 +03:00
cmdno = = DM_DEVICE_TABLE & &
2007-04-27 19:12:26 +04:00
! strcmp ( target_type , " crypt " ) ) {
c = params ;
while ( * c & & * c ! = ' ' )
c + + ;
if ( * 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 ) ;
2011-03-02 05:44:56 +03:00
if ( multiple_devices & & _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 */
2011-03-02 05:44:56 +03:00
static int _targets ( CMD_ARGS )
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 ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( dmt ) )
goto out ;
2004-01-23 17:37:47 +03:00
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 ] ) ;
2010-12-20 16:37:26 +03:00
target = ( struct dm_versions * ) ( ( char * ) target + target - > next ) ;
2004-01-23 17:37:47 +03:00
} while ( last_target ! = target ) ;
r = 1 ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2011-03-02 05:44:56 +03:00
static int _info ( CMD_ARGS )
2001-11-21 15:47:42 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
2004-03-30 18:31:58 +04:00
char * name = NULL ;
2003-09-16 18:13:51 +04:00
2011-03-02 05:44:56 +03:00
if ( names )
2003-09-16 18:13:51 +04:00
name = names - > name ;
2004-10-01 23:11:37 +04:00
else {
if ( argc = = 1 & & ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] )
2011-03-02 05:44:56 +03:00
return _process_all ( cmd , argc , argv , 0 , _info ) ;
2011-07-08 21:08:19 +04:00
name = argv [ 1 ] ;
2004-10-01 23:11:37 +04:00
}
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 ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( 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 ;
}
2011-03-02 05:44:56 +03:00
static int _deps ( CMD_ARGS )
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 ;
2004-10-01 23:11:37 +04:00
char * name = NULL ;
2012-01-11 16:46:19 +04:00
char dev_name [ PATH_MAX ] ;
int major , minor ;
2003-09-16 18:13:51 +04:00
2011-03-02 05:44:56 +03:00
if ( names )
2003-09-16 18:13:51 +04:00
name = names - > name ;
2004-10-01 23:11:37 +04:00
else {
if ( argc = = 1 & & ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] )
2011-03-02 05:44:56 +03:00
return _process_all ( cmd , argc , argv , 0 , _deps ) ;
2011-07-08 21:08:19 +04:00
name = argv [ 1 ] ;
2004-10-01 23:11:37 +04:00
}
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 ;
2009-11-06 03:43:08 +03:00
if ( _switches [ INACTIVE_ARG ] & & ! dm_task_query_inactive_table ( dmt ) )
goto out ;
2011-07-01 18:09:19 +04:00
if ( _switches [ CHECKS_ARG ] & & ! dm_task_enable_checks ( 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
2011-03-02 05:44:56 +03:00
if ( multiple_devices & & ! _switches [ VERBOSE_ARG ] )
2003-09-16 18:13:51 +04:00
printf ( " %s: " , name ) ;
2002-03-06 17:38:25 +03:00
printf ( " %d dependencies \t : " , deps - > count ) ;
2012-01-11 16:46:19 +04:00
for ( i = 0 ; i < deps - > count ; i + + ) {
major = ( int ) MAJOR ( deps - > device [ i ] ) ;
minor = ( int ) MINOR ( deps - > device [ i ] ) ;
if ( ( _dev_name_type = = DN_BLK | | _dev_name_type = = DN_MAP ) & &
dm_device_get_name ( major , minor , _dev_name_type = = DN_BLK ,
dev_name , PATH_MAX ) )
printf ( " (%s) " , dev_name ) ;
else
printf ( " (%d, %d) " , major , minor ) ;
}
2002-03-06 17:38:25 +03:00
printf ( " \n " ) ;
2011-03-02 05:44:56 +03:00
if ( multiple_devices & & _switches [ VERBOSE_ARG ] )
2003-09-16 18:13:51 +04:00
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 ;
}
2011-03-02 05:44:56 +03:00
static int _display_name ( CMD_ARGS )
2003-07-02 01:20:58 +04:00
{
2012-01-11 16:46:19 +04:00
char dev_name [ PATH_MAX ] ;
if ( ( _dev_name_type = = DN_BLK | | _dev_name_type = = DN_MAP ) & &
dm_device_get_name ( ( int ) MAJOR ( names - > dev ) , ( int ) MINOR ( names - > dev ) ,
_dev_name_type = = DN_BLK , dev_name , PATH_MAX ) )
printf ( " %s \t (%s) \n " , names - > name , dev_name ) ;
else
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 */
2012-01-11 16:46:19 +04:00
TR_BLKDEVNAME , /* display device kernel name */
2005-10-16 18:33:22 +04:00
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 - - ;
}
}
}
2007-04-27 18:52:41 +04:00
static void _out_string ( const char * str )
2005-10-16 18:33:22 +04:00
{
while ( * str )
2007-04-27 18:52:41 +04:00
_out_char ( ( unsigned char ) * str + + ) ;
2005-10-16 18:33:22 +04:00
}
/* 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 ( ' ] ' ) ;
}
2011-12-01 18:57:30 +04:00
/* FIXME Display table or status line. (Disallow both?) */
static void _display_tree_targets ( struct dm_tree_node * node , unsigned depth )
{
}
2005-11-09 17:10:50 +03:00
static void _display_tree_node ( struct dm_tree_node * node , unsigned depth ,
2010-07-09 19:34:40 +04:00
unsigned first_child __attribute__ ( ( unused ) ) ,
2006-05-16 20:20:29 +04:00
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 ;
2012-01-11 16:46:19 +04:00
char dev_name [ PATH_MAX ] ;
2005-10-16 18:33:22 +04:00
/* 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
2012-01-11 16:46:19 +04:00
if ( ( ! name | | ! * name ) & &
( ! _tree_switches [ TR_DEVICE ] & & ! _tree_switches [ TR_BLKDEVNAME ] ) )
2005-10-16 18:33:22 +04:00
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
2012-01-11 16:46:19 +04:00
if ( _tree_switches [ TR_BLKDEVNAME ] & &
dm_device_get_name ( info - > major , info - > minor , 1 , dev_name , PATH_MAX ) ) {
_out_string ( name ? " < " : " < " ) ;
_out_string ( dev_name ) ;
_out_char ( ' > ' ) ;
}
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 ;
2011-12-01 18:57:30 +04:00
_display_tree_targets ( node , depth + 2 ) ;
2005-10-16 18:33:22 +04:00
}
}
/*
* Walk the dependency tree
*/
2007-06-11 17:20:29 +04:00
static void _display_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 )
2007-06-11 17:20:29 +04:00
_display_tree_walk_children ( child , depth + 1 ) ;
2005-10-16 18:33:22 +04:00
first_child = 0 ;
}
}
2011-03-02 05:44:56 +03:00
static int _add_dep ( CMD_ARGS )
2005-10-16 18:33:22 +04:00
{
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
*/
2011-03-02 05:44:56 +03:00
static int _build_whole_deptree ( const struct command * cmd )
2005-10-16 18:33:22 +04:00
{
2007-06-11 17:20:29 +04:00
if ( _dtree )
return 1 ;
2005-11-09 17:10:50 +03:00
if ( ! ( _dtree = dm_tree_create ( ) ) )
2005-10-16 18:33:22 +04:00
return 0 ;
2011-03-02 05:44:56 +03:00
if ( ! _process_all ( cmd , 0 , NULL , 0 , _add_dep ) )
2005-10-16 18:33:22 +04:00
return 0 ;
2007-06-11 17:20:29 +04:00
return 1 ;
}
2005-10-16 18:33:22 +04:00
2011-03-02 05:44:56 +03:00
static int _display_tree ( CMD_ARGS )
2007-06-11 17:20:29 +04:00
{
2011-03-02 05:44:56 +03:00
if ( ! _build_whole_deptree ( cmd ) )
2007-06-11 17:20:29 +04:00
return 0 ;
_display_tree_walk_children ( dm_tree_find_node ( _dtree , 0 , 0 ) , 0 ) ;
2005-10-16 18:33:22 +04:00
return 1 ;
}
2007-01-24 21:09:07 +03:00
/*
* Report device information
*/
/* dm specific display functions */
static int _int32_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2007-01-24 21:09:07 +03:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2007-01-24 21:09:07 +03:00
{
const int32_t value = * ( const int32_t * ) data ;
return dm_report_field_int32 ( rh , field , & value ) ;
}
static int _uint32_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2007-06-11 17:20:29 +04:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2007-01-24 21:09:07 +03:00
{
const uint32_t value = * ( const int32_t * ) data ;
return dm_report_field_uint32 ( rh , field , & value ) ;
}
static int _dm_name_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2007-01-24 21:09:07 +03:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2007-01-24 21:09:07 +03:00
{
2007-04-27 18:52:41 +04:00
const char * name = dm_task_get_name ( ( const struct dm_task * ) data ) ;
2007-01-24 21:09:07 +03:00
return dm_report_field_string ( rh , field , & name ) ;
}
static int _dm_uuid_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2007-01-24 21:09:07 +03:00
struct dm_report_field * field ,
2010-07-09 19:34:40 +04:00
const void * data , void * private __attribute__ ( ( unused ) ) )
2007-01-24 21:09:07 +03:00
{
2007-04-27 18:52:41 +04:00
const char * uuid = dm_task_get_uuid ( ( const struct dm_task * ) data ) ;
2007-01-24 21:09:07 +03:00
if ( ! uuid | | ! * uuid )
uuid = " " ;
return dm_report_field_string ( rh , field , & uuid ) ;
}
2007-11-27 23:57:05 +03:00
static int _dm_read_ahead_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2007-11-27 23:57:05 +03:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2007-11-27 23:57:05 +03:00
{
2007-11-30 17:59:57 +03:00
uint32_t value ;
2007-11-27 23:57:05 +03:00
2007-11-30 17:59:57 +03:00
if ( ! dm_task_get_read_ahead ( ( const struct dm_task * ) data , & value ) )
value = 0 ;
return dm_report_field_uint32 ( rh , field , & value ) ;
2007-11-27 23:57:05 +03:00
}
2012-01-11 16:46:19 +04:00
static int _dm_blk_name_disp ( struct dm_report * rh ,
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
struct dm_report_field * field , const void * data ,
void * private __attribute__ ( ( unused ) ) )
{
char dev_name [ PATH_MAX ] ;
const char * s = dev_name ;
const struct dm_info * info = data ;
if ( ! dm_device_get_name ( info - > major , info - > minor , 1 , dev_name , PATH_MAX ) ) {
log_error ( " Could not resolve block device name for %d:%d. " ,
info - > major , info - > minor ) ;
return 0 ;
}
return dm_report_field_string ( rh , field , & s ) ;
}
2007-01-24 21:09:07 +03:00
static int _dm_info_status_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2007-01-24 21:09:07 +03:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2007-01-24 21:09:07 +03:00
{
char buf [ 5 ] ;
const char * s = buf ;
2007-04-27 18:52:41 +04:00
const struct dm_info * info = data ;
2007-01-24 21:09:07 +03:00
buf [ 0 ] = info - > live_table ? ' L ' : ' - ' ;
buf [ 1 ] = info - > inactive_table ? ' I ' : ' - ' ;
buf [ 2 ] = info - > suspended ? ' s ' : ' - ' ;
buf [ 3 ] = info - > read_only ? ' r ' : ' w ' ;
buf [ 4 ] = ' \0 ' ;
return dm_report_field_string ( rh , field , & s ) ;
}
2008-04-21 17:16:30 +04:00
static int _dm_info_table_loaded_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2008-04-21 17:16:30 +04:00
struct dm_report_field * field ,
const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2008-04-21 17:16:30 +04:00
{
const struct dm_info * info = data ;
if ( info - > live_table ) {
if ( info - > inactive_table )
dm_report_field_set_value ( field , " Both " , NULL ) ;
else
dm_report_field_set_value ( field , " Live " , NULL ) ;
return 1 ;
}
if ( info - > inactive_table )
dm_report_field_set_value ( field , " Inactive " , NULL ) ;
else
dm_report_field_set_value ( field , " None " , NULL ) ;
return 1 ;
}
static int _dm_info_suspended_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2008-04-21 17:16:30 +04:00
struct dm_report_field * field ,
const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2008-04-21 17:16:30 +04:00
{
const struct dm_info * info = data ;
if ( info - > suspended )
dm_report_field_set_value ( field , " Suspended " , NULL ) ;
else
2008-04-21 20:57:11 +04:00
dm_report_field_set_value ( field , " Active " , NULL ) ;
2008-04-21 17:16:30 +04:00
return 1 ;
}
static int _dm_info_read_only_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2008-04-21 17:16:30 +04:00
struct dm_report_field * field ,
const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2008-04-21 17:16:30 +04:00
{
const struct dm_info * info = data ;
if ( info - > read_only )
dm_report_field_set_value ( field , " Read-only " , NULL ) ;
else
dm_report_field_set_value ( field , " Writeable " , NULL ) ;
return 1 ;
}
2007-06-15 22:20:28 +04:00
static int _dm_info_devno_disp ( struct dm_report * rh , struct dm_pool * mem ,
struct dm_report_field * field , const void * data ,
void * private )
{
2012-01-11 16:46:19 +04:00
char buf [ PATH_MAX ] , * repstr ;
2010-01-14 13:15:23 +03:00
const struct dm_info * info = data ;
2007-06-15 22:20:28 +04:00
if ( ! dm_pool_begin_object ( mem , 8 ) ) {
log_error ( " dm_pool_begin_object failed " ) ;
return 0 ;
}
2012-01-11 16:46:19 +04:00
if ( private ) {
if ( ! dm_device_get_name ( info - > major , info - > minor ,
1 , buf , PATH_MAX ) )
goto out_abandon ;
}
else {
if ( dm_snprintf ( buf , sizeof ( buf ) , " %d:%d " ,
info - > major , info - > minor ) < 0 ) {
log_error ( " dm_pool_alloc failed " ) ;
goto out_abandon ;
}
2007-06-15 22:20:28 +04:00
}
2007-06-19 19:47:20 +04:00
if ( ! dm_pool_grow_object ( mem , buf , strlen ( buf ) + 1 ) ) {
2007-06-15 22:20:28 +04:00
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
repstr = dm_pool_end_object ( mem ) ;
dm_report_field_set_value ( field , repstr , repstr ) ;
return 1 ;
out_abandon :
dm_pool_abandon_object ( mem ) ;
return 0 ;
}
static int _dm_tree_names ( struct dm_report * rh , struct dm_pool * mem ,
struct dm_report_field * field , const void * data ,
void * private , unsigned inverted )
{
2010-01-14 13:15:23 +03:00
const struct dm_tree_node * node = data ;
struct dm_tree_node * parent ;
2007-06-15 22:20:28 +04:00
void * t = NULL ;
const char * name ;
int first_node = 1 ;
char * repstr ;
if ( ! dm_pool_begin_object ( mem , 16 ) ) {
log_error ( " dm_pool_begin_object failed " ) ;
return 0 ;
}
while ( ( parent = dm_tree_next_child ( & t , node , inverted ) ) ) {
name = dm_tree_node_get_name ( parent ) ;
if ( ! name | | ! * name )
continue ;
2007-06-19 20:50:38 +04:00
if ( ! first_node & & ! dm_pool_grow_object ( mem , " , " , 1 ) ) {
2007-06-15 22:20:28 +04:00
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
2008-04-19 19:50:18 +04:00
if ( ! dm_pool_grow_object ( mem , name , 0 ) ) {
2007-06-15 22:20:28 +04:00
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
if ( first_node )
first_node = 0 ;
}
if ( ! dm_pool_grow_object ( mem , " \0 " , 1 ) ) {
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
repstr = dm_pool_end_object ( mem ) ;
dm_report_field_set_value ( field , repstr , repstr ) ;
return 1 ;
out_abandon :
dm_pool_abandon_object ( mem ) ;
return 0 ;
}
static int _dm_deps_names_disp ( struct dm_report * rh ,
struct dm_pool * mem ,
struct dm_report_field * field ,
const void * data , void * private )
{
return _dm_tree_names ( rh , mem , field , data , private , 0 ) ;
}
static int _dm_tree_parents_names_disp ( struct dm_report * rh ,
struct dm_pool * mem ,
struct dm_report_field * field ,
const void * data , void * private )
{
return _dm_tree_names ( rh , mem , field , data , private , 1 ) ;
}
static int _dm_tree_parents_devs_disp ( struct dm_report * rh , struct dm_pool * mem ,
struct dm_report_field * field ,
const void * data , void * private )
{
2010-01-14 13:15:23 +03:00
const struct dm_tree_node * node = data ;
struct dm_tree_node * parent ;
2007-06-15 22:20:28 +04:00
void * t = NULL ;
const struct dm_info * info ;
int first_node = 1 ;
char buf [ DM_MAX_TYPE_NAME ] , * repstr ;
if ( ! dm_pool_begin_object ( mem , 16 ) ) {
log_error ( " dm_pool_begin_object failed " ) ;
return 0 ;
}
while ( ( parent = dm_tree_next_child ( & t , node , 1 ) ) ) {
info = dm_tree_node_get_info ( parent ) ;
if ( ! info - > major & & ! info - > minor )
continue ;
if ( ! first_node & & ! dm_pool_grow_object ( mem , " , " , 1 ) ) {
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
if ( dm_snprintf ( buf , sizeof ( buf ) , " %d:%d " ,
info - > major , info - > minor ) < 0 ) {
log_error ( " dm_snprintf failed " ) ;
goto out_abandon ;
}
2008-04-19 19:50:18 +04:00
if ( ! dm_pool_grow_object ( mem , buf , 0 ) ) {
2007-06-15 22:20:28 +04:00
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
if ( first_node )
first_node = 0 ;
}
if ( ! dm_pool_grow_object ( mem , " \0 " , 1 ) ) {
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
repstr = dm_pool_end_object ( mem ) ;
dm_report_field_set_value ( field , repstr , repstr ) ;
return 1 ;
out_abandon :
dm_pool_abandon_object ( mem ) ;
return 0 ;
}
2007-06-11 17:20:29 +04:00
static int _dm_tree_parents_count_disp ( struct dm_report * rh ,
struct dm_pool * mem ,
struct dm_report_field * field ,
const void * data , void * private )
{
2010-01-14 13:15:23 +03:00
const struct dm_tree_node * node = data ;
2007-06-11 17:20:29 +04:00
int num_parent = dm_tree_node_num_children ( node , 1 ) ;
return dm_report_field_int ( rh , field , & num_parent ) ;
}
2007-01-24 21:09:07 +03:00
2012-01-11 16:46:19 +04:00
static int _dm_deps_disp_common ( struct dm_report * rh , struct dm_pool * mem ,
struct dm_report_field * field , const void * data ,
void * private , int disp_blk_dev_names )
2007-06-15 22:20:28 +04:00
{
2010-10-25 17:36:57 +04:00
const struct dm_deps * deps = data ;
2012-01-11 16:46:19 +04:00
char buf [ PATH_MAX ] , * repstr ;
int major , minor ;
2011-04-08 18:40:18 +04:00
unsigned i ;
2007-06-15 22:20:28 +04:00
if ( ! dm_pool_begin_object ( mem , 16 ) ) {
log_error ( " dm_pool_begin_object failed " ) ;
return 0 ;
}
for ( i = 0 ; i < deps - > count ; i + + ) {
2012-01-11 16:46:19 +04:00
major = ( int ) MAJOR ( deps - > device [ i ] ) ;
minor = ( int ) MINOR ( deps - > device [ i ] ) ;
if ( disp_blk_dev_names ) {
if ( ! dm_device_get_name ( major , minor , 1 , buf , PATH_MAX ) ) {
log_error ( " Could not resolve block device "
" name for %d:%d. " , major , minor ) ;
goto out_abandon ;
}
}
else if ( dm_snprintf ( buf , sizeof ( buf ) , " %d:%d " ,
major , minor ) < 0 ) {
2007-06-15 22:20:28 +04:00
log_error ( " dm_snprintf failed " ) ;
goto out_abandon ;
}
2012-01-11 16:46:19 +04:00
2008-04-19 19:50:18 +04:00
if ( ! dm_pool_grow_object ( mem , buf , 0 ) ) {
2007-06-15 22:20:28 +04:00
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
2012-01-11 16:46:19 +04:00
2007-06-15 22:20:28 +04:00
if ( i + 1 < deps - > count & & ! dm_pool_grow_object ( mem , " , " , 1 ) ) {
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
}
if ( ! dm_pool_grow_object ( mem , " \0 " , 1 ) ) {
log_error ( " dm_pool_grow_object failed " ) ;
goto out_abandon ;
}
repstr = dm_pool_end_object ( mem ) ;
dm_report_field_set_value ( field , repstr , repstr ) ;
return 1 ;
out_abandon :
dm_pool_abandon_object ( mem ) ;
return 0 ;
}
2012-01-11 16:46:19 +04:00
static int _dm_deps_disp ( struct dm_report * rh , struct dm_pool * mem ,
struct dm_report_field * field , const void * data ,
void * private )
{
return _dm_deps_disp_common ( rh , mem , field , data , private , 0 ) ;
}
static int _dm_deps_blk_names_disp ( struct dm_report * rh , struct dm_pool * mem ,
struct dm_report_field * field ,
const void * data , void * private )
{
return _dm_deps_disp_common ( rh , mem , field , data , private , 1 ) ;
}
2009-06-03 22:35:39 +04:00
static int _dm_subsystem_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2009-06-03 22:35:39 +04:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2009-06-03 22:35:39 +04:00
{
2011-03-30 01:49:18 +04:00
return dm_report_field_string ( rh , field , ( const char * const * ) data ) ;
2009-06-03 22:35:39 +04:00
}
static int _dm_vg_name_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2009-06-03 22:35:39 +04:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2009-06-03 22:35:39 +04:00
{
2011-03-30 01:49:18 +04:00
return dm_report_field_string ( rh , field , ( const char * const * ) data ) ;
2009-06-03 22:35:39 +04:00
}
static int _dm_lv_name_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2009-06-03 22:35:39 +04:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2009-06-03 22:35:39 +04:00
{
2011-03-30 01:49:18 +04:00
return dm_report_field_string ( rh , field , ( const char * const * ) data ) ;
2009-06-03 22:35:39 +04:00
}
static int _dm_lv_layer_name_disp ( struct dm_report * rh ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2009-06-03 22:35:39 +04:00
struct dm_report_field * field , const void * data ,
2010-07-09 19:34:40 +04:00
void * private __attribute__ ( ( unused ) ) )
2009-06-03 22:35:39 +04:00
{
2011-03-30 01:49:18 +04:00
return dm_report_field_string ( rh , field , ( const char * const * ) data ) ;
2009-06-03 22:35:39 +04:00
}
2007-01-24 21:09:07 +03:00
static void * _task_get_obj ( void * obj )
{
return ( ( struct dmsetup_report_obj * ) obj ) - > task ;
}
static void * _info_get_obj ( void * obj )
{
return ( ( struct dmsetup_report_obj * ) obj ) - > info ;
}
2007-06-15 22:20:28 +04:00
static void * _deps_get_obj ( void * obj )
{
return dm_task_get_deps ( ( ( struct dmsetup_report_obj * ) obj ) - > deps_task ) ;
}
2007-06-11 17:20:29 +04:00
static void * _tree_get_obj ( void * obj )
{
return ( ( struct dmsetup_report_obj * ) obj ) - > tree_node ;
}
2009-06-03 22:35:39 +04:00
static void * _split_name_get_obj ( void * obj )
{
return ( ( struct dmsetup_report_obj * ) obj ) - > split_name ;
}
2007-01-24 21:09:07 +03:00
static const struct dm_report_object_type _report_types [ ] = {
{ DR_TASK , " Mapped Device Name " , " " , _task_get_obj } ,
{ DR_INFO , " Mapped Device Information " , " " , _info_get_obj } ,
2007-06-15 22:20:28 +04:00
{ DR_DEPS , " Mapped Device Relationship Information " , " " , _deps_get_obj } ,
{ DR_TREE , " Mapped Device Relationship Information " , " " , _tree_get_obj } ,
2009-06-03 22:35:39 +04:00
{ DR_NAME , " Mapped Device Name Components " , " " , _split_name_get_obj } ,
2007-01-24 21:09:07 +03:00
{ 0 , " " , " " , NULL } ,
} ;
/* Column definitions */
2008-06-18 14:19:25 +04:00
# define OFFSET_OF(strct, field) (((char*)&((struct strct*)0)->field) - (char*)0)
2007-01-24 21:09:07 +03:00
# define STR (DM_REPORT_FIELD_TYPE_STRING)
# define NUM (DM_REPORT_FIELD_TYPE_NUMBER)
2007-01-29 20:45:32 +03:00
# define FIELD_O(type, strct, sorttype, head, field, width, func, id, desc) {DR_ ## type, sorttype, OFFSET_OF(strct, field), width, id, head, &_ ## func ## _disp, desc},
# define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, sorttype, 0, width, id, head, &_ ## func ## _disp, desc},
2007-01-24 21:09:07 +03:00
static const struct dm_report_field_type _report_fields [ ] = {
/* *INDENT-OFF* */
FIELD_F ( TASK , STR , " Name " , 16 , dm_name , " name " , " Name of mapped device. " )
2007-01-29 21:18:41 +03:00
FIELD_F ( TASK , STR , " UUID " , 32 , dm_uuid , " uuid " , " Unique (optional) identifier for mapped device. " )
2007-11-27 23:57:05 +03:00
/* FIXME Next one should be INFO */
2007-12-05 17:42:10 +03:00
FIELD_F ( TASK , NUM , " RAhead " , 6 , dm_read_ahead , " read_ahead " , " Read ahead in sectors. " )
2007-11-27 23:57:05 +03:00
2012-01-11 16:46:19 +04:00
FIELD_F ( INFO , STR , " BlkDevName " , 16 , dm_blk_name , " blkdevname " , " Name of block device. " )
2007-01-29 22:35:24 +03:00
FIELD_F ( INFO , STR , " Stat " , 4 , dm_info_status , " attr " , " (L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite. " )
2008-04-21 17:16:30 +04:00
FIELD_F ( INFO , STR , " Tables " , 6 , dm_info_table_loaded , " tables_loaded " , " Which of the live and inactive table slots are filled. " )
FIELD_F ( INFO , STR , " Suspended " , 9 , dm_info_suspended , " suspended " , " Whether the device is suspended. " )
FIELD_F ( INFO , STR , " Read-only " , 9 , dm_info_read_only , " readonly " , " Whether the device is read-only or writeable. " )
2007-06-15 22:20:28 +04:00
FIELD_F ( INFO , STR , " DevNo " , 5 , dm_info_devno , " devno " , " Device major and minor numbers " )
2007-01-29 21:18:41 +03:00
FIELD_O ( INFO , dm_info , NUM , " Maj " , major , 3 , int32 , " major " , " Block device major number. " )
FIELD_O ( INFO , dm_info , NUM , " Min " , minor , 3 , int32 , " minor " , " Block device minor number. " )
2007-01-29 22:35:24 +03:00
FIELD_O ( INFO , dm_info , NUM , " Open " , open_count , 4 , int32 , " open " , " Number of references to open device, if requested. " )
FIELD_O ( INFO , dm_info , NUM , " Targ " , target_count , 4 , int32 , " segments " , " Number of segments in live table, if present. " )
FIELD_O ( INFO , dm_info , NUM , " Event " , event_nr , 6 , uint32 , " events " , " Number of most recent event. " )
2007-06-15 22:20:28 +04:00
FIELD_O ( DEPS , dm_deps , NUM , " #Devs " , count , 5 , int32 , " device_count " , " Number of devices used by this one. " )
FIELD_F ( TREE , STR , " DevNames " , 8 , dm_deps_names , " devs_used " , " List of names of mapped devices used by this one. " )
FIELD_F ( DEPS , STR , " DevNos " , 6 , dm_deps , " devnos_used " , " List of device numbers of devices used by this one. " )
2012-01-11 16:46:19 +04:00
FIELD_F ( DEPS , STR , " BlkDevNames " , 16 , dm_deps_blk_names , " blkdevs_used " , " List of names of block devices used by this one. " )
2007-06-15 22:20:28 +04:00
FIELD_F ( TREE , NUM , " #Refs " , 5 , dm_tree_parents_count , " device_ref_count " , " Number of mapped devices referencing this one. " )
FIELD_F ( TREE , STR , " RefNames " , 8 , dm_tree_parents_names , " names_using_dev " , " List of names of mapped devices using this one. " )
FIELD_F ( TREE , STR , " RefDevNos " , 9 , dm_tree_parents_devs , " devnos_using_dev " , " List of device numbers of mapped devices using this one. " )
2009-06-03 22:35:39 +04:00
FIELD_O ( NAME , dm_split_name , STR , " Subsys " , subsystem , 6 , dm_subsystem , " subsystem " , " Userspace subsystem responsible for this device. " )
FIELD_O ( NAME , dm_split_name , STR , " VG " , vg_name , 4 , dm_vg_name , " vg_name " , " LVM Volume Group name. " )
FIELD_O ( NAME , dm_split_name , STR , " LV " , lv_name , 4 , dm_lv_name , " lv_name " , " LVM Logical Volume name. " )
FIELD_O ( NAME , dm_split_name , STR , " LVLayer " , lv_layer , 7 , dm_lv_layer_name , " lv_layer " , " LVM device layer. " )
2007-01-29 20:45:32 +03:00
{ 0 , 0 , 0 , 0 , " " , " " , NULL , NULL } ,
2007-01-24 21:09:07 +03:00
/* *INDENT-ON* */
} ;
# undef STR
# undef NUM
# undef FIELD_O
# undef FIELD_F
2007-01-29 22:35:24 +03:00
static const char * default_report_options = " name,major,minor,attr,open,segments,events,uuid " ;
2009-06-04 00:44:42 +04:00
static const char * splitname_report_options = " vg_name,lv_name,lv_layer " ;
2007-01-24 21:09:07 +03:00
2011-03-02 05:44:56 +03:00
static int _report_init ( const struct command * cmd )
2007-01-24 21:09:07 +03:00
{
char * options = ( char * ) default_report_options ;
const char * keys = " " ;
const char * separator = " " ;
2008-06-25 02:53:48 +04:00
int aligned = 1 , headings = 1 , buffered = 1 , field_prefixes = 0 ;
int quoted = 1 , columns_as_rows = 0 ;
2007-01-24 21:09:07 +03:00
uint32_t flags = 0 ;
size_t len = 0 ;
int r = 0 ;
2011-03-02 05:44:56 +03:00
if ( cmd & & ! strcmp ( cmd - > name , " splitname " ) )
2009-06-04 00:44:42 +04:00
options = ( char * ) splitname_report_options ;
2007-01-24 21:09:07 +03:00
/* emulate old dmsetup behaviour */
if ( _switches [ NOHEADINGS_ARG ] ) {
separator = " : " ;
aligned = 0 ;
headings = 0 ;
}
2007-06-15 22:20:28 +04:00
if ( _switches [ UNBUFFERED_ARG ] )
buffered = 0 ;
2008-06-25 02:53:48 +04:00
if ( _switches [ ROWS_ARG ] )
columns_as_rows = 1 ;
2008-06-25 00:16:47 +04:00
if ( _switches [ UNQUOTED_ARG ] )
quoted = 0 ;
2008-06-06 22:53:08 +04:00
if ( _switches [ NAMEPREFIXES_ARG ] ) {
2008-04-21 15:59:22 +04:00
aligned = 0 ;
field_prefixes = 1 ;
}
2007-01-24 21:09:07 +03:00
if ( _switches [ OPTIONS_ARG ] & & _string_args [ OPTIONS_ARG ] ) {
if ( * _string_args [ OPTIONS_ARG ] ! = ' + ' )
options = _string_args [ OPTIONS_ARG ] ;
else {
len = strlen ( default_report_options ) +
2007-01-25 17:16:20 +03:00
strlen ( _string_args [ OPTIONS_ARG ] ) + 1 ;
2007-01-24 21:09:07 +03:00
if ( ! ( options = dm_malloc ( len ) ) ) {
err ( " Failed to allocate option string. " ) ;
return 0 ;
}
if ( dm_snprintf ( options , len , " %s,%s " ,
default_report_options ,
& _string_args [ OPTIONS_ARG ] [ 1 ] ) < 0 ) {
err ( " snprintf failed " ) ;
goto out ;
}
}
}
if ( _switches [ SORT_ARG ] & & _string_args [ SORT_ARG ] ) {
keys = _string_args [ SORT_ARG ] ;
buffered = 1 ;
2011-03-02 05:44:56 +03:00
if ( cmd & & ( ! strcmp ( cmd - > name , " status " ) | | ! strcmp ( cmd - > name , " table " ) ) ) {
2007-01-24 21:09:07 +03:00
err ( " --sort is not yet supported with status and table " ) ;
goto out ;
}
}
if ( _switches [ SEPARATOR_ARG ] & & _string_args [ SEPARATOR_ARG ] ) {
separator = _string_args [ SEPARATOR_ARG ] ;
aligned = 0 ;
}
if ( aligned )
flags | = DM_REPORT_OUTPUT_ALIGNED ;
if ( buffered )
flags | = DM_REPORT_OUTPUT_BUFFERED ;
if ( headings )
flags | = DM_REPORT_OUTPUT_HEADINGS ;
2008-04-21 15:59:22 +04:00
if ( field_prefixes )
flags | = DM_REPORT_OUTPUT_FIELD_NAME_PREFIX ;
2008-06-25 00:16:47 +04:00
if ( ! quoted )
flags | = DM_REPORT_OUTPUT_FIELD_UNQUOTED ;
2008-06-25 02:53:48 +04:00
if ( columns_as_rows )
flags | = DM_REPORT_OUTPUT_COLUMNS_AS_ROWS ;
2007-06-11 17:20:29 +04:00
if ( ! ( _report = dm_report_init ( & _report_type ,
_report_types , _report_fields ,
options , separator , flags , keys , NULL ) ) )
goto out ;
2011-03-02 05:44:56 +03:00
if ( ( _report_type & DR_TREE ) & & ! _build_whole_deptree ( cmd ) ) {
2007-06-11 17:20:29 +04:00
err ( " Internal device dependency tree creation failed. " ) ;
2007-01-24 21:09:07 +03:00
goto out ;
2007-06-11 17:20:29 +04:00
}
2007-01-24 21:09:07 +03:00
2008-04-21 15:59:22 +04:00
if ( field_prefixes )
dm_report_set_output_field_name_prefix ( _report , " dm_ " ) ;
2007-01-24 21:09:07 +03:00
r = 1 ;
out :
2010-08-03 16:56:00 +04:00
if ( ! strcasecmp ( options , " help " ) | | ! strcmp ( options , " ? " ) )
r = 1 ;
2007-01-24 21:09:07 +03:00
if ( len )
dm_free ( options ) ;
return r ;
}
2005-10-16 18:33:22 +04:00
/*
* List devices
*/
2011-03-02 05:44:56 +03:00
static int _ls ( CMD_ARGS )
2003-09-16 18:13:51 +04:00
{
2005-05-17 00:46:46 +04:00
if ( ( _switches [ TARGET_ARG ] & & _target ) | |
( _switches [ EXEC_ARG ] & & _command ) )
2011-03-02 05:44:56 +03:00
return _status ( cmd , argc , argv , NULL , 0 ) ;
2005-10-16 18:33:22 +04:00
else if ( ( _switches [ TREE_ARG ] ) )
2011-03-02 05:44:56 +03:00
return _display_tree ( cmd , 0 , NULL , NULL , 0 ) ;
2005-05-16 20:04:34 +04:00
else
2011-03-02 05:44:56 +03:00
return _process_all ( cmd , argc , argv , 0 , _display_name ) ;
2003-07-02 01:20:58 +04:00
}
2011-03-02 05:44:56 +03:00
static int _help ( CMD_ARGS ) ;
2007-01-29 21:18:41 +03:00
2001-11-21 15:47:42 +03:00
/*
2007-01-24 21:09:07 +03:00
* Dispatch table
2001-11-21 15:47:42 +03:00
*/
static struct command _commands [ ] = {
2011-03-02 05:44:56 +03:00
{ " help " , " [-c|-C|--columns] " , 0 , 0 , 0 , _help } ,
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 "
2011-02-04 22:33:53 +03:00
" \t [-u|uuid <uuid>] [{--addnodeonresume|--addnodeoncreate}] \n "
2006-08-10 18:11:03 +04:00
" \t [--notable | --table <table> | <table_file>] " ,
2011-03-02 05:44:56 +03:00
1 , 2 , 0 , _create } ,
{ " remove " , " [-f|--force] <device> " , 0 , - 1 , 1 , _remove } ,
{ " remove_all " , " [-f|--force] " , 0 , 0 , 0 , _remove_all } ,
{ " suspend " , " [--noflush] <device> " , 0 , - 1 , 1 , _suspend } ,
{ " resume " , " <device> [{--addnodeonresume|--addnodeoncreate}] " , 0 , - 1 , 1 , _resume } ,
{ " load " , " <device> [<table_file>] " , 0 , 2 , 0 , _load } ,
{ " clear " , " <device> " , 0 , - 1 , 1 , _clear } ,
{ " reload " , " <device> [<table_file>] " , 0 , 2 , 0 , _load } ,
2012-01-18 22:52:02 +04:00
{ " wipe_table " , " <device> " , 0 , - 1 , 1 , _error_device } ,
2011-03-02 05:44:56 +03:00
{ " rename " , " <device> [--setuuid] <new_name_or_uuid> " , 1 , 2 , 0 , _rename } ,
{ " message " , " <device> <sector> <message> " , 2 , - 1 , 0 , _message } ,
2012-01-11 16:46:19 +04:00
{ " ls " , " [--target <target_type>] [--exec <command>] [-o options] [--tree] " , 0 , 0 , 0 , _ls } ,
2011-03-02 05:44:56 +03:00
{ " info " , " [<device>] " , 0 , - 1 , 1 , _info } ,
2012-01-11 16:46:19 +04:00
{ " deps " , " [-o options] [<device>] " , 0 , - 1 , 1 , _deps } ,
2011-03-02 05:44:56 +03:00
{ " status " , " [<device>] [--target <target_type>] " , 0 , - 1 , 1 , _status } ,
{ " table " , " [<device>] [--target <target_type>] [--showkeys] " , 0 , - 1 , 1 , _status } ,
{ " wait " , " <device> [<event_nr>] " , 0 , 2 , 0 , _wait } ,
{ " mknodes " , " [<device>] " , 0 , - 1 , 1 , _mknodes } ,
{ " udevcreatecookie " , " " , 0 , 0 , 0 , _udevcreatecookie } ,
{ " udevreleasecookie " , " [<cookie>] " , 0 , 1 , 0 , _udevreleasecookie } ,
{ " udevflags " , " <cookie> " , 1 , 1 , 0 , _udevflags } ,
{ " udevcomplete " , " <cookie> " , 1 , 1 , 0 , _udevcomplete } ,
2011-06-30 01:56:46 +04:00
{ " udevcomplete_all " , " <age_in_minutes> " , 0 , 1 , 0 , _udevcomplete_all } ,
2011-03-02 05:44:56 +03:00
{ " udevcookies " , " " , 0 , 0 , 0 , _udevcookies } ,
{ " targets " , " " , 0 , 0 , 0 , _targets } ,
{ " version " , " " , 0 , 0 , 0 , _version } ,
{ " setgeometry " , " <device> <cyl> <head> <sect> <start> " , 5 , 5 , 0 , _setgeometry } ,
{ " splitname " , " <device> [<subsystem>] " , 1 , 2 , 0 , _splitname } ,
{ NULL , NULL , 0 , 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 " ) ;
2010-03-08 19:05:07 +03:00
fprintf ( out , " dmsetup [--version] [-h|--help [-c|-C|--columns]] \n "
2011-07-01 18:09:19 +04:00
" [--checks] [-v|--verbose [-v|--verbose ...]] \n "
2009-11-06 03:43:08 +03:00
" [-r|--readonly] [--noopencount] [--nolockfs] [--inactive] \n "
2011-06-30 01:56:46 +04:00
" [--udevcookie [cookie]] [--noudevrules] [--noudevsync] [--verifyudev] \n "
2011-09-22 21:12:28 +04:00
" [-y|--yes] [--readahead [+]<sectors>|auto|none] [--retry] \n "
2007-01-29 21:45:08 +03:00
" [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>] \n "
2008-06-06 22:53:08 +04:00
" [--nameprefixes] [--noheadings] [--separator <separator>] \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 " ) ;
2007-01-29 21:37:57 +03:00
fprintf ( out , " <fields> are comma-separated. Use 'help -c' for list. \n " ) ;
2006-04-06 20:20:40 +04:00
fprintf ( out , " Table_file contents may be supplied on stdin. \n " ) ;
2012-01-11 16:46:19 +04:00
fprintf ( out , " Options are: devno, devname, blkdevname. \n " ) ;
fprintf ( out , " Tree specific options are: ascii, utf, vt100; compact, inverted, notrunc; \n "
" blkdevname, [no]device, active, open, rw and uuid. \n " ) ;
2007-01-29 21:18:41 +03:00
fprintf ( out , " \n " ) ;
2001-11-21 15:47:42 +03:00
}
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 " ) ;
}
2011-03-02 05:44:56 +03:00
static int _help ( CMD_ARGS )
2007-01-29 21:18:41 +03:00
{
_usage ( stderr ) ;
2007-01-29 21:37:57 +03:00
if ( _switches [ COLS_ARG ] ) {
_switches [ OPTIONS_ARG ] = 1 ;
_string_args [ OPTIONS_ARG ] = ( char * ) " help " ;
_switches [ SORT_ARG ] = 0 ;
2009-12-11 16:04:30 +03:00
if ( _report ) {
dm_report_free ( _report ) ;
_report = NULL ;
}
2011-03-02 05:44:56 +03:00
( void ) _report_init ( cmd ) ;
2007-01-29 21:37:57 +03:00
}
2007-01-29 21:18:41 +03:00
return 1 ;
}
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 ;
2007-04-27 18:52:41 +04:00
size_t len ;
2005-10-16 18:33:22 +04:00
/* 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 ;
2012-01-11 16:46:19 +04:00
else if ( ! strncmp ( s , " blkdevname " , len ) )
_tree_switches [ TR_BLKDEVNAME ] = 1 ;
2005-10-16 18:33:22 +04:00
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 )
2007-04-27 18:52:41 +04:00
if ( ioctl ( 1 , ( unsigned long ) TIOCGWINSZ , & winsz ) > = 0 & & winsz . ws_col > 3 )
2005-10-16 18:33:22 +04:00
_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 .
*/
2007-10-09 16:14:48 +04:00
static char * _get_abspath ( const char * path )
2006-10-12 19:42:25 +04:00
{
char * _path ;
# ifdef HAVE_CANONICALIZE_FILE_NAME
_path = canonicalize_file_name ( path ) ;
# else
/* FIXME Provide alternative */
# endif
return _path ;
}
2007-10-09 16:14:48 +04:00
static char * parse_loop_device_name ( const char * dev , const char * dev_dir )
2006-10-12 19:42:25 +04:00
{
char * buf ;
char * device ;
2007-01-17 00:13:07 +03:00
if ( ! ( buf = dm_malloc ( PATH_MAX ) ) )
2006-10-12 19:42:25 +04:00
return NULL ;
if ( dev [ 0 ] = = ' / ' ) {
if ( ! ( device = _get_abspath ( dev ) ) )
goto error ;
2007-10-09 16:14:48 +04:00
if ( strncmp ( device , dev_dir , strlen ( dev_dir ) ) )
goto error ;
/* If dev_dir does not end in a slash, ensure that the
following byte in the device string is " / " . */
2007-12-05 20:05:04 +03:00
if ( dev_dir [ strlen ( dev_dir ) - 1 ] ! = ' / ' & &
device [ strlen ( dev_dir ) ] ! = ' / ' )
2006-10-12 19:42:25 +04:00
goto error ;
2007-04-27 18:52:41 +04:00
strncpy ( buf , strrchr ( device , ' / ' ) + 1 , ( size_t ) PATH_MAX ) ;
2006-10-12 19:42:25 +04:00
dm_free ( device ) ;
} else {
/* check for device number */
if ( ! strncmp ( dev , " loop " , strlen ( " loop " ) ) )
2007-04-27 18:52:41 +04:00
strncpy ( buf , dev , ( size_t ) PATH_MAX ) ;
2006-10-12 19:42:25 +04:00
else
goto error ;
}
return buf ;
error :
2010-11-24 12:43:18 +03:00
dm_free ( buf ) ;
2006-10-12 19:42:25 +04:00
return NULL ;
}
/*
* create a table for a mapped device using the loop target .
*/
2007-01-22 18:03:57 +03:00
static int _loop_table ( char * table , size_t tlen , char * file ,
2010-07-09 19:34:40 +04:00
char * dev __attribute__ ( ( unused ) ) , off_t off )
2006-10-12 19:42:25 +04:00
{
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 ] )
2007-04-27 18:52:41 +04:00
fprintf ( stderr , " losetup: set loop size to %llukB "
" (%llu sectors) \n " , ( long long unsigned ) sectors > > 1 ,
( long long unsigned ) sectors ) ;
2006-10-12 19:42:25 +04:00
# ifdef HAVE_SYS_STATVFS_H
if ( fstatvfs ( fd , & fsbuf ) )
2007-01-18 20:47:58 +03:00
goto error ;
2006-10-12 19:42:25 +04:00
/* FIXME Fragment size currently unused */
blksize = fsbuf . f_frsize ;
# endif
close ( fd ) ;
2007-01-18 20:47:58 +03:00
if ( dm_snprintf ( table , tlen , " %llu %llu loop %s %llu \n " , 0ULL ,
2010-07-06 02:56:31 +04:00
( long long unsigned ) sectors , file , ( long long unsigned ) off ) < 0 )
2006-10-12 19:42:25 +04:00
return 0 ;
if ( _switches [ VERBOSE_ARG ] > 1 )
fprintf ( stderr , " Table: %s \n " , table ) ;
return 1 ;
error :
if ( fd > - 1 )
close ( fd ) ;
return 0 ;
}
2007-10-09 16:14:48 +04:00
static int _process_losetup_switches ( const char * base , int * argc , char * * * argv ,
const char * dev_dir )
2006-10-12 19:42:25 +04:00
{
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 ;
2011-02-18 19:17:56 +03:00
while ( ( c = GETOPTLONG_FN ( * argc , * argv , " ade:fo:v " ,
long_options , NULL ) ) ! = - 1 ) {
2006-10-12 19:42:25 +04:00
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 ;
}
2007-10-09 16:14:48 +04:00
if ( ! ( device_name = parse_loop_device_name ( ( * argv ) [ 0 ] , dev_dir ) ) ) {
2006-10-12 19:42:25 +04:00
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 ) ;
2007-02-14 18:12:16 +03:00
dm_free ( device_name ) ;
2006-10-12 19:42:25 +04:00
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 ) ;
2007-02-14 18:12:16 +03:00
dm_free ( device_name ) ;
2006-10-12 19:42:25 +04:00
return 0 ;
}
/* FIXME Missing free */
_table = dm_malloc ( LOOP_TABLE_SIZE ) ;
2007-04-27 18:52:41 +04:00
if ( ! _loop_table ( _table , ( size_t ) LOOP_TABLE_SIZE , loop_file , device_name , offset ) ) {
2006-10-12 19:42:25 +04:00
fprintf ( stderr , " Could not build device-mapper table for %s \n " , ( * argv ) [ 0 ] ) ;
2007-02-14 18:12:16 +03:00
dm_free ( device_name ) ;
2006-10-12 19:42:25 +04:00
return 0 ;
}
_switches [ TABLE_ARG ] + + ;
( * argv ) [ 0 ] = ( char * ) " create " ;
( * argv ) [ 1 ] = device_name ;
return 1 ;
}
2012-01-11 16:46:19 +04:00
static int _process_options ( const char * options )
{
const char * s , * end ;
size_t len ;
/* Tree options are processed separately. */
if ( _switches [ TREE_ARG ] )
return _process_tree_options ( _string_args [ OPTIONS_ARG ] ) ;
/* Column options are processed separately by _report_init (called later). */
if ( _switches [ COLS_ARG ] )
return 1 ;
/* No options specified. */
if ( ! _switches [ OPTIONS_ARG ] )
return 1 ;
/* Set defaults. */
_dev_name_type = DN_DEVNO ;
/* Parse. */
for ( s = options ; s & & * s ; s + + ) {
len = 0 ;
for ( end = s ; * end & & * end ! = ' , ' ; end + + , len + + )
;
if ( ! strncmp ( s , " devno " , len ) )
_dev_name_type = DN_DEVNO ;
else if ( ! strncmp ( s , " blkdevname " , len ) )
_dev_name_type = DN_BLK ;
else if ( ! strncmp ( s , " devname " , len ) )
_dev_name_type = DN_MAP ;
else {
fprintf ( stderr , " Option not recognised: %s \n " , s ) ;
return 0 ;
}
if ( ! * end )
break ;
s = end ;
}
return 1 ;
}
2007-10-09 16:14:48 +04:00
static int _process_switches ( int * argc , char * * * argv , const char * dev_dir )
2002-01-03 13:39:21 +03:00
{
2007-11-29 17:44:28 +03:00
char * base , * namebase , * s ;
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 } ,
2011-07-01 18:09:19 +04:00
{ " checks " , 0 , & ind , CHECKS_ARG } ,
2005-05-16 18:53:23 +04:00
{ " 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 } ,
2010-03-08 19:05:07 +03:00
{ " help " , 0 , & ind , HELP_ARG } ,
2009-11-06 03:43:08 +03:00
{ " inactive " , 0 , & ind , INACTIVE_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 } ,
2008-06-06 22:53:08 +04:00
{ " nameprefixes " , 0 , & ind , NAMEPREFIXES_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 } ,
2010-02-15 19:21:33 +03:00
{ " udevcookie " , 1 , & ind , UDEVCOOKIE_ARG } ,
2010-01-07 22:45:12 +03:00
{ " noudevrules " , 0 , & ind , NOUDEVRULES_ARG } ,
2009-07-31 21:51:45 +04:00
{ " noudevsync " , 0 , & ind , NOUDEVSYNC_ARG } ,
2005-05-16 18:53:23 +04:00
{ " options " , 1 , & ind , OPTIONS_ARG } ,
2007-11-27 23:57:05 +03:00
{ " readahead " , 1 , & ind , READAHEAD_ARG } ,
2011-09-22 21:12:28 +04:00
{ " retry " , 0 , & ind , RETRY_ARG } ,
2008-06-25 02:53:48 +04:00
{ " rows " , 0 , & ind , ROWS_ARG } ,
2007-01-18 20:47:58 +03:00
{ " separator " , 1 , & ind , SEPARATOR_ARG } ,
2010-10-15 05:10:27 +04:00
{ " setuuid " , 0 , & ind , SETUUID_ARG } ,
2006-10-19 19:34:50 +04:00
{ " showkeys " , 0 , & ind , SHOWKEYS_ARG } ,
2007-01-18 20:47:58 +03:00
{ " sort " , 1 , & ind , SORT_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 } ,
2007-06-15 22:20:28 +04:00
{ " unbuffered " , 0 , & ind , UNBUFFERED_ARG } ,
2008-06-25 00:16:47 +04:00
{ " unquoted " , 0 , & ind , UNQUOTED_ARG } ,
2005-05-16 18:53:23 +04:00
{ " verbose " , 1 , & ind , VERBOSE_ARG } ,
2011-06-28 01:43:58 +04:00
{ " verifyudev " , 0 , & ind , VERIFYUDEV_ARG } ,
2005-05-16 18:53:23 +04:00
{ " version " , 0 , & ind , VERSION_ARG } ,
2009-09-11 19:53:57 +04:00
{ " yes " , 0 , & ind , YES_ARG } ,
2011-02-04 22:33:53 +03:00
{ " addnodeonresume " , 0 , & ind , ADD_NODE_ON_RESUME_ARG } ,
{ " addnodeoncreate " , 0 , & ind , ADD_NODE_ON_CREATE_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 ) ) ;
2007-01-18 20:47:58 +03:00
memset ( & _int_args , 0 , sizeof ( _int_args ) ) ;
2007-11-29 17:44:28 +03:00
_read_ahead_flags = 0 ;
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 ] + + ;
2007-01-18 20:47:58 +03:00
_string_args [ OPTIONS_ARG ] = ( char * ) " name " ;
2005-03-27 15:37:46 +04:00
if ( * argc = = 3 ) {
2007-01-18 20:47:58 +03:00
_int_args [ MAJOR_ARG ] = atoi ( ( * argv ) [ 1 ] ) ;
_int_args [ MINOR_ARG ] = atoi ( ( * argv ) [ 2 ] ) ;
2005-03-27 15:37:46 +04:00
* 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 " ,
2007-01-18 20:47:58 +03:00
& _int_args [ MAJOR_ARG ] ,
& _int_args [ MINOR_ARG ] ) ) ) {
2005-03-27 15:37:46 +04:00
* argc - = 1 ;
* argv + = 1 ;
} else {
fprintf ( stderr , " Usage: devmap_name <major> <minor> \n " ) ;
return 0 ;
}
( * argv ) [ 0 ] = ( char * ) " info " ;
return 1 ;
}
2007-01-29 21:18:41 +03:00
if ( ! strcmp ( base , " losetup " ) | | ! strcmp ( base , " dmlosetup " ) ) {
2007-10-09 16:14:48 +04:00
r = _process_losetup_switches ( base , argc , argv , dev_dir ) ;
2006-10-12 19:42:25 +04:00
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 ;
2010-03-08 19:05:07 +03:00
while ( ( ind = - 1 , c = GETOPTLONG_FN ( * argc , * argv , " cCfG:hj:m:M:no:O:ru:U:vy " ,
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 ;
2010-03-08 19:05:07 +03:00
if ( c = = ' h ' | | ind = = HELP_ARG )
_switches [ HELP_ARG ] + + ;
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 ] + + ;
2007-01-18 20:47:58 +03:00
_int_args [ MAJOR_ARG ] = atoi ( optarg ) ;
2003-04-04 17:22:58 +04:00
}
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 ] + + ;
2007-01-18 20:47:58 +03:00
_int_args [ MINOR_ARG ] = atoi ( optarg ) ;
2002-01-11 15:12:46 +03:00
}
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 ] + + ;
2007-01-18 20:47:58 +03:00
_string_args [ OPTIONS_ARG ] = optarg ;
}
if ( ind = = SEPARATOR_ARG ) {
_switches [ SEPARATOR_ARG ] + + ;
_string_args [ SEPARATOR_ARG ] = optarg ;
}
if ( c = = ' O ' | | ind = = SORT_ARG ) {
_switches [ SORT_ARG ] + + ;
_string_args [ SORT_ARG ] = optarg ;
2005-03-27 15:37:46 +04:00
}
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 ;
}
2009-09-11 19:53:57 +04:00
if ( c = = ' y ' | | ind = = YES_ARG )
_switches [ YES_ARG ] + + ;
2011-02-04 22:33:53 +03:00
if ( ind = = ADD_NODE_ON_RESUME_ARG )
_switches [ ADD_NODE_ON_RESUME_ARG ] + + ;
if ( ind = = ADD_NODE_ON_CREATE_ARG )
_switches [ ADD_NODE_ON_CREATE_ARG ] + + ;
2011-07-01 18:09:19 +04:00
if ( ind = = CHECKS_ARG )
_switches [ CHECKS_ARG ] + + ;
2010-02-15 19:21:33 +03:00
if ( ind = = UDEVCOOKIE_ARG ) {
_switches [ UDEVCOOKIE_ARG ] + + ;
_udev_cookie = _get_cookie_value ( optarg ) ;
}
2010-01-07 22:45:12 +03:00
if ( ind = = NOUDEVRULES_ARG )
_switches [ NOUDEVRULES_ARG ] + + ;
2009-07-31 21:51:45 +04:00
if ( ind = = NOUDEVSYNC_ARG )
_switches [ NOUDEVSYNC_ARG ] + + ;
2011-06-28 01:43:58 +04:00
if ( ind = = VERIFYUDEV_ARG )
_switches [ VERIFYUDEV_ARG ] + + ;
2006-02-03 17:23:22 +03:00
if ( c = = ' G ' | | ind = = GID_ARG ) {
_switches [ GID_ARG ] + + ;
2007-01-18 20:47:58 +03:00
_int_args [ GID_ARG ] = atoi ( optarg ) ;
2006-02-03 17:23:22 +03:00
}
if ( c = = ' U ' | | ind = = UID_ARG ) {
_switches [ UID_ARG ] + + ;
2007-01-18 20:47:58 +03:00
_int_args [ UID_ARG ] = atoi ( optarg ) ;
2006-02-03 17:23:22 +03:00
}
if ( c = = ' M ' | | ind = = MODE_ARG ) {
_switches [ MODE_ARG ] + + ;
/* FIXME Accept modes as per chmod */
2007-01-18 20:47:58 +03:00
_int_args [ MODE_ARG ] = ( int ) strtol ( optarg , NULL , 8 ) ;
2006-02-03 17:23:22 +03:00
}
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 ;
}
2009-11-06 03:43:08 +03:00
if ( ( ind = = INACTIVE_ARG ) )
_switches [ INACTIVE_ARG ] + + ;
2008-06-06 22:53:08 +04:00
if ( ( ind = = NAMEPREFIXES_ARG ) )
_switches [ NAMEPREFIXES_ARG ] + + ;
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 ] + + ;
2007-11-27 23:57:05 +03:00
if ( ( ind = = READAHEAD_ARG ) ) {
_switches [ READAHEAD_ARG ] + + ;
2007-11-29 17:44:28 +03:00
if ( ! strcasecmp ( optarg , " auto " ) )
_int_args [ READAHEAD_ARG ] = DM_READ_AHEAD_AUTO ;
else if ( ! strcasecmp ( optarg , " none " ) )
_int_args [ READAHEAD_ARG ] = DM_READ_AHEAD_NONE ;
else {
for ( s = optarg ; isspace ( * s ) ; s + + )
;
if ( * s = = ' + ' )
_read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG ;
_int_args [ READAHEAD_ARG ] = atoi ( optarg ) ;
if ( _int_args [ READAHEAD_ARG ] < - 1 ) {
log_error ( " Negative read ahead value "
" (%d) is not understood. " ,
_int_args [ READAHEAD_ARG ] ) ;
return 0 ;
}
}
2007-11-27 23:57:05 +03:00
}
2011-09-22 21:12:28 +04:00
if ( ( ind = = RETRY_ARG ) )
_switches [ RETRY_ARG ] + + ;
2008-06-25 02:53:48 +04:00
if ( ( ind = = ROWS_ARG ) )
_switches [ ROWS_ARG ] + + ;
2010-10-15 05:10:27 +04:00
if ( ( ind = = SETUUID_ARG ) )
_switches [ SETUUID_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 ] + + ;
2008-06-25 00:16:47 +04:00
if ( ( ind = = UNQUOTED_ARG ) )
_switches [ UNQUOTED_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 ;
}
2012-01-11 16:46:19 +04:00
if ( ! _process_options ( _string_args [ OPTIONS_ARG ] ) )
2005-10-16 18:33:22 +04:00
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 ;
}
2011-02-04 22:33:53 +03:00
if ( _switches [ ADD_NODE_ON_RESUME_ARG ] & & _switches [ ADD_NODE_ON_CREATE_ARG ] ) {
fprintf ( stderr , " --addnodeonresume and --addnodeoncreate 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 )
{
2005-10-16 18:33:22 +04:00
int r = 1 ;
2007-10-09 16:14:48 +04:00
const char * dev_dir ;
2011-03-02 05:44:56 +03:00
const struct command * cmd ;
int multiple_devices ;
2005-10-16 18:33:22 +04:00
2006-08-10 18:11:03 +04:00
( void ) setlocale ( LC_ALL , " " ) ;
2001-11-21 15:47:42 +03:00
2010-02-15 19:21:33 +03:00
dev_dir = getenv ( DM_DEV_DIR_ENV_VAR_NAME ) ;
2007-10-09 16:14:48 +04:00
if ( dev_dir & & * dev_dir ) {
if ( ! dm_set_dev_dir ( dev_dir ) ) {
2007-12-05 20:05:04 +03:00
fprintf ( stderr , " Invalid DM_DEV_DIR environment variable value. \n " ) ;
2007-10-09 16:14:48 +04:00
goto out ;
}
2007-12-05 20:05:04 +03:00
} else
2007-10-09 16:14:48 +04:00
dev_dir = DEFAULT_DM_DEV_DIR ;
if ( ! _process_switches ( & argc , & argv , dev_dir ) ) {
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
}
2010-03-08 19:05:07 +03:00
if ( _switches [ HELP_ARG ] ) {
2011-03-02 05:44:56 +03:00
cmd = _find_command ( " help " ) ;
2010-03-08 19:05:07 +03:00
goto doit ;
}
2003-07-04 23:38:49 +04:00
if ( _switches [ VERSION_ARG ] ) {
2011-03-02 05:44:56 +03:00
cmd = _find_command ( " version " ) ;
2003-07-04 23:38:49 +04:00
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
}
2011-03-02 05:44:56 +03:00
if ( ! ( cmd = _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
}
2011-03-02 05:44:56 +03:00
if ( argc < cmd - > min_args + 1 | |
( cmd - > max_args > = 0 & & argc > cmd - > 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
}
2011-03-02 05:44:56 +03:00
if ( ! _switches [ COLS_ARG ] & & ! strcmp ( cmd - > name , " splitname " ) )
2009-06-04 00:44:42 +04:00
_switches [ COLS_ARG ] + + ;
2010-08-03 16:56:00 +04:00
if ( _switches [ COLS_ARG ] ) {
2011-03-02 05:44:56 +03:00
if ( ! _report_init ( cmd ) )
2010-08-03 16:56:00 +04:00
goto out ;
if ( ! _report ) {
2011-03-02 05:44:56 +03:00
if ( ! strcmp ( cmd - > name , " info " ) )
2010-08-03 16:56:00 +04:00
r = 0 ; /* info -c -o help */
goto out ;
}
}
2007-01-24 21:09:07 +03:00
2010-02-15 19:21:33 +03:00
# ifdef UDEV_SYNC_SUPPORT
if ( ! _set_up_udev_support ( dev_dir ) )
goto out ;
# endif
2010-01-11 18:36:24 +03:00
2003-07-04 23:38:49 +04:00
doit :
2011-08-11 21:06:24 +04:00
multiple_devices = ( cmd - > repeatable_cmd & & argc ! = 2 & &
2011-08-11 23:18:17 +04:00
( argc ! = 1 | | ( ! _switches [ UUID_ARG ] & & ! _switches [ MAJOR_ARG ] ) ) ) ;
2011-03-02 05:44:56 +03:00
do {
if ( ! cmd - > fn ( cmd , argc - - , argv + + , NULL , multiple_devices ) ) {
fprintf ( stderr , " Command failed \n " ) ;
goto out ;
}
} while ( cmd - > repeatable_cmd & & argc > 1 ) ;
2001-11-21 15:47:42 +03:00
2005-10-16 18:33:22 +04:00
r = 0 ;
out :
2007-01-24 21:09:07 +03:00
if ( _report ) {
dm_report_output ( _report ) ;
dm_report_free ( _report ) ;
}
2007-06-11 17:20:29 +04:00
if ( _dtree )
dm_tree_free ( _dtree ) ;
2005-10-16 18:33:22 +04:00
return r ;
2001-11-21 15:47:42 +03:00
}