2001-10-12 14:32:06 +04:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2006 Red Hat , Inc . All rights reserved .
2001-10-12 14:32:06 +04:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
2007-08-21 00:55:30 +04:00
* of the GNU Lesser General Public License v .2 .1 .
2004-03-30 23:35:44 +04:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 23:35:44 +04:00
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2001-10-12 14:32:06 +04:00
*/
2002-11-18 17:01:16 +03:00
# include "lib.h"
2001-10-12 14:32:06 +04:00
# include "uuid.h"
2008-12-07 07:23:37 +03:00
# include "lvm-wrappers.h"
2001-10-12 14:32:06 +04:00
2008-11-04 18:07:45 +03:00
# include <assert.h>
2001-10-12 14:32:06 +04:00
# include <sys/stat.h>
# include <unistd.h>
2008-08-29 04:49:46 +04:00
# include <ctype.h>
2001-10-12 14:32:06 +04:00
2008-08-07 17:59:49 +04:00
static const char _c [ ] =
2003-08-20 19:48:27 +04:00
" 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!# " ;
2001-10-12 14:32:06 +04:00
2001-12-11 14:40:34 +03:00
static int _built_inverse ;
2006-05-10 01:23:51 +04:00
static char _inverse_c [ 256 ] ;
2001-12-11 14:40:34 +03:00
2002-04-24 22:20:51 +04:00
int lvid_create ( union lvid * lvid , struct id * vgid )
{
memcpy ( lvid - > id , vgid , sizeof ( * lvid - > id ) ) ;
2005-01-20 21:11:53 +03:00
return id_create ( & lvid - > id [ 1 ] ) ;
2002-04-24 22:20:51 +04:00
}
2004-01-09 22:18:20 +03:00
void uuid_from_num ( char * uuid , uint32_t num )
{
unsigned i ;
for ( i = ID_LEN ; i ; i - - ) {
uuid [ i - 1 ] = _c [ num % ( sizeof ( _c ) - 1 ) ] ;
num / = sizeof ( _c ) - 1 ;
}
}
2002-12-20 02:25:55 +03:00
int lvid_from_lvnum ( union lvid * lvid , struct id * vgid , uint32_t lv_num )
2002-02-21 18:26:44 +03:00
{
int i ;
2002-03-05 23:03:09 +03:00
memcpy ( lvid - > id , vgid , sizeof ( * lvid - > id ) ) ;
2002-02-21 18:26:44 +03:00
for ( i = ID_LEN ; i ; i - - ) {
2002-03-05 23:03:09 +03:00
lvid - > id [ 1 ] . uuid [ i - 1 ] = _c [ lv_num % ( sizeof ( _c ) - 1 ) ] ;
2002-02-21 18:26:44 +03:00
lv_num / = sizeof ( _c ) - 1 ;
}
2002-03-05 23:03:09 +03:00
lvid - > s [ sizeof ( lvid - > s ) - 1 ] = ' \0 ' ;
2002-02-21 18:26:44 +03:00
return 1 ;
}
2002-03-05 23:03:09 +03:00
int lvnum_from_lvid ( union lvid * lvid )
2002-02-21 18:26:44 +03:00
{
int i , lv_num = 0 ;
2006-05-10 01:23:51 +04:00
char * c ;
2002-02-21 18:26:44 +03:00
for ( i = 0 ; i < ID_LEN ; i + + ) {
lv_num * = sizeof ( _c ) - 1 ;
2002-03-05 23:03:09 +03:00
if ( ( c = strchr ( _c , lvid - > id [ 1 ] . uuid [ i ] ) ) )
2002-02-21 18:26:44 +03:00
lv_num + = ( int ) ( c - _c ) ;
2008-08-28 22:41:51 +04:00
if ( lv_num < 0 )
lv_num = 0 ;
2002-02-21 18:26:44 +03:00
}
return lv_num ;
}
2008-08-28 22:41:51 +04:00
int lvid_in_restricted_range ( union lvid * lvid )
{
int i ;
for ( i = 0 ; i < ID_LEN - 3 ; i + + )
if ( lvid - > id [ 1 ] . uuid [ i ] ! = ' 0 ' )
return 0 ;
for ( i = ID_LEN - 3 ; i < ID_LEN ; i + + )
if ( ! isdigit ( lvid - > id [ 1 ] . uuid [ i ] ) )
return 0 ;
return 1 ;
}
2001-10-12 14:32:06 +04:00
int id_create ( struct id * id )
{
2006-05-10 01:23:51 +04:00
unsigned i ;
2002-12-20 02:25:55 +03:00
size_t len = sizeof ( id - > uuid ) ;
2001-10-12 14:32:06 +04:00
memset ( id - > uuid , 0 , len ) ;
2008-12-07 07:23:37 +03:00
if ( ! read_urandom ( & id - > uuid , len ) ) {
2001-10-12 14:32:06 +04:00
return 0 ;
}
2008-01-30 17:00:02 +03:00
/*
* Skip out the last 2 chars in randomized creation for LVM1
* backwards compatibility .
*/
2001-10-12 14:32:06 +04:00
for ( i = 0 ; i < len ; i + + )
2003-09-15 18:58:43 +04:00
id - > uuid [ i ] = _c [ id - > uuid [ i ] % ( sizeof ( _c ) - 3 ) ] ;
2001-10-12 14:32:06 +04:00
return 1 ;
}
2001-12-11 14:40:34 +03:00
/*
* The only validity check we have is that
* the uuid just contains characters from
* ' _c ' . A checksum would have been nice : (
*/
2002-12-20 02:25:55 +03:00
static void _build_inverse ( void )
2001-12-11 14:40:34 +03:00
{
2008-08-07 17:59:49 +04:00
const char * ptr ;
2001-12-11 14:40:34 +03:00
if ( _built_inverse )
return ;
2011-01-28 13:14:08 +03:00
_built_inverse = 1 ;
2001-12-11 14:40:34 +03:00
memset ( _inverse_c , 0 , sizeof ( _inverse_c ) ) ;
for ( ptr = _c ; * ptr ; ptr + + )
_inverse_c [ ( int ) * ptr ] = ( char ) 0x1 ;
}
2015-12-03 17:25:09 +03:00
static int _id_valid ( struct id * id , int e )
2001-10-12 14:32:06 +04:00
{
2001-12-11 14:40:34 +03:00
int i ;
_build_inverse ( ) ;
for ( i = 0 ; i < ID_LEN ; i + + )
if ( ! _inverse_c [ id - > uuid [ i ] ] ) {
2015-12-03 17:25:09 +03:00
if ( e )
log_error ( " UUID contains invalid character '%c' " , id - > uuid [ i ] ) ;
2001-12-11 14:40:34 +03:00
return 0 ;
}
2001-10-12 14:32:06 +04:00
return 1 ;
}
2015-12-03 17:25:09 +03:00
int id_valid ( struct id * id )
{
return _id_valid ( id , 1 ) ;
}
2002-12-20 02:25:55 +03:00
int id_equal ( const struct id * lhs , const struct id * rhs )
2001-10-12 14:32:06 +04:00
{
2002-01-15 13:24:48 +03:00
return ! memcmp ( lhs - > uuid , rhs - > uuid , sizeof ( lhs - > uuid ) ) ;
2001-10-12 14:32:06 +04:00
}
2001-12-11 14:40:34 +03:00
# define GROUPS (ID_LEN / 4)
2001-12-20 19:05:14 +03:00
2002-12-20 02:25:55 +03:00
int id_write_format ( const struct id * id , char * buffer , size_t size )
2001-12-11 14:40:34 +03:00
{
2002-01-04 19:55:14 +03:00
int i , tot ;
2011-02-18 17:47:28 +03:00
static const unsigned group_size [ ] = { 6 , 4 , 4 , 4 , 4 , 4 , 6 } ;
2001-12-11 14:40:34 +03:00
2002-01-04 19:55:14 +03:00
assert ( ID_LEN = = 32 ) ;
2004-03-30 18:36:50 +04:00
/* split into groups separated by dashes */
2002-01-04 19:55:14 +03:00
if ( size < ( 32 + 6 + 1 ) ) {
2016-05-31 10:56:10 +03:00
if ( size > 0 )
buffer [ 0 ] = ' \0 ' ;
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't write uuid, buffer too small. " ) ;
2001-12-11 14:40:34 +03:00
return 0 ;
2002-01-04 19:55:14 +03:00
}
2001-12-11 14:40:34 +03:00
2002-01-04 19:55:14 +03:00
for ( i = 0 , tot = 0 ; i < 7 ; i + + ) {
memcpy ( buffer , id - > uuid + tot , group_size [ i ] ) ;
buffer + = group_size [ i ] ;
tot + = group_size [ i ] ;
* buffer + + = ' - ' ;
2001-12-11 14:40:34 +03:00
}
2002-01-04 19:55:14 +03:00
* - - buffer = ' \0 ' ;
2001-12-11 14:40:34 +03:00
return 1 ;
}
2015-12-03 17:25:09 +03:00
static int _id_read_format ( struct id * id , const char * buffer , int e )
2001-12-11 14:40:34 +03:00
{
2002-01-04 19:55:14 +03:00
int out = 0 ;
2001-12-12 19:22:38 +03:00
2002-01-04 19:55:14 +03:00
/* just strip out any dashes */
while ( * buffer ) {
if ( * buffer = = ' - ' ) {
buffer + + ;
continue ;
}
if ( out > = ID_LEN ) {
2015-12-03 17:25:09 +03:00
if ( e )
log_error ( " Too many characters to be uuid. " ) ;
2002-01-04 19:55:14 +03:00
return 0 ;
}
id - > uuid [ out + + ] = * buffer + + ;
2001-12-11 14:40:34 +03:00
}
2002-01-04 19:55:14 +03:00
if ( out ! = ID_LEN ) {
2015-12-03 17:25:09 +03:00
if ( e )
log_error ( " Couldn't read uuid: incorrect number of "
" characters. " ) ;
2002-01-04 19:55:14 +03:00
return 0 ;
}
2001-12-11 14:40:34 +03:00
2015-12-03 17:25:09 +03:00
return _id_valid ( id , e ) ;
}
int id_read_format ( struct id * id , const char * buffer )
{
return _id_read_format ( id , buffer , 1 ) ;
}
int id_read_format_try ( struct id * id , const char * buffer )
{
return _id_read_format ( id , buffer , 0 ) ;
2001-12-11 14:40:34 +03:00
}
2010-09-30 18:07:33 +04:00
char * id_format_and_copy ( struct dm_pool * mem , const struct id * id )
{
char * repstr = NULL ;
if ( ! ( repstr = dm_pool_alloc ( mem , 40 ) ) ) {
log_error ( " dm_pool_alloc failed " ) ;
return NULL ;
}
if ( ! id_write_format ( id , repstr , 40 ) )
return_NULL ;
return repstr ;
}