2012-01-31 17 views
10

Usando el siguiente código, que soy capaz de abrir con éxito un disco sin procesar en mi máquina, pero cuando llego a la longitud de disco consigo 0 cada vez ...Open Sin editar discos y obtener el tamaño OS X

// Where "Path" is /dev/rdisk1 -- is rdisk1 versus disk1 the proper way to open a raw disk? 
Device = open(Path, O_RDWR); 
if (Device == -1) 
{ 
    throw xException("Error opening device"); 
} 

Y conseguir tamaño, con ambos de estos métodos devuelve 0:

struct stat st; 

if (stat(Path, &st) == 0) 
    _Length = st.st_size; 

/

_Length = (INT64)lseek(Device, 0, SEEK_END); 
     lseek(Device, 0, SEEK_SET); 

no estoy totalmente familiarizado con la programación en la no-ventana s plataformas, así que por favor perdona todo lo que parezca extraño. Mis preguntas aquí son:

  1. ¿Es esta la manera correcta de abrir un disco sin procesar en OS X?
  2. ¿Qué podría estar causando que el tamaño del disco se devuelva como 0?

El disco en cuestión es un disco sin formato, pero para aquellos que quieran la información de la Utilidad de Discos (con cosas no importantes eliminado):

Name : ST920217 AS Media 
Type : Disk 

Partition Map Scheme : Unformatted 
Disk Identifier  : disk1 
Media Name   : ST920217 AS Media 
Media Type   : Generic 
Writable    : Yes 
Total Capacity  : 20 GB (20,003,880,960 Bytes) 
Disk Number   : 1 
Partition Number  : 0 
+0

Si bien es una buena forma de acceder al disco sin procesar, obtener un tamaño así podría no funcionar como lo habías notado (también, probablemente deberías probar 'lseek64' primero). Es posible obtener el tamaño usando 'ioctl' o' fcntl'; de lo contrario, debe recurrir a obtener la información a través de alguna función especial específica de OSX. –

+0

@JoachimPileborg Bueno, tengo _FILE_OFFSET_BITS 64 definidos ... ¿no actúan de la misma manera? – Lander

+0

@JoachimPileborg haciendo: 'lseek (Dispositivo, 0x7FFFFFFF - 1, SEEK_SET)' en realidad devuelve 0x7FFFFFFE, por lo que se están descartando los bits o los discos no son compatibles con 'lseek (..., 0, SEEK_END);', pero desde mi entendiendo que deberían. editar: No sé por qué no hice 'lseek (Dispositivo, 0xFFFFFFFF + 5, SEEK_SET)' antes, pero eso devuelve 4, así que supongo que se están eliminando los bits. – Lander

Respuesta

8

Después de un poco de búsqueda a través de ioctl códigos de petición , Encontré algo que realmente funciona.

#include <sys/disk.h> 
#include <sys/ioctl.h> 
#include <fcntl.h> 

int main() 
{ 
    // Open disk 
    uint32_t dev = open("/dev/disk1", O_RDONLY); 

    if (dev == -1) { 
     perror("Failed to open disk"); 
     return -1; 
    } 

    uint64_t sector_count = 0; 
    // Query the number of sectors on the disk 
    ioctl(dev, DKIOCGETBLOCKCOUNT, &sector_count); 

    uint32_t sector_size = 0; 
    // Query the size of each sector 
    ioctl(dev, DKIOCGETBLOCKSIZE, &sector_size); 

    uint64_t disk_size = sector_count * sector_size; 
    printf("%ld", disk_size); 
    return 0; 
} 

Algo así debería hacer el truco. Acabo de copiar el código que tenía en eso, así que no estoy seguro de si se compilará bien, pero debería.

+0

Realmente no funcionará así - unsigned int Sectors debe estar al menos unsigned Long; de lo contrario, la primera ioctl provocará que otras variables de la pila se descarten ("dev" se escribe en cero con la configuración predeterminada del compilador y se prueba un disco razonablemente pequeño)) Más apropiadamente, estas variables deben ser uint64_t y uint32_t según las estructuras de datos en sys/disk.h – kert

+0

@kert good catch, actualizaré el código. – Lander