2002-12-20 02:25:55 +03: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 - 2007 Red Hat , Inc . All rights reserved .
2002-12-20 02:25:55 +03: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
2002-12-20 02:25:55 +03:00
*/
# include "lib.h"
# include "lvm-string.h"
2014-03-11 20:13:47 +04:00
# include "metadata-exported.h"
2002-12-20 02:25:55 +03:00
2006-08-21 16:54:53 +04:00
# include <ctype.h>
2014-04-15 15:27:47 +04:00
# include <stdarg.h>
2003-09-18 00:35:57 +04:00
int emit_to_buffer ( char * * buffer , size_t * size , const char * fmt , . . . )
{
int n ;
va_list ap ;
va_start ( ap , fmt ) ;
n = vsnprintf ( * buffer , * size , fmt , ap ) ;
va_end ( ap ) ;
2010-09-20 18:25:27 +04:00
/*
* Revert to old glibc behaviour ( version < = 2.0 .6 ) where snprintf
* returned - 1 if buffer was too small . From glibc 2.1 it returns number
* of chars that would have been written had there been room .
*/
if ( n < 0 | | ( ( unsigned ) n + 1 > * size ) )
n = - 1 ;
2007-08-22 18:38:18 +04:00
if ( n < 0 | | ( ( size_t ) n = = * size ) )
2003-09-18 00:35:57 +04:00
return 0 ;
* buffer + = n ;
* size - = n ;
return 1 ;
}
2004-02-13 17:43:35 +03:00
2010-11-17 13:19:29 +03:00
/*
* A - Za - z0 - 9. _ - + / = ! : & #
*/
int validate_tag ( const char * n )
{
register char c ;
2012-02-08 16:57:15 +04:00
/* int len = 0; */
2010-11-17 13:19:29 +03:00
if ( ! n | | ! * n )
return 0 ;
2012-02-08 16:57:15 +04:00
/* FIXME: Is unlimited tag size support needed ? */
while ( ( /* len++, */ c = * n + + ) )
2010-11-17 13:19:29 +03:00
if ( ! isalnum ( c ) & & c ! = ' . ' & & c ! = ' _ ' & & c ! = ' - ' & & c ! = ' + ' & & c ! = ' / '
& & c ! = ' = ' & & c ! = ' ! ' & & c ! = ' : ' & & c ! = ' & ' & & c ! = ' # ' )
return 0 ;
return 1 ;
}
2014-05-07 15:52:01 +04:00
static name_error_t _validate_name ( const char * n )
2006-04-19 19:33:07 +04:00
{
register char c ;
register int len = 0 ;
if ( ! n | | ! * n )
2014-05-07 15:52:01 +04:00
return NAME_INVALID_EMPTY ;
2006-04-19 19:33:07 +04:00
/* Hyphen used as VG-LV separator - ambiguity if LV starts with it */
if ( * n = = ' - ' )
2014-05-07 15:52:01 +04:00
return NAME_INVALID_HYPEN ;
2006-04-19 19:33:07 +04:00
2012-12-14 17:03:58 +04:00
if ( ( * n = = ' . ' ) & & ( ! n [ 1 ] | | ( n [ 1 ] = = ' . ' & & ! n [ 2 ] ) ) ) /* ".", ".." */
2014-05-07 15:52:01 +04:00
return NAME_INVALID_DOTS ;
2006-04-19 19:33:07 +04:00
while ( ( len + + , c = * n + + ) )
if ( ! isalnum ( c ) & & c ! = ' . ' & & c ! = ' _ ' & & c ! = ' - ' & & c ! = ' + ' )
2014-05-07 15:52:01 +04:00
return NAME_INVALID_CHARSET ;
2006-04-19 19:33:07 +04:00
if ( len > NAME_LEN )
2014-05-07 15:52:01 +04:00
return NAME_INVALID_LENGTH ;
2006-04-19 19:33:07 +04:00
2014-05-07 15:52:01 +04:00
return NAME_VALID ;
2013-09-26 20:37:40 +04:00
}
/*
* Device layer names are all of the form < vg > - < lv > - < layer > , any
* other hyphens that appear in these names are quoted with yet
* another hyphen . The top layer of any device has no layer
* name . eg , vg0 - lvol0 .
*/
int validate_name ( const char * n )
{
2014-05-07 15:52:01 +04:00
return ( _validate_name ( n ) = = NAME_VALID ) ? 1 : 0 ;
2006-04-19 19:33:07 +04:00
}
2010-04-23 18:16:32 +04:00
2014-04-07 22:19:14 +04:00
static const char * _lvname_has_reserved_prefix ( const char * lvname )
2010-04-23 18:16:32 +04:00
{
2014-04-07 22:19:14 +04:00
static const char _prefixes [ ] [ 12 ] = {
2011-09-06 19:38:44 +04:00
" pvmove " ,
2014-04-07 22:19:14 +04:00
" snapshot "
2011-09-06 19:38:44 +04:00
} ;
2014-04-07 22:19:14 +04:00
unsigned i ;
for ( i = 0 ; i < DM_ARRAY_SIZE ( _prefixes ) ; + + i )
if ( ! strncmp ( lvname , _prefixes [ i ] , strlen ( _prefixes [ i ] ) ) )
return _prefixes [ i ] ;
2011-09-06 19:38:44 +04:00
2014-04-07 22:19:14 +04:00
return NULL ;
}
static const char * _lvname_has_reserved_string ( const char * lvname )
{
static const char _strings [ ] [ 12 ] = {
2014-04-07 23:36:59 +04:00
" _cdata " ,
" _cmeta " ,
2011-09-06 19:38:44 +04:00
" _mimage " ,
2014-04-07 22:19:14 +04:00
" _mlog " ,
2013-07-05 19:10:47 +04:00
" _pmspare " ,
2011-09-06 19:38:44 +04:00
" _rimage " ,
" _rmeta " ,
2011-11-03 18:38:36 +04:00
" _tdata " ,
2011-09-06 19:38:44 +04:00
" _tmeta " ,
2014-04-07 22:19:14 +04:00
" _vorigin "
2011-09-06 19:38:44 +04:00
} ;
unsigned i ;
2014-04-07 22:19:14 +04:00
for ( i = 0 ; i < DM_ARRAY_SIZE ( _strings ) ; + + i )
if ( strstr ( lvname , _strings [ i ] ) )
return _strings [ i ] ;
return NULL ;
}
int apply_lvname_restrictions ( const char * name )
{
2011-09-06 19:38:44 +04:00
const char * s ;
2014-04-07 22:19:14 +04:00
if ( ( s = _lvname_has_reserved_prefix ( name ) ) ) {
log_error ( " Names starting \" %s \" are reserved. "
" Please choose a different LV name. " , s ) ;
return 0 ;
2011-09-06 04:26:42 +04:00
}
2014-04-07 22:19:14 +04:00
if ( ( s = _lvname_has_reserved_string ( name ) ) ) {
log_error ( " Names including \" %s \" are reserved. "
" Please choose a different LV name. " , s ) ;
return 0 ;
2011-09-06 04:26:42 +04:00
}
2010-04-23 18:16:32 +04:00
return 1 ;
}
2013-09-26 20:37:40 +04:00
/*
* Validates name and returns an emunerated reason for name validataion failure .
*/
name_error_t validate_name_detailed ( const char * name )
{
return _validate_name ( name ) ;
}
2010-04-23 18:16:32 +04:00
int is_reserved_lvname ( const char * name )
{
2014-04-07 22:19:14 +04:00
return ( _lvname_has_reserved_prefix ( name ) | |
_lvname_has_reserved_string ( name ) ) ? 1 : 0 ;
2010-04-23 18:16:32 +04:00
}
2011-08-30 18:55:15 +04:00
2014-03-11 20:13:47 +04:00
char * build_dm_uuid ( struct dm_pool * mem , const struct logical_volume * lv ,
2011-08-30 18:55:15 +04:00
const char * layer )
{
2014-03-11 20:13:47 +04:00
const char * lvid = lv - > lvid . s ;
2014-03-11 20:14:01 +04:00
if ( ! layer & & lv_is_thin_pool ( lv ) )
layer = " pool " ;
2011-08-30 18:55:15 +04:00
return dm_build_dm_uuid ( mem , UUID_PREFIX , lvid , layer ) ;
}