Compute a fingerprint for a file path.
Strategy:
- Read the file size (inquire(size=...)).
- Hash up to three blocks (head/mid/tail) using FNV-1a mixing.
- Combine with file size to reduce collision risk.
Missing/unreadable files return 0.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| character(len=*), | intent(in) | :: | path |
integer(int64) function file_fingerprint(path) result(fp) character(len=*), intent(in) :: path logical :: ex integer(int64) :: sz, h, n64, pos_mid, pos_end, pos_max integer :: u, ios, n inquire(file=trim(path), exist=ex, size=sz, iostat=ios) if (ios /= 0 .or. .not. ex) then fp = 0_int64 return end if if (sz <= 0_int64) then fp = 0_int64 return end if n64 = min(sz, int(BLOCK_SIZE, int64)) n = int(n64) open(newunit=u, file=trim(path), access="stream", form="unformatted", action="read", status="old", iostat=ios) if (ios /= 0) then fp = ieor(ishft(sz, 1), FNV_OFFSET) return end if if (.not. allocated(io_buf)) allocate(io_buf(BLOCK_SIZE)) h = FNV_OFFSET call hash_block(u, 1_int64, n, h) if (sz > n64) then pos_max = max(1_int64, sz - n64 + 1_int64) pos_mid = sz / 2_int64 - n64 / 2_int64 if (pos_mid < 1_int64) pos_mid = 1_int64 if (pos_mid > pos_max) pos_mid = pos_max pos_end = pos_max call hash_block(u, pos_mid, n, h) call hash_block(u, pos_end, n, h) end if close(u) fp = ieor(ishft(sz, 1), h) end function file_fingerprint