"Fossies" - the Fresh Open Source Software Archive

Member "zuluCrypt-5.7.1/zuluCrypt-cli/lib/status.c" (15 Jan 2020, 19203 Bytes) of package /linux/misc/zuluCrypt-5.7.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "status.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.7.0_vs_5.7.1.

    1 /*
    2  *
    3  *  Copyright (c) 2011-2015
    4  *  name : Francis Banyikwa
    5  *  email: mhogomchungu@gmail.com
    6  *  This program is free software: you can redistribute it and/or modify
    7  *  it under the terms of the GNU General Public License as published by
    8  *  the Free Software Foundation, either version 2 of the License, or
    9  *  (at your option) any later version.
   10  *
   11  *  This program is distributed in the hope that it will be useful,
   12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  *  GNU General Public License for more details.
   15  *
   16  *  You should have received a copy of the GNU General Public License
   17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
   18  */
   19 
   20 #include "includes.h"
   21 
   22 #include <sys/types.h>
   23 #include <sys/stat.h>
   24 #include <fcntl.h>
   25 #include <blkid/blkid.h>
   26 #include <sys/statvfs.h>
   27 #include <dirent.h>
   28 #include <stdio.h>
   29 #include <libcryptsetup.h>
   30 #include <fcntl.h>
   31 #include <unistd.h>
   32 
   33 #include "luks2_support.h"
   34 #include "zuluplay_support.h"
   35 #include "share_mount_prefix_path.h"
   36 
   37 #define SIZE 1024
   38 
   39 #define TYPE 3
   40 
   41 #define UUID 4
   42 
   43 /*
   44  * zuluCryptLoopDeviceAddress() is moved to create_loop.c
   45  */
   46 
   47 char * zuluCryptGetMountPointFromPath( const char * path ) ;
   48 
   49 typedef struct{
   50     string_t integrity_hash ;
   51     string_t integrity_keysize ;
   52 }authenticated_luks2 ;
   53 
   54 #ifdef CRYPT_LUKS2
   55 
   56 static int _is_authenticated_luks2( struct crypt_device * cd )
   57 {
   58     struct crypt_params_integrity m ;
   59 
   60     memset( &m,'\0',sizeof( m ) ) ;
   61 
   62     if( crypt_get_integrity_info( cd,&m ) == 0 ){
   63 
   64         return m.integrity != NULL ;
   65     }else{
   66         return 0 ;
   67     }
   68 }
   69 
   70 static void _authenticated_luks2( struct crypt_device * cd,authenticated_luks2 * s )
   71 {
   72     char buffer[ 1024 ] ;
   73 
   74     struct crypt_params_integrity m ;
   75 
   76     memset( &m,'\0',sizeof( m ) ) ;
   77     memset( buffer,'\0',sizeof( buffer ) ) ;
   78 
   79     if( crypt_get_integrity_info( cd,&m ) == 0 ){
   80 
   81         if( m.integrity != NULL ){
   82 
   83             s->integrity_hash = String_1( "/integrity: ",m.integrity,NULL ) ;
   84         }
   85 
   86         if( m.integrity_key_size != 0 ){
   87 
   88             snprintf( buffer,sizeof( buffer ),
   89                   "/integrity: %d bits",
   90                   ( int )m.integrity_key_size * 8 ) ;
   91 
   92             s->integrity_keysize = String( buffer ) ;
   93         }
   94     }
   95 }
   96 #else
   97 static void _authenticated_luks2( struct crypt_device * cd,authenticated_luks2 * s )
   98 {
   99     if( s && cd ){}
  100 }
  101 static int _is_authenticated_luks2( struct crypt_device * cd )
  102 {
  103     if( cd ){}
  104     return 0 ;
  105 }
  106 #endif
  107 
  108 static void _convert( char * buffer,size_t buffer_size,const char * s,u_int64_t y,u_int64_t z )
  109 {
  110     snprintf( buffer,buffer_size,"%.1f %s",( double )y/z,s ) ;
  111 }
  112 
  113 void zuluCryptFormatSize( u_int64_t number,char * buffer,size_t buffer_size )
  114 {
  115     const char * z = StringIntToString_1( buffer,buffer_size,number ) ;
  116 
  117     switch( StringSize( z ) ){
  118     case 0 :
  119     case 1 : case 2 : case 3 :
  120          snprintf( buffer,buffer_size,"%d B",( int )number ) ;
  121          break ;
  122     case 4 : case 5 : case 6 :
  123          _convert( buffer,buffer_size,"KB",number,1024 ) ;
  124          break ;
  125     case 7 : case 8 : case 9 :
  126          _convert( buffer,buffer_size,"MB",number,1024 * 1024 ) ;
  127          break ;
  128     case 10: case 11 : case 12 :
  129          _convert( buffer,buffer_size,"GB",number,1024 * 1024 * 1024 ) ;
  130          break ;
  131     case 13: case 14 : case 15 :
  132          _convert( buffer,buffer_size,"TB",number,1024 * 1024 * 1024 * 1024ll ) ;
  133          break ;
  134     default:
  135          _convert( buffer,buffer_size,"TB",number,1024 * 1024 * 1024 * 1024ll ) ;
  136          break ;
  137     }
  138 }
  139 
  140 static string_t _get_mapper_property_from_udev( const char * mapper,const char * prefix,size_t position )
  141 {
  142     DIR * dir = opendir( "/dev/disk/by-id/" ) ;
  143     struct dirent * e ;
  144 
  145     const char * f = mapper + StringSize( crypt_get_dir() ) + 1 ;
  146 
  147     stringList_t stl ;
  148 
  149     string_t st = StringVoid ;
  150 
  151     if( dir != NULL ){
  152 
  153         while( ( e = readdir( dir ) ) != NULL ){
  154 
  155             if( StringStartsAndEndsWith( e->d_name,prefix,f ) ){
  156 
  157                 stl = StringListSplit( e->d_name,'-' ) ;
  158 
  159                 st = StringListCopyStringAt( stl,position ) ;
  160 
  161                 StringListDelete( &stl ) ;
  162 
  163                 break ;
  164             }
  165         }
  166 
  167         closedir( dir ) ;
  168     }
  169 
  170     return st ;
  171 }
  172 
  173 static char * _get_uuid_from_udev( const char * mapper )
  174 {
  175     string_t st = _get_mapper_property_from_udev( mapper,"dm-uuid-CRYPT-LUKS",UUID ) ;
  176     return StringDeleteHandle( &st ) ;
  177 }
  178 
  179 static char * _get_type_from_udev( const char * mapper )
  180 {
  181     string_t st = _get_mapper_property_from_udev( mapper,"dm-uuid-CRYPT-",TYPE ) ;
  182 
  183     if( st == StringVoid ){
  184 
  185         return StringCopy_2( "Nil" ) ;
  186     }else{
  187         StringPrepend( st,"crypto_" ) ;
  188 
  189         return StringDeleteHandle( &st ) ;
  190     }
  191 }
  192 
  193 static string_t _get_type_from_udev_1( const char * mapper )
  194 {
  195     string_t st = _get_mapper_property_from_udev( mapper,"dm-uuid-CRYPT-",TYPE ) ;
  196 
  197     if( st == StringVoid ){
  198 
  199         /*
  200          * failed to discover volume type
  201          */
  202         return String( "Nil" ) ;
  203     }else{
  204         StringToLowerCase( st ) ;
  205 
  206         return st ;
  207     }
  208 }
  209 
  210 char * zuluCryptGetUUIDFromMapper( const char * mapper )
  211 {
  212     string_t uuid ;
  213     struct crypt_device * cd ;
  214 
  215     const char * id ;
  216     const char * e = " UUID:   \t\"Nil\"" ;
  217 
  218     char * f ;
  219 
  220     if( crypt_init_by_name( &cd,mapper ) < 0 ){
  221 
  222         uuid = String( e ) ;
  223     }else{
  224         id = crypt_get_uuid( cd ) ;
  225 
  226         if( id == NULL ){
  227 
  228             /*
  229              * Either not a LUKS volume or a LUKS volume but with a detached header.
  230              * consult udev to see if it can sort this volume out.
  231              */
  232 
  233             f = _get_uuid_from_udev( mapper ) ;
  234 
  235             if( f == NULL ){
  236 
  237                 uuid = String( e ) ;
  238             }else{
  239                 uuid = String_1( " UUID:   \t\"",f,"\"",NULL ) ;
  240                 StringFree( f ) ;
  241             }
  242 
  243         }else{
  244             uuid = String_1( " UUID:   \t\"",id,"\"",NULL ) ;
  245         }
  246 
  247         crypt_free( cd ) ;
  248     }
  249 
  250     return StringDeleteHandle( &uuid ) ;
  251 }
  252 
  253 void zuluCryptFileSystemProperties( string_t p,const char * mapper,const char * m_point )
  254 {
  255     const char * e ;
  256     blkid_probe blkid ;
  257     struct statvfs vfs ;
  258     u_int64_t total ;
  259     u_int64_t used ;
  260     u_int64_t unused ;
  261     u_int64_t block_size ;
  262     char buff[ SIZE ] ;
  263     char * buffer = buff ;
  264     string_t q ;
  265     ssize_t index ;
  266     struct stat statstr ;
  267 
  268     blkid = blkid_new_probe_from_filename( mapper ) ;
  269 
  270     if( blkid == NULL ){
  271 
  272         return ;
  273     }
  274 
  275     blkid_do_probe( blkid ) ;
  276 
  277     StringMultipleAppend( p,"\n file system:\t",zuluCryptVolumeType( blkid,mapper ),NULL ) ;
  278 
  279     blkid_free_probe( blkid ) ;
  280 
  281     if( statvfs( m_point,&vfs ) != 0 ){
  282         return ;
  283     }
  284 
  285     block_size = vfs.f_frsize ;
  286     total = block_size * vfs.f_blocks  ;
  287     unused =  block_size * vfs.f_bavail  ;
  288 
  289     used = total - unused ;
  290 
  291     zuluCryptFormatSize( total,buffer,SIZE ) ;
  292     StringMultipleAppend( p,"\n total space:\t",buffer,NULL ) ;
  293 
  294     zuluCryptFormatSize( used,buffer,SIZE ) ;
  295     StringMultipleAppend( p,"\n used space:\t",buffer,NULL ) ;
  296 
  297     zuluCryptFormatSize( unused,buffer,SIZE ) ;
  298     StringMultipleAppend( p,"\n free space:\t",buffer,NULL ) ;
  299 
  300     if( used == total ){
  301 
  302         StringAppend( p,"\n used%:   \t100%\n" ) ;
  303 
  304     }else if( used == 0 ){
  305 
  306         StringAppend( p,"\n used%:   \t0%\n" ) ;
  307     }else{
  308         snprintf( buff,SIZE,"%.2f%%",100 * ( ( float ) used / ( float ) total ) ) ;
  309         StringMultipleAppend( p,"\n used%:   \t",buff,"\n",NULL ) ;
  310     }
  311 
  312     buffer = zuluCryptGetUUIDFromMapper( mapper ) ;
  313     StringAppend( p,buffer ) ;
  314 
  315     StringFree( buffer ) ;
  316 
  317     StringMultipleAppend( p,"\n mount point1:\t",m_point,NULL ) ;
  318 
  319     q = String( m_point ) ;
  320     index = StringLastIndexOfChar( q,'/' ) ;
  321 
  322     if( index == -1 ){
  323 
  324         StringAppend( p,"\n mount point2:\tNil" ) ;
  325     }else{
  326         StringRemoveLeft( q,index ) ;
  327         e = StringPrepend( q,SHARE_MOUNT_PREFIX ) ;
  328 
  329         if( stat( e,&statstr ) == 0 ){
  330 
  331             StringMultipleAppend( p,"\n mount point2:\t",e,NULL ) ;
  332         }else{
  333             StringAppend( p,"\n mount point2:\tNil" ) ;
  334         }
  335     }
  336 
  337     StringDelete( &q ) ;
  338 }
  339 
  340 static int _string_starts_with( const char * a,const char * b )
  341 {
  342     return strncmp( a,b,strlen( b ) ) == 0 ;
  343 }
  344 
  345 static int _string_ends_with( const char * e,size_t ee,const char * s,size_t ss )
  346 {
  347     if( ee >= ss ){
  348         return memcmp( e + ee - ss,s,ss ) == 0 ;
  349     }else{
  350         return 0 ;
  351     }
  352 }
  353 
  354 static int _string_starts_and_ends_with( const char * a,const char * b,const char * c )
  355 {
  356     if( _string_starts_with( a,b ) ){
  357 
  358         return _string_ends_with( a,strlen( a ),c,strlen( c ) ) ;
  359     }else{
  360         return 0 ;
  361     }
  362 }
  363 
  364 static int _created_with_tcplay( const char * map_name )
  365 {
  366     DIR * dir = opendir( "/dev/disk/by-id/" ) ;
  367     struct dirent * e ;
  368 
  369     const char * m = strrchr( map_name,'/' ) ;
  370 
  371     if( m != NULL ){
  372 
  373         map_name = m + 1 ;
  374     }
  375 
  376     if( dir != NULL ){
  377 
  378         while( ( e = readdir( dir ) ) != NULL ){
  379 
  380             if ( _string_starts_and_ends_with( e->d_name,"dm-uuid-CRYPT-",map_name ) ){
  381 
  382                 if ( _string_starts_with( e->d_name,"dm-uuid-CRYPT-TCRYPT" ) ){
  383 
  384                     if ( _string_starts_with( e->d_name,"dm-uuid-CRYPT-TCRYPT-zuluCrypt" ) ){
  385 
  386                         return 0 ;
  387                     }else{
  388                         return 1 ;
  389                     }
  390 
  391                 }else if( _string_starts_with( e->d_name,"dm-uuid-CRYPT-VCRYPT" ) ) {
  392 
  393                     return 1 ;
  394                 }
  395 
  396                 break ;
  397             }
  398         }
  399 
  400         closedir( dir ) ;
  401     }
  402 
  403     return 0 ;
  404 }
  405 
  406 int zuluCryptVolumeManagedByTcplay( const char * mapper )
  407 {
  408     if( zuluCryptBitLockerVolume( mapper ) ){
  409 
  410         return 0 ;
  411     }else{
  412         return _created_with_tcplay( mapper ) ;
  413     }
  414 }
  415 
  416 static char * _get_type( struct crypt_device * cd,const char * mapper )
  417 {
  418     char * r ;
  419     string_t st ;
  420 
  421     const char * type = crypt_get_type( cd ) ;
  422 
  423     if( type == NULL ){
  424 
  425         if( StringHasComponent( mapper,"veracrypt" ) ){
  426 
  427             r = StringCopy_2( "crypto_VCRYPT" ) ;
  428 
  429         }else if( StringHasComponent( mapper,"truecrypt" ) ){
  430 
  431             r = StringCopy_2( "crypto_TCRYPT" ) ;
  432         }else{
  433             r = _get_type_from_udev( mapper ) ;
  434         }
  435     }else{
  436         if( _is_authenticated_luks2( cd ) ){
  437 
  438             st = String_1( "crypto_",type,"+",NULL ) ;
  439         }else{
  440             st = String_1( "crypto_",type,NULL ) ;
  441         }
  442 
  443         r = StringDeleteHandle( &st ) ;
  444     }
  445 
  446     return r ;
  447 }
  448 
  449 char * zuluCryptGetVolumeTypeFromMapperPath( const char * mapper )
  450 {
  451     struct crypt_device * cd ;
  452     char * r ;
  453 
  454     if( zuluCryptBitLockerVolume( mapper ) ){
  455 
  456         return StringCopy_2( zuluCryptBitLockerType() ) ;
  457     }
  458     if( crypt_init_by_name( &cd,mapper ) < 0 ){
  459 
  460         return StringCopy_2( "Nil" ) ;
  461     }
  462 
  463     r = _get_type( cd,mapper ) ;
  464 
  465     crypt_free( cd ) ;
  466 
  467     return r ;
  468 }
  469 
  470 char * zuluCryptGetVolumeType_1( const char * device )
  471 {
  472     struct crypt_device * cd ;
  473     char * r ;
  474 
  475     if( crypt_init( &cd,device ) != 0 ){
  476 
  477         return StringCopy_2( "Nil" ) ;
  478     }
  479     if( crypt_load( cd,NULL,NULL ) != 0 ){
  480 
  481         crypt_free( cd ) ;
  482         return StringCopy_2( "Nil" ) ;
  483     }
  484 
  485     r = _get_type( cd,"" ) ;
  486 
  487     crypt_free( cd ) ;
  488 
  489     return r ;
  490 }
  491 
  492 static void _device_info( string_t p,const char * device )
  493 {
  494     char * path ;
  495 
  496     if( device == NULL ){
  497 
  498         StringMultipleAppend( p,"\n device:   \t","Nil","\n loop:   \t","Nil",NULL ) ;
  499 
  500     }else if( StringPrefixEqual( device,"/dev/loop" ) ){
  501 
  502         if( zuluCryptMultiPartitionLoopDevice( device ) ){
  503 
  504             StringMultipleAppend( p,"\n device:   \t",device,"\n loop:   \t",device,NULL ) ;
  505         }else{
  506             path = zuluCryptLoopDeviceAddress_1( device ) ;
  507 
  508             if( path != NULL ){
  509 
  510                 StringMultipleAppend( p,"\n device:   \t",device,"\n loop:   \t",path,NULL ) ;
  511                 StringFree( path ) ;
  512             }else{
  513                 StringMultipleAppend( p,"\n device:   \t",device,"\n loop:   \tNil",NULL ) ;
  514             }
  515         }
  516     }else{
  517         /*
  518          * zuluCryptResolvePath() is defined in resolve_path.c
  519          */
  520         path = zuluCryptResolvePath( device ) ;
  521         StringMultipleAppend( p,"\n device:   \t",path,"\n loop:   \tNil",NULL ) ;
  522         StringFree( path ) ;
  523     }
  524 }
  525 
  526 typedef struct{
  527 
  528     const char * mapper ;
  529     void * argument ;
  530     void ( *function )( void *,const tcplay_volume_info * info ) ;
  531     void ( *format_offset )( u_int64_t offset,char * buffer,size_t s ) ;
  532 
  533 }mapper_info;
  534 
  535 static int _tcplay_info( const mapper_info * e )
  536 {
  537     int r = 1 ;
  538 
  539     tc_api_task task ;
  540 
  541     tcplay_volume_info info ;
  542 
  543     memset( &info,'\0',sizeof( info ) ) ;
  544 
  545     if( tc_api_initialize() ){
  546 
  547         if( tc_api_task_initialize( &task,"info_mapped" ) ){
  548 
  549             tc_api_task_set( task,"map_name",e->mapper ) ;
  550 
  551             tc_api_task_do( task ) ;
  552 
  553             info.format_offset = e->format_offset ;
  554 
  555             tc_api_task_info_get( task,"volume_info",sizeof( info ),&info ) ;
  556 
  557             e->function( e->argument,&info ) ;
  558 
  559             tc_api_task_uninit( task ) ;
  560 
  561             r = 0 ;
  562         }
  563 
  564         tc_api_uninit() ;
  565     }
  566 
  567     return r ;
  568 }
  569 
  570 typedef struct{
  571 
  572     const char * mapper ;
  573     string_t st ;
  574 
  575 } volume_properties ;
  576 
  577 static void _get_volume_properties( void * e,const tcplay_volume_info * info )
  578 {
  579     volume_properties * p = e ;
  580     string_t st = p->st ;
  581 
  582     StringMultipleAppend( st,p->mapper," ",info->status,".",NULL ) ;
  583 
  584     if( StringAtLeastOneMatch_1( info->status,"active","active and is in use",NULL ) ){
  585 
  586         StringMultipleAppend( st,
  587                       "\n type:   \t",info->type,
  588                       "\n cipher: \t",info->cipher,
  589                       "\n keysize:\t",info->keysize,
  590                       "\n offset: \t",info->offset,NULL ) ;
  591 
  592         _device_info( st,info->device ) ;
  593 
  594         StringMultipleAppend( st,"\n mode:   \t",info->mode,"\n active slots:\tNil",NULL ) ;
  595     }
  596 }
  597 
  598 static void _format_offset( u_int64_t offset,char * buffer,size_t s )
  599 {
  600     char tmp[ 128 ] ;
  601     char tmp_0[ 128 ] ;
  602 
  603     const char * e ;
  604 
  605     zuluCryptFormatSize( 512 * offset,tmp,sizeof( tmp ) ) ;
  606 
  607     e = StringIntToString_1( tmp_0,sizeof( tmp_0 ),offset ) ;
  608 
  609     snprintf( buffer,s,"%s sectors / %s",e,tmp ) ;
  610 }
  611 
  612 static string_t _get_crypto_info_from_tcplay( const char * mapper )
  613 {
  614     volume_properties p ;
  615     mapper_info e ;
  616 
  617     memset( &e,'\0',sizeof( e ) ) ;
  618     memset( &p,'\0',sizeof( p ) ) ;
  619 
  620     p.st = StringEmpty() ;
  621     p.mapper = mapper ;
  622 
  623     e.argument      = &p ;
  624     e.mapper        = mapper ;
  625     e.format_offset = _format_offset ;
  626     e.function      = _get_volume_properties ;
  627 
  628     if( _tcplay_info( &e ) != 0 ){
  629 
  630         StringMultipleAppend( p.st,mapper," is invalid.\n",NULL ) ;
  631     }
  632 
  633     return p.st ;
  634 }
  635 
  636 static void _get_volume_offset( void * e,const tcplay_volume_info * info )
  637 {
  638     u_int64_t * offset = e ;
  639 
  640     *offset = StringConvertToInt( info->offset ) ;
  641 }
  642 
  643 static void _format_offset_1( u_int64_t offset,char * buffer,size_t s )
  644 {
  645     char tmp[ 128 ] ;
  646     char tmp_0[ 128 ] ;
  647 
  648     const char * e ;
  649 
  650     zuluCryptFormatSize( 512 * offset,tmp,sizeof( tmp ) ) ;
  651 
  652     e = StringIntToString_1( tmp_0,sizeof( tmp_0 ),offset ) ;
  653 
  654     snprintf( buffer,s,"%s",e ) ;
  655 }
  656 
  657 static u_int64_t _crypt_get_data_offset( struct crypt_device * cd,const char * mapper,const char * type )
  658 {
  659     u_int64_t p = crypt_get_data_offset( cd ) ;
  660 
  661     mapper_info e ;
  662 
  663     if( p == 0 && ( type == NULL || StringPrefixEqual( type,"LUKS" ) ) ){
  664 
  665         /*
  666          * cryptsetup returns offset 0 with LUKS volumes that uses a detached header.
  667          *
  668          * We take this path here to ask tcplay to get the offset for us since cryptsetup
  669          * returns wrong info
  670          */
  671 
  672         memset( &e,'\0',sizeof( e ) ) ;
  673 
  674         e.argument      = &p ;
  675         e.mapper        = mapper ;
  676         e.format_offset = _format_offset_1 ;
  677         e.function      = _get_volume_offset ;
  678 
  679         _tcplay_info( &e ) ;
  680     }
  681 
  682     return p ;
  683 }
  684 
  685 static string_t _get_crypto_info_from_cryptsetup( const char * mapper )
  686 {
  687     char buff[ SIZE ] ;
  688     char * buffer = buff ;
  689 
  690     const char * z ;
  691     const char * type ;
  692 
  693     uint64_t e ;
  694 
  695     string_t q ;
  696     string_t p ;
  697 
  698     int k ;
  699     int i = 0 ;
  700     int j ;
  701 
  702     authenticated_luks2 auth_luks2 ;
  703 
  704     crypt_status_info info ;
  705 
  706     struct crypt_device * cd ;
  707 
  708     struct crypt_active_device cad ;
  709 
  710     if( crypt_init_by_name( &cd,mapper ) != 0 ){
  711 
  712         return StringVoid ;
  713     }
  714 
  715     memset( &auth_luks2,'\0',sizeof( auth_luks2 ) ) ;
  716 
  717     _authenticated_luks2( cd,&auth_luks2 ) ;
  718 
  719     p = String( mapper ) ;
  720 
  721     info = crypt_status( cd,mapper ) ;
  722 
  723     switch( info ){
  724     case CRYPT_INACTIVE :
  725         StringAppend( p," is inactive.\n" ) ;
  726         break ;
  727     case CRYPT_INVALID  :
  728         StringAppend( p," is invalid.\n" ) ;
  729         break ;
  730     case CRYPT_ACTIVE   :
  731         StringAppend( p," is active.\n" ) ;
  732         break ;
  733     case CRYPT_BUSY     :
  734         StringAppend( p," is active and is in use.\n" ) ;
  735         break ;
  736     default :
  737         StringAppend( p," is invalid.\n" ) ;
  738     }
  739 
  740     if( info == CRYPT_ACTIVE || info == CRYPT_BUSY ){
  741 
  742         StringAppend( p," type:   \t" ) ;
  743 
  744         type = crypt_get_type( cd ) ;
  745 
  746         if( type != NULL ){
  747 
  748             if( StringsAreEqual( type,zuluCryptCryptsetupBitLockerType() ) ){
  749 
  750                 q = String( zuluCryptBitLockerType() ) ;
  751 
  752                 StringReplaceString( q,"crypto_","" ) ;
  753             }else{
  754                 q = String( type ) ;
  755             }
  756 
  757             StringAppend( p,StringToLowerCase( q ) ) ;
  758 
  759             if( StringsAreEqual_2( q,"luks2" ) && auth_luks2.integrity_hash ){
  760 
  761                 StringAppend( p,"+" ) ;
  762             }
  763 
  764             StringDelete( &q ) ;
  765         }else{
  766             q = _get_type_from_udev_1( mapper ) ;
  767 
  768             StringAppendString( p,q ) ;
  769 
  770             StringDelete( &q ) ;
  771         }
  772 
  773         z = crypt_get_cipher( cd ) ;
  774 
  775         if( z != NULL ){
  776 
  777             StringMultipleAppend( p,"\n cipher:\t",z,"-",NULL ) ;
  778         }else{
  779             StringAppend( p,"\n cipher:\tNil-" ) ;
  780         }
  781 
  782         z = crypt_get_cipher_mode( cd ) ;
  783 
  784         if( z != NULL ){
  785 
  786             StringAppend( p,z ) ;
  787         }else{
  788             StringAppend( p,"Nil" ) ;
  789         }
  790 
  791         StringAppendString( p,auth_luks2.integrity_hash ) ;
  792 
  793         z = StringIntToString_1( buffer,SIZE,8 * crypt_get_volume_key_size( cd ) ) ;
  794         StringMultipleAppend( p,"\n keysize:\t",z," bits",NULL ) ;
  795 
  796         StringAppendString( p,auth_luks2.integrity_keysize ) ;
  797 
  798         e = _crypt_get_data_offset( cd,mapper,type ) ;
  799 
  800         z = StringIntToString_1( buffer,SIZE,e ) ;
  801         StringMultipleAppend( p,"\n offset:\t",z," sectors",NULL ) ;
  802 
  803         zuluCryptFormatSize( e * 512,buffer,SIZE ) ;
  804         StringMultipleAppend( p," / ",buffer,NULL ) ;
  805 
  806         _device_info( p,crypt_get_device_name( cd ) ) ;
  807 
  808         crypt_get_active_device( NULL,mapper,&cad ) ;
  809 
  810         if( cad.flags == 1 ){
  811 
  812             StringAppend( p,"\n mode:   \tread only" ) ;
  813         }else{
  814             StringAppend( p,"\n mode:   \tread and write" ) ;
  815         }
  816 
  817         k = crypt_keyslot_max( crypt_get_type( cd ) ) ;
  818 
  819         if( k > 0 ){
  820 
  821             i = 0 ;
  822 
  823             for( j = 0 ; j < k ; j++ ){
  824 
  825                 switch( crypt_keyslot_status( cd,j ) ){
  826 
  827                     case CRYPT_SLOT_ACTIVE_LAST : i++ ; break ;
  828                     case CRYPT_SLOT_ACTIVE      : i++ ; break ;
  829                     default : ;
  830                 }
  831             }
  832 
  833             StringMultipleAppend( p,"\n active slots:\t",StringIntToString_1( buffer,SIZE,i ),NULL ) ;
  834 
  835             StringMultipleAppend( p," / ",StringIntToString_1( buffer,SIZE,k ),NULL ) ;
  836         }else{
  837             StringAppend( p,"\n active slots:\tNil" ) ;
  838         }
  839     }
  840 
  841     crypt_free( cd ) ;
  842 
  843     StringDelete( &auth_luks2.integrity_hash ) ;
  844     StringDelete( &auth_luks2.integrity_keysize ) ;
  845 
  846     return p ;
  847 }
  848 
  849 char * zuluCryptVolumeStatus( const char * mapper )
  850 {
  851     char * path ;
  852 
  853     string_t p ;
  854 
  855     if( zuluCryptVolumeManagedByTcplay( mapper ) ){
  856 
  857         p = _get_crypto_info_from_tcplay( mapper ) ;
  858     }else{
  859         p = _get_crypto_info_from_cryptsetup( mapper ) ;
  860     }
  861 
  862     if( p == StringVoid ){
  863 
  864         return NULL ;
  865     }else{
  866         /*
  867          * zuluCryptGetMountPointFromPath() is defined in mountinfo.c
  868          */
  869         path = zuluCryptGetMountPointFromPath( mapper ) ;
  870 
  871         if( path != NULL ){
  872 
  873             zuluCryptFileSystemProperties( p,mapper,path ) ;
  874             StringFree( path ) ;
  875         }
  876 
  877         return StringDeleteHandle( &p ) ;
  878     }
  879 }
  880 
  881 typedef struct{
  882 
  883     char * device ;
  884     char * ( *function )( const char * ) ;
  885 
  886 }info_device ;
  887 
  888 static void _info_device( void * e,const tcplay_volume_info * info )
  889 {
  890     info_device * d = e ;
  891 
  892     d->device = d->function( info->device ) ;
  893 }
  894 
  895 char * zuluCryptVolumeDeviceName( const char * mapper )
  896 {
  897     struct crypt_device * cd ;
  898 
  899     mapper_info m ;
  900     info_device d ;
  901 
  902     char * f = NULL ;
  903 
  904     const char * e ;
  905 
  906     if( zuluCryptVolumeManagedByTcplay( mapper ) ){
  907 
  908         memset( &m,'\0',sizeof( m ) ) ;
  909         memset( &d,'\0',sizeof( d ) ) ;
  910 
  911         /*
  912          * zuluCryptResolvePath_3() is defined in resolve_path.c
  913          */
  914 
  915         d.function = zuluCryptResolvePath_3 ;
  916 
  917         m.argument      = &d ;
  918         m.mapper        = mapper ;
  919         m.function      = _info_device ;
  920 
  921         _tcplay_info( &m ) ;
  922 
  923         return d.device ;
  924     }else{
  925         if( crypt_init_by_name( &cd,mapper ) == 0 ){
  926 
  927             e = crypt_get_device_name( cd ) ;
  928 
  929             if( e != NULL ){
  930 
  931                 f = zuluCryptResolvePath_3( e ) ;
  932             }
  933 
  934             crypt_free( cd ) ;
  935         }
  936 
  937         return f ;
  938     }
  939 }