For fun and as practice I tried to create a program that writes a bit pattern to a specific sector of a hard drive. My idea was to be able to supply a specific sector number (in LBA format) and have the program try to write to it and then read from it and determine if the written and read is the same.
So far, the program works. However, I run into problems when dealing with very large drives (and therefor really large offsets).
For example, seeking from the beginning to LBA 1306638144 (i.e. seeking to 1306638144*512) overflows seek's off_t
.
//approximately what I am trying to achieve
#define SECTOR_SIZE 512
char buf[SECTOR_SIZE] = {0}; //would be initialised with a specific pattern
long long offset = 1306638144*SECTOR_SIZE
int fd = open("/dev/sdb", O_RDWR);
lseek(fd, offset, SEEK_SET); //offset overflows
write(fd, buf, sizeof(buf)/sizeof(char));
I tried working around the issue by iteratively increasing from SEEK_CUR
and avoiding passing the huge number.
Is there a proper way to deal with this issue? Is lseek() the wrong function to do this? Is there a better way to seek for a specific sector?
Best regards!
lseek
only accepts off_t
offset values and on most architectures, they are 32 bits signed long values. Even if you prepare a long long
offset it will be converted to a 32 bits value before being used.
But Posix now comes with lseek64
. It is almost the same function with same interface, except that it uses an off64_t
type offset which is guaranteed to have (at least) 64 bits.
So just use the new 64 bits enabled lseek64
instead of the legacy lseek
if you have to process files (or devices) where the offset could be greater that what can be represented with a (signed) 32 bits value.