Ok. I'm going to explain all this business. It's about some new developments in loaders-update.
Among others things, this script tests the content of a freebsd-boot partition in order to know if it contains gptboot or gptzfsboot. I wasn't and I'm still not satisfied the way it operates. The current distributed version just tests if it finds the strings 'ZFS' and 'zfs' (with grep). If not, it's gptboot; a questionable logic.
I added the detection of a string that belongs to the BTX loader. So, it will find if the partition has never been filled at all with a FreeBSD BIOS loader. Fine, but after several tests I found a bug, a very special case...
What about if a partition has been filled first with gptzfsboot, then filled with gptboot in a second time? As the size of gptboot is very inferior to the one of gptzfsboot, the strings 'ZFS' and 'zfs' remain in the partition and it's falsely detected as gptzfsboot.
Hence the idea to detect the end of the file: an area with many 0 bytes. I compare it with the offset where 'ZFS' has been localized. If it's inferior, it means we are in this special case and it is gptboot in fact.
For the moment, I stick with the covacat solution because it's the simplest and the quickest:
eof=$(cat "$p" | tr '\0' K | grep -b -m1 -E 'K{24}' | cut -f1 -d ':')
$p is the partition to examine.
I transformed the
Kai Burghardt script in a simplified function that works as well, but it's slower (and I didn't understand why it also does not give the right offset):
Code:
# DetectEOF FileToExamine NumberOfZeroWanted
DetectEOF()
{
local current previous
unset previous
{ cat "$1" | cmp -l - /dev/zero 2>&-
} | { while read -r current sample zero
do
if [ ${current} -gt $((${previous} + $2)) ]; then
printf '%d\n' $((${previous} + 1))
return
fi
previous=${current}
done
}
}
How about this suggestion: A really simple C program, which copies characters one at a time from stdin to stdout, turning every nul byte into the letter "0", and every non-null byte into the letter "X"? Then compile and link it (that's a single command, cc foo.c -o foo), and run it in a pipeline. Having done that conversion, you can use grep to find a sequence of 16 "0" in a row. If grep has a problem with the fact that the input string is a single "line" with no terminating newline, add a putchar('\n') at the end, before the return.
That will be the best solution because I realize that grep isn't good for binary file. It is not only for a sequence of zero, but for all strings detection. The problem is that supposes to compile a part of the port. I don't want to go in this way for the moment.
Maybe a simplest alternative would be to add a dependency with a tool that do well the job and designed for that: retrieve the offset of a string in a binary file. Anyone knows a suited port?
I admit, I don't like to be dependent of another software.