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>
2006-03-23 12:50:55 +03:00
# include "libvolume_id.h"
2005-02-23 04:58:31 +03:00
# include "util.h"
2005-01-31 07:28:44 +03:00
# define ISO_SUPERBLOCK_OFFSET 0x8000
# define ISO_SECTOR_SIZE 0x800
# define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
# define ISO_VD_PRIMARY 0x1
# define ISO_VD_SUPPLEMENTARY 0x2
# define ISO_VD_END 0xff
# define ISO_VD_MAX 16
2005-03-11 10:02:47 +03:00
struct iso_volume_descriptor {
2006-09-12 16:33:06 +04:00
uint8_t type ;
uint8_t id [ 5 ] ;
uint8_t version ;
2005-08-01 03:33:36 +04:00
uint8_t flags ;
uint8_t system_id [ 32 ] ;
uint8_t volume_id [ 32 ] ;
uint8_t unused [ 8 ] ;
uint8_t space_size [ 8 ] ;
uint8_t escape_sequences [ 8 ] ;
2006-02-21 20:44:18 +03:00
} PACKED ;
2005-03-11 10:02:47 +03:00
struct high_sierra_volume_descriptor {
2005-08-01 03:33:36 +04:00
uint8_t foo [ 8 ] ;
uint8_t type ;
2006-09-12 16:33:06 +04:00
uint8_t id [ 5 ] ;
2005-08-01 03:33:36 +04:00
uint8_t version ;
2006-02-21 20:44:18 +03:00
} PACKED ;
2005-02-09 03:02:18 +03:00
2006-07-25 16:59:50 +04:00
int volume_id_probe_iso9660 ( struct volume_id * id , uint64_t off , uint64_t size )
2005-01-31 07:28:44 +03:00
{
2005-08-01 03:33:36 +04:00
uint8_t * buf ;
2005-03-11 10:02:47 +03:00
struct iso_volume_descriptor * is ;
struct high_sierra_volume_descriptor * hs ;
2005-02-09 03:02:18 +03:00
2006-04-08 07:04:35 +04:00
info ( " probing at offset 0x%llx " , ( unsigned long long ) off ) ;
2005-01-31 07:28:44 +03:00
2005-03-11 10:02:47 +03:00
buf = volume_id_get_buffer ( id , off + ISO_SUPERBLOCK_OFFSET , 0x200 ) ;
if ( buf = = NULL )
2005-01-31 07:28:44 +03:00
return - 1 ;
2005-03-11 10:02:47 +03:00
is = ( struct iso_volume_descriptor * ) buf ;
2006-09-12 16:33:06 +04:00
if ( memcmp ( is - > id , " CD001 " , 5 ) = = 0 ) {
2005-01-31 07:28:44 +03:00
int vd_offset ;
int i ;
2005-03-11 10:02:47 +03:00
dbg ( " read label from PVD " ) ;
volume_id_set_label_raw ( id , is - > volume_id , 32 ) ;
volume_id_set_label_string ( id , is - > volume_id , 32 ) ;
2005-01-31 07:28:44 +03:00
2005-03-11 10:02:47 +03:00
dbg ( " looking for SVDs " ) ;
2005-01-31 07:28:44 +03:00
vd_offset = ISO_VD_OFFSET ;
for ( i = 0 ; i < ISO_VD_MAX ; i + + ) {
2005-08-01 03:33:36 +04:00
uint8_t svd_label [ 64 ] ;
2005-03-11 10:02:47 +03:00
is = ( struct iso_volume_descriptor * ) volume_id_get_buffer ( id , off + vd_offset , 0x200 ) ;
2006-09-12 16:33:06 +04:00
if ( is = = NULL | | is - > type = = ISO_VD_END )
2005-01-31 07:28:44 +03:00
break ;
2006-09-12 16:33:06 +04:00
if ( is - > type ! = ISO_VD_SUPPLEMENTARY )
2005-03-11 10:02:47 +03:00
continue ;
dbg ( " found SVD at offset 0x%llx " , ( unsigned long long ) ( off + vd_offset ) ) ;
if ( memcmp ( is - > escape_sequences , " %/@ " , 3 ) = = 0 | |
memcmp ( is - > escape_sequences , " %/C " , 3 ) = = 0 | |
memcmp ( is - > escape_sequences , " %/E " , 3 ) = = 0 ) {
dbg ( " Joliet extension found " ) ;
2005-08-01 03:33:36 +04:00
volume_id_set_unicode16 ( ( char * ) svd_label , sizeof ( svd_label ) , is - > volume_id , BE , 32 ) ;
2005-03-11 10:02:47 +03:00
if ( memcmp ( id - > label , svd_label , 16 ) = = 0 ) {
dbg ( " SVD label is identical, use the possibly longer PVD one " ) ;
break ;
}
volume_id_set_label_raw ( id , is - > volume_id , 32 ) ;
volume_id_set_label_string ( id , svd_label , 32 ) ;
strcpy ( id - > type_version , " Joliet Extension " ) ;
goto found ;
2005-01-31 07:28:44 +03:00
}
vd_offset + = ISO_SECTOR_SIZE ;
}
goto found ;
}
2005-03-11 10:02:47 +03:00
hs = ( struct high_sierra_volume_descriptor * ) buf ;
if ( memcmp ( hs - > id , " CDROM " , 5 ) = = 0 ) {
strcpy ( id - > type_version , " High Sierra " ) ;
2005-01-31 07:28:44 +03:00
goto found ;
2005-03-11 10:02:47 +03:00
}
2005-01-31 07:28:44 +03:00
return - 1 ;
found :
volume_id_set_usage ( id , VOLUME_ID_FILESYSTEM ) ;
id - > type = " iso9660 " ;
return 0 ;
}