Reputation: 773
I want to read a block device file, block by block until last byte even if the block is full of zeroes.
My code is this. size
is the no. of bytes I want it to read in one go - could be anything 4K, 8K etc.
for (int i = 1; i <= num; i++){
read_bytes = read(fd, buf, size);
if (read_bytes < 0) {
perror("read failed");
return 1;
}
lseek_offset = lseek(fd, size, SEEK_CUR);
if (lseek_offset < 0){
perror("lseek failed.\n");
return 1;
}
}
When a block is filled with zero bytes (not the length of block but the data in block), lseek fails with EINV.
And I can see from df -h
that that disk is half full and rest is zero bytes since it was formatted with ext4 before using it.
Upvotes: 0
Views: 517
Reputation: 2551
As already mentioned by @Mat in the comments read
already updates the file offset so you should remove the lseek
call. From read(2)
man pages:
On files that support seeking, the read operation commences at the current file offset, and the file offset is incremented by the number of bytes read. If the current file offset is at or past the end of file, no bytes are read, and read() returns zero.
Also note that the read
call might fail due to an interrupt, so you should check the value of errno
for that (I'm guessing you'd still like to continue reading).
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
for (int i = 1; i <= num; i++) {
read_bytes = read(fd, buf, size);
if (read_bytes < 0 && errno != EINTR) {
perror("read failed");
return 1;
}
}
Finally, note that you are not guaranteed that the size
number of bytes will be read in one go (see read(2)
), most likely because of a signal interrupt. So here's an idea of the top of my head. You could check file size in a while
loop within a single iteration of the for
loop to determine how much you still need to read. For example:
for (int i = 1; i <= num; i++) {
size_t remain = size;
while(remain) { // keep reading until you've read size bytes
read_bytes = read(fd, buf, remain);
if (read_bytes < 0 && errno != EINTR) {
perror("read failed");
return 1;
}
.... // determine the amount of bytes read in the last iteration
remain = ... // update the size to the bytes still needed to be read
}
}
Upvotes: 2