#include <stdio.h> /* printf, perror */
#include <sys/ioctl.h> /* ioctl */
#include <fcntl.h> /* open, O_RDONLY, off_t */
#include <linux/fs.h> /* FIGETBSZ */
#include <unistd.h> /* read, lseek, close */
#include <stdlib.h> /* strtoul */
int main(int argc, char **argv)
{
unsigned long i;
int fd; /* File descriptor returned from open */
unsigned long blocknum; /* The disk block (number) to read */
unsigned long offset; /* Where to start within the block */
off_t position; /* Position in the "file" to seek */
unsigned long bytes_to_read; /* How many bytes to read from the block */
int blocksize; /* The I/O block size */
char *partition; /* Partition provided by the user */
/* There are 4 required arguments to the program */
if (argc < 5)
{
printf("Usage: %s <partition> <block-number> <offset> <bytes-to-read>\n", argv[0]);
return 1;
}
partition = argv[1];
/* strtoul accepts hex and octal as well as decimal */
blocknum = strtoul(argv[2], 0, 0);
offset = strtoul(argv[3], 0, 0);
bytes_to_read = strtoul(argv[4], 0, 0);
/* Debugging stuff */
#if 0
printf(" Partition: %s\n", partition);
printf(" Blocknum: %lu\n", blocknum);
printf(" Offset: %lu\n", offset);
printf("bytes to read: %lu\n", bytes_to_read);
printf("start_byte: %lu\n", blocknum * blocksize + offset);
return 0;
#endif
/* Open the partition (everything is a file in Linux) */
fd = open(partition, O_RDONLY);
if (fd == -1)
{
perror("open");
return 2;
}
/* Get the block size of the filesystem */
if (ioctl(fd, FIGETBSZ, &blocksize) == -1)
{
perror("ioctl");
return 3;
}
/* Calculate the exact byte to start reading */
position = lseek(fd, blocknum * blocksize + offset, SEEK_SET);
if (position == -1)
{
perror("lseek");
return 2;
}
/* Just print out all of the bytes. Not the most efficient
* way, but just fine for a quick-and-dirty tool.
*/
for (i = 0; i < bytes_to_read; i++)
{
unsigned char c;
ssize_t count = read(fd, &c, 1);
/* Read error */
if (count == -1)
{
printf("Error reading byte %lu\n", i);
perror("read");
break;
}
fputc(c, stdout);
}
/* Done with partition */
close(fd);
return 0;
}