Read a single sector from a disk

17,823

Solution 1

Try something like this to do it from the CLI:

# df -h .
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda2              27G   24G  1.6G  94% /
# dd bs=512 if=/dev/sda2 of=/tmp/sector200 skip=200 count=1
1+0 records in
1+0 records out

From man 4 sd:

FILES
   /dev/sd[a-h]: the whole device
   /dev/sd[a-h][0-8]: individual block partitions

And if you want to do this from within a program, just use a combination of system calls from man 2 ... like open, lseek,, and read, with the parameters from the dd example.

Solution 2

I'm not sure what the best programmatic approach is, but from the Linux command-line you could use the dd command in combination with the raw device for your disk to directly read from the disk.

You need to sudo this command to get access to the raw disk device (e.g. /dev/rdisk0).

For example, the following will read a single 512-byte block from an offset of 900 blocks from the top of disk0 and output it to stdout.

sudo dd if=/dev/rdisk0 bs=512 skip=900 count=1

See the dd man page to get additional information on the parameters to dd.

Solution 3

In C it is something like the following... It would require root permissions. I think you need to open the file with O_DIRECT if you want to read single sectors. Otherwise you'll get a page. I'm not sure if the aligned buffer is required for a read, but it is for a write.

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SECTOR_SIZE 512

int main(int argc, char *argv[]) {
        int offset = 0;
    int length = 5;
    int rc = -1;

    char *sector = aligned_alloc(SECTOR_SIZE, SECTOR_SIZE);
    memset(sector, 0, SECTOR_SIZE);
    /* replace XXX with the source block device */
    int fd=open("/dev/XXX", O_RDWR | O_DIRECT);

    lseek(fd, offset, SEEK_SET);
    for (int i = 0; i < length; i++) {
        rc = read(fd, sector, SECTOR_SIZE);
        if (rc < 0)
            printf("sector read error at offset = %d + %d\n %s", offset, i, strerror(errno));
        printf("Sector: %d\n", i);
        for (int j = 0; j < SECTOR_SIZE; j++) {
            printf("%x", sector[i]);
            if ((j + 1) % 16 == 0)
                printf("\n");
        }
    }
    free(sector);
    close(fd);
}
Share:
17,823
Admin
Author by

Admin

Updated on June 08, 2022

Comments

  • Admin
    Admin almost 2 years

    I am trying to read a single specific sector from the disk directly. I've currently run out of ideas and any suggestions how to go about it would be great!

  • caf
    caf over 14 years
    Given the sizes of disks these days, either use lseek64(), or #define _FILE_OFFSET_BITS 64 to ensure that off_t is a 64 bit type.
  • MarkR
    MarkR over 14 years
    Disc devices are not normally called /dev/rdisk0 under Linux, you probably want something like /dev/sda
  • yonigo
    yonigo over 10 years
    does skip/seek get me to a physical sector or logical block?
  • Mehdi Ijadnazar
    Mehdi Ijadnazar almost 8 years
    could you please mentions some specific c programming language functions to read and write on sectors
  • Mehdi Ijadnazar
    Mehdi Ijadnazar almost 8 years
    could you please give some c programming language specific functions to read and write to disk sectors?
  • Jonathan Geisler
    Jonathan Geisler about 3 years
    This didn't actually print anything on the screen for me, until I piped it into hexdump, e.g. sudo dd if=/dev/sda bs=512 skip=900 count=1 | hexdump -C