2005-01-31 07:28:44 +03:00
/*
* volume_id - reads filesystem label and uuid
*
* Copyright ( C ) 2004 Kay Sievers < kay . sievers @ vrfy . org >
*
2005-09-27 18:27:35 +04:00
* 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 version 2 of the License .
2005-01-31 07:28:44 +03:00
*/
# ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# endif
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <errno.h>
# include <ctype.h>
2005-02-23 04:58:31 +03:00
# include "volume_id.h"
# include "util.h"
# include "logging.h"
2005-01-31 07:28:44 +03:00
2005-02-09 03:02:18 +03:00
struct ext2_super_block {
2005-10-23 19:41:55 +04:00
uint32_t s_inodes_count ;
uint32_t s_blocks_count ;
uint32_t s_r_blocks_count ;
uint32_t s_free_blocks_count ;
uint32_t s_free_inodes_count ;
uint32_t s_first_data_block ;
uint32_t s_log_block_size ;
uint32_t s_log_frag_size ;
uint32_t s_blocks_per_group ;
uint32_t s_frags_per_group ;
uint32_t s_inodes_per_group ;
uint32_t s_mtime ;
uint32_t s_wtime ;
uint16_t s_mnt_count ;
uint16_t s_max_mnt_count ;
uint16_t s_magic ;
uint16_t s_state ;
uint16_t s_errors ;
uint16_t s_minor_rev_level ;
uint32_t s_lastcheck ;
uint32_t s_checkinterval ;
uint32_t s_creator_os ;
uint32_t s_rev_level ;
uint16_t s_def_resuid ;
uint16_t s_def_resgid ;
uint32_t s_first_ino ;
uint16_t s_inode_size ;
uint16_t s_block_group_nr ;
uint32_t s_feature_compat ;
uint32_t s_feature_incompat ;
uint32_t s_feature_ro_compat ;
uint8_t s_uuid [ 16 ] ;
uint8_t s_volume_name [ 16 ] ;
2006-02-21 20:44:18 +03:00
} PACKED ;
2005-02-09 03:02:18 +03:00
2005-10-23 19:41:55 +04:00
# define EXT_SUPER_MAGIC 0xEF53
2005-01-31 07:28:44 +03:00
# define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
# define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
# define EXT_SUPERBLOCK_OFFSET 0x400
2005-10-23 19:41:55 +04:00
# define EXT3_MIN_BLOCK_SIZE 0x400
# define EXT3_MAX_BLOCK_SIZE 0x1000
2005-08-01 03:33:36 +04:00
int volume_id_probe_ext ( struct volume_id * id , uint64_t off )
2005-01-31 07:28:44 +03:00
{
2005-02-09 03:02:18 +03:00
struct ext2_super_block * es ;
2005-10-23 19:41:55 +04:00
size_t bsize ;
2005-02-09 03:02:18 +03:00
2005-03-10 02:58:01 +03:00
dbg ( " probing at offset 0x%llx " , ( unsigned long long ) off ) ;
2005-01-31 07:28:44 +03:00
es = ( struct ext2_super_block * ) volume_id_get_buffer ( id , off + EXT_SUPERBLOCK_OFFSET , 0x200 ) ;
if ( es = = NULL )
return - 1 ;
2005-10-23 19:41:55 +04:00
if ( es - > s_magic ! = cpu_to_le16 ( EXT_SUPER_MAGIC ) )
2005-01-31 07:28:44 +03:00
return - 1 ;
2005-10-23 23:12:51 +04:00
bsize = 0x400 < < le32_to_cpu ( es - > s_log_block_size ) ;
dbg ( " ext blocksize 0x%zx " , bsize ) ;
if ( bsize < EXT3_MIN_BLOCK_SIZE | | bsize > EXT3_MAX_BLOCK_SIZE ) {
dbg ( " invalid ext blocksize " ) ;
return - 1 ;
}
2005-10-23 19:41:55 +04:00
volume_id_set_label_raw ( id , es - > s_volume_name , 16 ) ;
volume_id_set_label_string ( id , es - > s_volume_name , 16 ) ;
volume_id_set_uuid ( id , es - > s_uuid , UUID_DCE ) ;
snprintf ( id - > type_version , sizeof ( id - > type_version ) - 1 ,
" %u.%u " , es - > s_rev_level , es - > s_minor_rev_level ) ;
/* check for external journal device */
if ( ( le32_to_cpu ( es - > s_feature_incompat ) & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV ) ! = 0 ) {
volume_id_set_usage ( id , VOLUME_ID_OTHER ) ;
id - > type = " jbd " ;
return 0 ;
}
/* check for ext2 / ext3 */
volume_id_set_usage ( id , VOLUME_ID_FILESYSTEM ) ;
if ( ( le32_to_cpu ( es - > s_feature_compat ) & EXT3_FEATURE_COMPAT_HAS_JOURNAL ) ! = 0 )
2005-01-31 07:28:44 +03:00
id - > type = " ext3 " ;
else
id - > type = " ext2 " ;
return 0 ;
}