2011-12-22 01:30:48 +04:00
/*
* probe disks for filesystems and partitions
*
* Copyright ( C ) 2011 Kay Sievers < kay . sievers @ vrfy . org >
* Copyright ( C ) 2011 Karel Zak < kzak @ redhat . com >
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <stdio.h>
# include <stdlib.h>
# include <stdarg.h>
# include <unistd.h>
# include <string.h>
# include <errno.h>
# include <fcntl.h>
2011-12-23 06:16:56 +04:00
# include <getopt.h>
2011-12-22 01:30:48 +04:00
# include <sys/stat.h>
# include <blkid/blkid.h>
# include "udev.h"
2011-12-23 06:16:56 +04:00
static void print_property ( struct udev_device * dev , bool test , const char * name , const char * value )
2011-12-22 01:30:48 +04:00
{
2011-12-23 06:16:56 +04:00
char s [ 265 ] ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
s [ 0 ] = ' \0 ' ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
if ( ! strcmp ( name , " TYPE " ) ) {
udev_builtin_add_property ( dev , test , " ID_FS_TYPE " , value ) ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
} else if ( ! strcmp ( name , " VERSION " ) ) {
udev_builtin_add_property ( dev , test , " ID_FS_VERSION " , value ) ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
} else if ( ! strcmp ( name , " UUID " ) ) {
blkid_safe_string ( value , s , sizeof ( s ) ) ;
udev_builtin_add_property ( dev , test , " ID_FS_UUID " , s ) ;
blkid_encode_string ( value , s , sizeof ( s ) ) ;
udev_builtin_add_property ( dev , test , " ID_FS_UUID_ENC " , s ) ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
} else if ( ! strcmp ( name , " UUID_SUB " ) ) {
blkid_safe_string ( value , s , sizeof ( s ) ) ;
udev_builtin_add_property ( dev , test , " ID_FS_UUID_SUB " , s ) ;
blkid_encode_string ( value , s , sizeof ( s ) ) ;
udev_builtin_add_property ( dev , test , " ID_FS_UUID_SUB_ENC " , s ) ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
} else if ( ! strcmp ( name , " LABEL " ) ) {
blkid_safe_string ( value , s , sizeof ( s ) ) ;
udev_builtin_add_property ( dev , test , " ID_FS_LABEL " , s ) ;
blkid_encode_string ( value , s , sizeof ( s ) ) ;
udev_builtin_add_property ( dev , test , " ID_FS_LABEL_ENC " , s ) ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
} else if ( ! strcmp ( name , " PTTYPE " ) ) {
udev_builtin_add_property ( dev , test , " ID_PART_TABLE_TYPE " , value ) ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
} else if ( ! strcmp ( name , " PART_ENTRY_NAME " ) ) {
blkid_encode_string ( value , s , sizeof ( s ) ) ;
udev_builtin_add_property ( dev , test , " PART_ENTRY_NAME " , s ) ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
} else if ( ! strcmp ( name , " PART_ENTRY_TYPE " ) ) {
blkid_encode_string ( value , s , sizeof ( s ) ) ;
udev_builtin_add_property ( dev , test , " PART_ENTRY_TYPE " , s ) ;
2011-12-22 01:30:48 +04:00
2011-12-23 06:16:56 +04:00
} else if ( ! strncmp ( name , " PART_ENTRY_ " , 11 ) ) {
util_strscpyl ( s , sizeof ( s ) , " ID_ " , name , NULL ) ;
udev_builtin_add_property ( dev , test , name , value ) ;
}
2011-12-22 01:30:48 +04:00
}
static int probe_superblocks ( blkid_probe pr )
{
struct stat st ;
int rc ;
if ( fstat ( blkid_probe_get_fd ( pr ) , & st ) )
return - 1 ;
blkid_probe_enable_partitions ( pr , 1 ) ;
if ( ! S_ISCHR ( st . st_mode ) & & blkid_probe_get_size ( pr ) < = 1024 * 1440 & &
blkid_probe_is_wholedisk ( pr ) ) {
/*
* check if the small disk is partitioned , if yes then
* don ' t probe for filesystems .
*/
blkid_probe_enable_superblocks ( pr , 0 ) ;
rc = blkid_do_fullprobe ( pr ) ;
if ( rc < 0 )
return rc ; /* -1 = error, 1 = nothing, 0 = succes */
if ( blkid_probe_lookup_value ( pr , " PTTYPE " , NULL , NULL ) = = 0 )
return 0 ; /* partition table detected */
}
blkid_probe_set_partitions_flags ( pr , BLKID_PARTS_ENTRY_DETAILS ) ;
blkid_probe_enable_superblocks ( pr , 1 ) ;
return blkid_do_safeprobe ( pr ) ;
}
2011-12-23 05:02:44 +04:00
static int builtin_blkid ( struct udev_device * dev , int argc , char * argv [ ] , bool test )
2011-12-22 01:30:48 +04:00
{
2011-12-23 06:16:56 +04:00
struct udev * udev = udev_device_get_udev ( dev ) ;
2011-12-22 01:30:48 +04:00
int64_t offset = 0 ;
2011-12-23 06:16:56 +04:00
bool noraid = false ;
2011-12-22 01:30:48 +04:00
int fd = - 1 ;
blkid_probe pr ;
const char * data ;
const char * name ;
int nvals ;
int i ;
size_t len ;
int err = 0 ;
2011-12-23 06:16:56 +04:00
static const struct option options [ ] = {
{ " offset " , optional_argument , NULL , ' o ' } ,
{ " noraid " , no_argument , NULL , ' R ' } ,
{ }
} ;
for ( ; ; ) {
int option ;
option = getopt_long ( argc , argv , " oR " , options , NULL ) ;
if ( option = = - 1 )
break ;
switch ( option ) {
case ' o ' :
offset = strtoull ( optarg , NULL , 0 ) ;
break ;
case ' R ' :
noraid = true ;
break ;
}
}
2011-12-22 01:30:48 +04:00
pr = blkid_new_probe ( ) ;
if ( ! pr ) {
err = - ENOMEM ;
return EXIT_FAILURE ;
}
blkid_probe_set_superblocks_flags ( pr ,
BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE |
BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION ) ;
2011-12-23 06:16:56 +04:00
if ( noraid )
blkid_probe_filter_superblocks_usage ( pr , BLKID_FLTR_NOTIN , BLKID_USAGE_RAID ) ;
fd = open ( udev_device_get_devnode ( dev ) , O_RDONLY | O_CLOEXEC ) ;
2011-12-22 01:30:48 +04:00
if ( fd < 0 ) {
2011-12-23 06:16:56 +04:00
fprintf ( stderr , " error: %s: %m \n " , udev_device_get_devnode ( dev ) ) ;
2011-12-22 01:30:48 +04:00
goto out ;
}
err = blkid_probe_set_device ( pr , fd , offset , 0 ) ;
if ( err < 0 )
goto out ;
2011-12-23 06:16:56 +04:00
info ( udev , " probe %s %sraid offset=%llu " ,
udev_device_get_devnode ( dev ) ,
noraid ? " no " : " " , ( unsigned long long ) offset ) ;
2011-12-22 01:30:48 +04:00
err = probe_superblocks ( pr ) ;
if ( err < 0 )
goto out ;
nvals = blkid_probe_numof_values ( pr ) ;
for ( i = 0 ; i < nvals ; i + + ) {
if ( blkid_probe_get_value ( pr , i , & name , & data , & len ) )
continue ;
len = strnlen ( ( char * ) data , len ) ;
2011-12-23 06:16:56 +04:00
print_property ( dev , test , name , ( char * ) data ) ;
2011-12-22 01:30:48 +04:00
}
blkid_free_probe ( pr ) ;
out :
if ( fd > 0 )
close ( fd ) ;
if ( err < 0 )
return EXIT_FAILURE ;
return EXIT_SUCCESS ;
}
const struct udev_builtin udev_builtin_blkid = {
. name = " blkid " ,
. cmd = builtin_blkid ,
. help = " filesystem and partition probing " ,
2011-12-23 05:02:44 +04:00
. run_once = true ,
2011-12-22 01:30:48 +04:00
} ;