Running on Tumbleweed with kernel 6.2.12-1-default
Using the _GNU_SOURCE define should allow the use of SEEK_DATA as the whence value for lseek.
According to the man page this should work for a range of file systems. I have tested this code on btrfs and ext4 with the same result.
#define _GNU_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
void test(char *filepath) {
int write_value = 0x22;
int fh = open(filepath, O_CREAT | O_TRUNC | O_RDWR);
int os = lseek(fh, 10, SEEK_SET);
int wret = write(fh, &write_value, sizeof(int));
int os2 = lseek(fh, 0, SEEK_DATA);
printf("os: %d os2: %d wret %d\n", os, os2, wret);
close(fh);
}
Given the above code, I would expect SEEK_DATA to find the first written value at offset 10, and that os2 == os, yet lseek returns 0.
The file is indeed written as expected and od -x gives the following output:
0000000 0000 0000 0000 0000 0000 0022 0000
Any suggestions? Have I made an incorrect assumption about the expected behaviour...
Sparse files are implementation-specific. We can assume hole granularity depends on filesystem I/O block size.
I modified your program to make some tests:
Filesystem block size is usual:
Results:
Analysis:
Write offset 10:
| data |0 blocks of hole, 1 block of data. Data block starts at the beginning: os2 == 0.
Write offset 4095:
| data | data |0 blocks of hole, 2 blocks of data. Data block starts at the beginning: os2 == 0.
Write offset 4096:
| hole | data |1 block of hole, 1 block of data. Data block start from second, os2 == 4096.
Write offset 8191:
| hole | data | data |1 block of hole, 2 blocks of data. Data blocks start from second, os2 == 4096
Write offset 8192:
| hole | hole | data |2 blocks of hole, 1 blocks of data. Data blocks start from third, os2 == 8192
Write offset 8193: the same as 8192.
Observed results meet expected.