2001-10-12 14:32:06 +04:00
/*
2004-03-30 23:35:44 +04: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 ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 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"
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
2006-05-10 01:23:51 +04:00
static 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 ) ;
}
return lv_num ;
}
2001-10-12 14:32:06 +04:00
int id_create ( struct id * id )
{
2006-05-10 01:23:51 +04:00
int randomfile ;
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 ) ;
2002-12-20 02:25:55 +03:00
if ( ( randomfile = open ( " /dev/urandom " , O_RDONLY ) ) < 0 ) {
2005-01-20 21:11:53 +03:00
log_sys_error ( " open " , " id_create: /dev/urandom " ) ;
2001-10-12 14:32:06 +04:00
return 0 ;
}
2006-05-10 01:23:51 +04:00
if ( read ( randomfile , id - > uuid , len ) ! = ( ssize_t ) len ) {
2005-01-20 21:11:53 +03:00
log_sys_error ( " read " , " id_create: /dev/urandom " ) ;
if ( close ( randomfile ) )
stack ;
2001-10-12 14:32:06 +04:00
return 0 ;
}
2005-01-20 21:11:53 +03:00
if ( close ( randomfile ) )
stack ;
2001-10-12 14:32:06 +04:00
2003-09-15 18:58:43 +04: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
{
char * ptr ;
if ( _built_inverse )
return ;
memset ( _inverse_c , 0 , sizeof ( _inverse_c ) ) ;
for ( ptr = _c ; * ptr ; ptr + + )
_inverse_c [ ( int ) * ptr ] = ( char ) 0x1 ;
}
2001-10-12 14:32:06 +04:00
int id_valid ( struct id * id )
{
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 ] ] ) {
log_err ( " UUID contains invalid character " ) ;
return 0 ;
}
2001-10-12 14:32:06 +04:00
return 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 ;
2002-12-20 02:25:55 +03:00
static 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 ) ) {
log_err ( " 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 ;
}
2002-12-20 02:25:55 +03:00
int id_read_format ( struct id * id , const char * buffer )
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 ) {
log_err ( " Too many characters to be uuid. " ) ;
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 ) {
log_err ( " Couldn't read uuid, incorrect number of characters. " ) ;
return 0 ;
}
2001-12-11 14:40:34 +03:00
return id_valid ( id ) ;
}