tags:

views:

149

answers:

3

What's the easiest way to access an ext3 file system at the block level? I don't care for the files, or raw bytes, I just have to read the FS one block at a time. Is there a simple way to do this (in C)? Or maybe a simple app whose source I could look into for inspiration? I found no usable tutorials on the net, and I'm a bit scared to dive into the kernel source to find out how to do it.

+1  A: 

Yes, see e2fsprogs. This provides tools you can use to do anything(!) with ext2, ext3, and ext4 filesystems. It also contains a library interface so you can do anything else.

See the included debugfs, it might be enough for you to start. Otherwise, check out the headers and write some code.

Adam Goode
+1  A: 

Disk devices, and partitions within them, behave just like regular files that you can read from (and write to), e.g.:

head -c 2048 /dev/sda1 > first_2048_bytes

You'll need to be root of course.

j_random_hacker
Usually you'd reach for `dd` first, I think... Linux doesn't care, but traditionally block devices only allowed block I/O.
ephemient
Agree with ephemient, dd is the better tool.
Tim Post
Agreed, just thought it might be helpful to point out that disk devices can be treated just like regular files (this was a surprise to me, coming from DOS years ago...)
j_random_hacker
DOS lets you treat devices like `LPT1` like regular files too ;) Really, though, Linux lets you do byte-aligned seeks/reads/writes on block devices, but most other UNIXes forbade that, so they can't really be treated like regular files.
ephemient
+3  A: 

If you want a simple app then I suggest you can take a look at "dd" utility. I comes as part of GNU Core Utility. Its source is available for download. Take a look at its home page, here.
If you want to achieve same from a C code, then please refer to following code. Hope this helps you. :)

#include <stdio.h>
#include <linux/fs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SECTOR_NO 10 /*read 10th sector*/

int main()
{
        int sector_size;
        char *buf;
        int n = SECTOR_NO;

        int fd = open("/dev/sda1", O_RDONLY|O_NONBLOCK);
        ioctl(fd, BLKSSZGET, &sector_size);
        printf("%d\n", sector_size);
        lseek(fd, n*sector_size, SEEK_SET);

        buf = malloc(sector_size);
        read(fd, buf, sector_size);

        return 0;
}
vinit dhatrak
Why O_NONBLOCK? Unless opening a special device (i.e. a modem), you would _want_ open to block on something busy or existentially challenged, yes?
Tim Post
Also, bdev_logical_block_size() in the kernel (which actually sets sector_size in your example by being returned by the ioctl handler) returns an unsigned short.
Tim Post
@tinkertim yes you are right !!!
vinit dhatrak
Still the best answer. 'dd' has been around since the dawn of UNIX for just that reason, its extremely useful and serves as a great example on how to manage block dev operations.
Tim Post
@tinkertim yes, bdev_logical_block_size() returns unsigned short but the ioctl returns int, I can see put_int at BLKSSZGET case in blkdev_ioctl() function so its safe to use int in user code.
vinit dhatrak
@vinit dhatrak: Now you are right!! :) I got caught up in thinking ioctl() would not returned a signed errno if the FD was indeed valid. Not enough coffee.
Tim Post