2001-10-12 10:32:06 +00:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
2001-10-31 12:47:01 +00:00
* This file is released under the LGPL .
2001-10-12 10:32:06 +00:00
*/
# include "uuid.h"
# include "log.h"
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
static unsigned char _c [ ] =
" 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " ;
2001-12-11 11:40:34 +00:00
static int _built_inverse ;
static unsigned char _inverse_c [ 256 ] ;
2001-10-12 10:32:06 +00:00
int id_create ( struct id * id )
{
int random , i , len = sizeof ( id - > uuid ) ;
memset ( id - > uuid , 0 , len ) ;
if ( ( random = open ( " /dev/urandom " , O_RDONLY ) ) < 0 ) {
log_sys_error ( " open " , " id_create " ) ;
return 0 ;
}
if ( read ( random , id - > uuid , len ) ! = len ) {
log_sys_error ( " read " , " id_create " ) ;
return 0 ;
}
close ( random ) ;
for ( i = 0 ; i < len ; i + + )
id - > uuid [ i ] = _c [ id - > uuid [ i ] % ( sizeof ( _c ) - 1 ) ] ;
return 1 ;
}
2001-12-11 11:40:34 +00:00
/*
* The only validity check we have is that
* the uuid just contains characters from
* ' _c ' . A checksum would have been nice : (
*/
void _build_inverse ( void )
{
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 10:32:06 +00:00
int id_valid ( struct id * id )
{
2001-12-11 11:40:34 +00: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 10:32:06 +00:00
return 1 ;
}
int id_cmp ( struct id * lhs , struct id * rhs )
{
return memcmp ( lhs - > uuid , rhs - > uuid , sizeof ( lhs - > uuid ) ) ;
}
2001-12-11 11:40:34 +00:00
# define GROUPS (ID_LEN / 4)
2001-12-20 11:52:54 +00:00
int id_write_format ( struct id * id , char * buffer , size_t size )
2001-12-11 11:40:34 +00:00
{
int i ;
/* split into 8 groups of four, with dashes in between */
if ( size < ( GROUPS * 5 ) )
return 0 ;
for ( i = 0 ; i < GROUPS ; i + + ) {
2001-12-12 16:22:38 +00:00
memcpy ( buffer + ( i * 5 ) , id - > uuid + ( i * 4 ) , 4 ) ;
2001-12-11 11:40:34 +00:00
buffer [ ( i * 5 ) + 4 ] = ' - ' ;
}
buffer [ GROUPS * 5 ] = ' \0 ' ;
return 1 ;
}
int id_read_format ( struct id * id , char * buffer )
{
2001-12-12 16:22:38 +00:00
int i ;
2001-12-11 11:40:34 +00:00
if ( strlen ( buffer ) < ( GROUPS * 5 ) ) {
log_err ( " Insufficient characters to be a proper uuid. " ) ;
return 0 ;
}
for ( i = 0 ; i < ID_LEN ; i + + )
id - > uuid [ i ] = buffer [ ( ( i / 4 ) * 5 ) + ( i % 4 ) ] ;
return id_valid ( id ) ;
}