@ -30,6 +30,7 @@
# define _GNU_SOURCE /* For strcasestr support */
# include <errno.h>
# include <sys/param.h>
# include <sys/ucred.h>
# include <sys/mount.h>
@ -246,24 +247,25 @@ static void parse_advanced_ata_fields(struct ata_params *buf, struct disk_proper
/* 2. Major ATA Version standard handling (Word 80 & Word 222 Transport Framework) */
if ( major = = 0xFFFF | | major = = 0x0000 ) {
strlcpy ( props - > ata_version , " Unknown " , sizeof ( props - > ata_version ) ) ;
fprintf ( stderr , " [WARNING] ATA Version unreadable: Word 80 reports invalid boundary (0x%04X) \n " , major ) ;
strlcpy ( props - > ata_version , " Unknown (Invalid Word 80) " , sizeof ( props - > ata_version ) ) ;
}
/*
* Detect actual ATA / ACS revision specification standard level by
* cross - verifying backward - compatible Word 80 flags against physical Word 222 transport bits .
*/
else if ( ( major & ( 1 < < 14 ) ) | | ( ( major & ( 1 < < 11 ) ) & & ( transport & 0x1000 ) & & ( transport & 0x0040 ) ) ) {
/* Word 80 Bit 14 OR (ATA8-ACS bit + SATA 3.1+ transport bit 12 + SATA 3.3 bit 6) -> ACS-4 */
strlcpy ( props - > ata_version , " ACS-4 " , sizeof ( props - > ata_version ) ) ;
} else if ( ( major & ( 1 < < 13 ) ) | | ( ( major & ( 1 < < 10 ) ) & & ( transport & 0x1000 ) ) ) {
/* Word 80 Bit 13 OR (ATA-7+ bit + SATA 3.1+ transport bit 12) -> ACS-3 */
strlcpy ( props - > ata_version , " ACS-3 " , sizeof ( props - > ata_version ) ) ;
} else if ( major & ( 1 < < 12 ) ) {
strlcpy ( props - > ata_version , " ACS-2 " , sizeof ( props - > ata_version ) ) ;
} else if ( major & ( 1 < < 11 ) ) {
} else if ( ( major & ( 1 < < 11 ) ) | | ( major & ( 1 < < 8 ) ) ) {
strlcpy ( props - > ata_version , " ATA8-ACS " , sizeof ( props - > ata_version ) ) ;
} else if ( major & ( 1 < < 10 ) ) {
} else if ( major & ( 1 < < 7 ) ) {
strlcpy ( props - > ata_version , " ATA/ATAPI-7 " , sizeof ( props - > ata_version ) ) ;
} else if ( major & ( 1 < < 6 ) ) {
strlcpy ( props - > ata_version , " ATA/ATAPI-6 " , sizeof ( props - > ata_version ) ) ;
} else {
snprintf ( props - > ata_version , sizeof ( props - > ata_version ) , " ATA Minor/Legacy (0x%04X) " , major ) ;
}
@ -276,7 +278,6 @@ static void parse_advanced_ata_fields(struct ata_params *buf, struct disk_proper
if ( transport ! = 0xFFFF & & transport ! = 0x0000 & & ( transport & 0x1000 ) ) {
if ( strcmp ( props - > ata_version , " ACS-4 " ) = = 0 ) {
/* ACS-4 devices can scale between SATA 3.2 and SATA 3.3 */
if ( ( transport & ( 1 < < 6 ) ) & & ( transport & 0x0100 ) ) {
ver = " SATA 3.3 " ;
} else {
@ -295,7 +296,6 @@ static void parse_advanced_ata_fields(struct ata_params *buf, struct disk_proper
else if ( sata_cap & 0x0002 ) ver = " SATA 1.0a " ;
}
/* Append signaling interface speed specs mapping data */
if ( sata_cap & 0x0006 ) {
snprintf ( props - > sata_version , sizeof ( props - > sata_version ) , " %s, 6.0 Gb/s " , ver ) ;
} else if ( sata_cap & 0x0004 ) {
@ -342,6 +342,17 @@ static void query_cam_properties(
strlcpy ( props - > sata_version , " N/A " , sizeof ( props - > sata_version ) ) ;
strlcpy ( props - > security_status , " N/A " , sizeof ( props - > security_status ) ) ;
/* CRITICAL Check: Permissions routing validation */
cam_dev = cam_open_device ( base_disk , O_RDWR ) ;
if ( cam_dev = = NULL ) {
if ( errno = = EACCES | | errno = = EPERM ) {
fprintf ( stderr , " [ERROR] %s: Permission denied. Accessing libcam transport layers requires root privileges (run with sudo). \n " , base_disk ) ;
} else {
fprintf ( stderr , " [ERROR] %s: Failed to open CAM device node (errno: %d) \n " , base_disk , errno ) ;
}
return ;
}
/* CRITICAL: Must use O_RDWR for transport-layer commands execution path to unlock */
cam_dev = cam_open_device ( base_disk , O_RDWR ) ;
if ( cam_dev = = NULL ) return ;
@ -418,6 +429,11 @@ static void query_cam_properties(
success = 1 ;
}
}
/* Filter out fake success on SAT(12) loop as well */
if ( success & & ident_buf - > model [ 0 ] = = 0 ) {
success = 0 ;
}
}
if ( success ) {
@ -463,7 +479,7 @@ static void query_cam_properties(
/* Parse advanced hardware descriptors from the verified buffer */
parse_advanced_ata_fields ( ident_buf , props ) ;
/* Parse Sector Sizes (Word 106: Physical sector size) */
/* Parse Sector Sizes (Word 106: Physical sector size / Advanced Format ) */
if ( ( ident_buf - > pss & 0x4000 ) & & ( ident_buf - > pss & 0x2000 ) ) {
props - > physical_sector_size = props - > logical_sector_size * ( 1 < < ( ident_buf - > pss & 0x000F ) ) ;
} else {
@ -478,6 +494,7 @@ static void query_cam_properties(
props - > smart_supported = 0 ; props - > smart_enabled = 0 ;
}
} else {
fprintf ( stderr , " [ERROR] %s: ATA Pass-Through rejected or returned empty payload (hardware timeout/fault) \n " , base_disk ) ;
* pt_failed = 1 ;
}
}
@ -493,61 +510,67 @@ static void query_cam_properties(
ccb - > ataio . cmd . command = 0xEC ;
if ( cam_send_ccb ( cam_dev , ccb ) = = 0 & & ( ccb - > ccb_h . status & CAM_STATUS_MASK ) = = CAM_REQ_CMP ) {
char real_model [ 41 ] ;
memcpy ( real_model , ident_buf - > model , sizeof ( ident_buf - > model ) ) ;
real_model [ sizeof ( ident_buf - > model ) ] = ' \0 ' ;
ata_str_fix ( real_model , sizeof ( real_model ) ) ;
if ( strlen ( real_model ) > 0 ) strlcpy ( props - > model , real_model , sizeof ( props - > model ) ) ;
char real_serial [ 21 ] ;
memcpy ( real_serial , ident_buf - > serial , sizeof ( ident_buf - > serial ) ) ;
real_serial [ sizeof ( ident_buf - > serial ) ] = ' \0 ' ;
ata_str_fix ( real_serial , sizeof ( real_serial ) ) ;
if ( strlen ( real_serial ) > 0 ) strlcpy ( props - > serial , real_serial , sizeof ( props - > serial ) ) ;
char real_fw [ 9 ] ;
memcpy ( real_fw , ident_buf - > revision , sizeof ( ident_buf - > revision ) ) ;
real_fw [ sizeof ( ident_buf - > revision ) ] = ' \0 ' ;
ata_str_fix ( real_fw , sizeof ( real_fw ) ) ;
if ( strlen ( real_fw ) > 0 ) strlcpy ( props - > fw_version , real_fw , sizeof ( props - > fw_version ) ) ;
/* Parse LU WWN Device ID */
uint64_t wwn_val = 0 ;
for ( int w = 0 ; w < 4 ; w + + ) {
wwn_val | = ( ( uint64_t ) ident_buf - > wwn [ w ] ) < < ( ( 3 - w ) * 16 ) ;
}
if ( wwn_val ! = 0 ) snprintf ( props - > wwn , sizeof ( props - > wwn ) , " %016llx " , ( unsigned long long ) wwn_val ) ;
else strlcpy ( props - > wwn , " N/A " , sizeof ( props - > wwn ) ) ;
/* Parse Rotation Rate and SSD state flags */
if ( ident_buf - > media_rotation_rate = = 1 ) {
props - > rotation_rate = 0 ;
* is_ssd = 1 ;
} else if ( ident_buf - > media_rotation_rate > 1 & & ident_buf - > media_rotation_rate < 0xFFFF ) {
props - > rotation_rate = ident_buf - > media_rotation_rate ;
* is_ssd = 0 ;
if ( ident_buf - > model [ 0 ] = = 0 ) {
fprintf ( stderr , " [ERROR] %s: IDENTIFY DEVICE returned empty payload (hardware fault) \n " , base_disk ) ;
} else {
props - > rotation_rate = - 1 ;
* is_ssd = 0 ;
}
char real_model [ 41 ] ;
memcpy ( real_model , ident_buf - > model , sizeof ( ident_buf - > model ) ) ;
real_model [ sizeof ( ident_buf - > model ) ] = ' \0 ' ;
ata_str_fix ( real_model , sizeof ( real_model ) ) ;
if ( strlen ( real_model ) > 0 ) strlcpy ( props - > model , real_model , sizeof ( props - > model ) ) ;
/* Parse advanced hardware descriptors from the direct AHCI buffer */
parse_advanced_ata_fields ( ident_buf , props ) ;
char real_serial [ 21 ] ;
memcpy ( real_serial , ident_buf - > serial , sizeof ( ident_buf - > serial ) ) ;
real_serial [ sizeof ( ident_buf - > serial ) ] = ' \0 ' ;
ata_str_fix ( real_serial , sizeof ( real_serial ) ) ;
if ( strlen ( real_serial ) > 0 ) strlcpy ( props - > serial , real_serial , sizeof ( props - > serial ) ) ;
/* Parse Sector Sizes (Word 106: Physical sector size) */
if ( ( ident_buf - > pss & 0x4000 ) & & ( ident_buf - > pss & 0x2000 ) ) {
props - > physical_sector_size = props - > logical_sector_size * ( 1 < < ( ident_buf - > pss & 0x000F ) ) ;
} else {
props - > physical_sector_size = props - > logical_sector_size ;
}
char real_fw [ 9 ] ;
memcpy ( real_fw , ident_buf - > revision , sizeof ( ident_buf - > revision ) ) ;
real_fw [ sizeof ( ident_buf - > revision ) ] = ' \0 ' ;
ata_str_fix ( real_fw , sizeof ( real_fw ) ) ;
if ( strlen ( real_fw ) > 0 ) strlcpy ( props - > fw_version , real_fw , sizeof ( props - > fw_version ) ) ;
/* Parse S.M.A.R.T. enablement states */
if ( ident_buf - > support . command1 & 0x0001 ) {
props - > smart_supported = 1 ;
props - > smart_enabled = ( ident_buf - > enabled . command1 & 0x0001 ) ? 1 : 0 ;
} else {
props - > smart_supported = 0 ; props - > smart_enabled = 0 ;
/* Parse LU WWN Device ID */
uint64_t wwn_val = 0 ;
for ( int w = 0 ; w < 4 ; w + + ) {
wwn_val | = ( ( uint64_t ) ident_buf - > wwn [ w ] ) < < ( ( 3 - w ) * 16 ) ;
}
if ( wwn_val ! = 0 ) snprintf ( props - > wwn , sizeof ( props - > wwn ) , " %016llx " , ( unsigned long long ) wwn_val ) ;
else strlcpy ( props - > wwn , " N/A " , sizeof ( props - > wwn ) ) ;
/* Parse Rotation Rate and SSD state flags */
if ( ident_buf - > media_rotation_rate = = 1 ) {
props - > rotation_rate = 0 ;
* is_ssd = 1 ;
} else if ( ident_buf - > media_rotation_rate > 1 & & ident_buf - > media_rotation_rate < 0xFFFF ) {
props - > rotation_rate = ident_buf - > media_rotation_rate ;
* is_ssd = 0 ;
} else {
props - > rotation_rate = - 1 ;
* is_ssd = 0 ;
}
/* Parse advanced hardware descriptors from the direct AHCI buffer */
parse_advanced_ata_fields ( ident_buf , props ) ;
/* Parse Sector Sizes (Word 106: Physical sector size / Advanced Format) */
if ( ( ident_buf - > pss & 0x4000 ) & & ( ident_buf - > pss & 0x2000 ) ) {
props - > physical_sector_size = props - > logical_sector_size * ( 1 < < ( ident_buf - > pss & 0x000F ) ) ;
} else {
props - > physical_sector_size = props - > logical_sector_size ;
}
/* Parse S.M.A.R.T. enablement states */
if ( ident_buf - > support . command1 & 0x0001 ) {
props - > smart_supported = 1 ;
props - > smart_enabled = ( ident_buf - > enabled . command1 & 0x0001 ) ? 1 : 0 ;
} else {
props - > smart_supported = 0 ; props - > smart_enabled = 0 ;
}
}
} else {
fprintf ( stderr , " [ERROR] %s: Native ATA IDENTIFY command rejected by the controller \n " , base_disk ) ;
}
}