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 "logging.h"
# include "util.h"
2005-01-31 07:28:44 +03:00
2005-02-09 03:02:18 +03:00
struct mac_driver_desc {
2005-08-01 03:33:36 +04:00
uint8_t signature [ 2 ] ;
uint16_t block_size ;
uint32_t block_count ;
2005-02-09 03:02:18 +03:00
} __attribute__ ( ( __packed__ ) ) ;
2005-01-31 07:28:44 +03:00
2005-02-09 03:02:18 +03:00
struct mac_partition {
2005-08-01 03:33:36 +04:00
uint8_t signature [ 2 ] ;
uint16_t res1 ;
uint32_t map_count ;
uint32_t start_block ;
uint32_t block_count ;
uint8_t name [ 32 ] ;
uint8_t type [ 32 ] ;
2005-02-09 03:02:18 +03:00
} __attribute__ ( ( __packed__ ) ) ;
2005-01-31 07:28:44 +03:00
2005-08-01 03:33:36 +04:00
int volume_id_probe_mac_partition_map ( struct volume_id * id , uint64_t off )
2005-02-09 03:02:18 +03:00
{
2005-08-01 03:33:36 +04:00
const uint8_t * buf ;
2005-02-09 03:02:18 +03:00
struct mac_driver_desc * driver ;
struct mac_partition * part ;
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
buf = volume_id_get_buffer ( id , off , 0x200 ) ;
if ( buf = = NULL )
return - 1 ;
part = ( struct mac_partition * ) buf ;
2005-02-05 06:10:48 +03:00
if ( ( memcmp ( part - > signature , " PM " , 2 ) = = 0 ) & &
( memcmp ( part - > type , " Apple_partition_map " , 19 ) = = 0 ) ) {
2005-01-31 07:28:44 +03:00
/* linux creates an own subdevice for the map
* just return the type if the drive header is missing */
volume_id_set_usage ( id , VOLUME_ID_PARTITIONTABLE ) ;
id - > type = " mac_partition_map " ;
return 0 ;
}
driver = ( struct mac_driver_desc * ) buf ;
2005-02-05 06:10:48 +03:00
if ( memcmp ( driver - > signature , " ER " , 2 ) = = 0 ) {
2005-01-31 07:28:44 +03:00
/* we are on a main device, like a CD
* just try to probe the first partition from the map */
unsigned int bsize = be16_to_cpu ( driver - > block_size ) ;
int part_count ;
int i ;
/* get first entry of partition table */
buf = volume_id_get_buffer ( id , off + bsize , 0x200 ) ;
if ( buf = = NULL )
return - 1 ;
part = ( struct mac_partition * ) buf ;
2005-02-05 06:10:48 +03:00
if ( memcmp ( part - > signature , " PM " , 2 ) ! = 0 )
2005-01-31 07:28:44 +03:00
return - 1 ;
part_count = be32_to_cpu ( part - > map_count ) ;
dbg ( " expecting %d partition entries " , part_count ) ;
if ( id - > partitions ! = NULL )
free ( id - > partitions ) ;
id - > partitions =
malloc ( part_count * sizeof ( struct volume_id_partition ) ) ;
if ( id - > partitions = = NULL )
return - 1 ;
memset ( id - > partitions , 0x00 , sizeof ( struct volume_id_partition ) ) ;
id - > partition_count = part_count ;
for ( i = 0 ; i < part_count ; i + + ) {
2005-08-01 03:33:36 +04:00
uint64_t poff ;
uint64_t plen ;
2005-01-31 07:28:44 +03:00
buf = volume_id_get_buffer ( id , off + ( ( i + 1 ) * bsize ) , 0x200 ) ;
if ( buf = = NULL )
return - 1 ;
part = ( struct mac_partition * ) buf ;
2005-02-05 06:10:48 +03:00
if ( memcmp ( part - > signature , " PM " , 2 ) ! = 0 )
2005-01-31 07:28:44 +03:00
return - 1 ;
poff = be32_to_cpu ( part - > start_block ) * bsize ;
plen = be32_to_cpu ( part - > block_count ) * bsize ;
dbg ( " found '%s' partition entry at 0x%llx, len 0x%llx " ,
2005-03-10 02:58:01 +03:00
part - > type , ( unsigned long long ) poff , ( unsigned long long ) plen ) ;
2005-01-31 07:28:44 +03:00
id - > partitions [ i ] . off = poff ;
id - > partitions [ i ] . len = plen ;
2005-02-05 06:10:48 +03:00
if ( memcmp ( part - > type , " Apple_Free " , 10 ) = = 0 ) {
2005-01-31 07:28:44 +03:00
volume_id_set_usage_part ( & id - > partitions [ i ] , VOLUME_ID_UNUSED ) ;
2005-02-05 06:10:48 +03:00
} else if ( memcmp ( part - > type , " Apple_partition_map " , 19 ) = = 0 ) {
2005-01-31 07:28:44 +03:00
volume_id_set_usage_part ( & id - > partitions [ i ] , VOLUME_ID_PARTITIONTABLE ) ;
} else {
volume_id_set_usage_part ( & id - > partitions [ i ] , VOLUME_ID_UNPROBED ) ;
}
}
volume_id_set_usage ( id , VOLUME_ID_PARTITIONTABLE ) ;
id - > type = " mac_partition_map " ;
return 0 ;
}
return - 1 ;
}