| //go:build !unix | |
| package bundle | |
| import "path/filepath" | |
| // inodeOf returns a portable fallback identity on platforms without | |
| // syscall.Stat_t inode access (e.g. Windows, wasm). It hashes the resolved | |
| // absolute path so the visited-set still de-duplicates a symlink that points at | |
| // a path already seen. This is weaker than a true inode (two distinct paths to | |
| // the same file via different hardlinks are not deduped), but it is sufficient | |
| // to break path-cycle symlink loops and never panics. | |
| func inodeOf(absPath string) (uint64, bool) { | |
| resolved, err := filepath.EvalSymlinks(absPath) | |
| if err != nil { | |
| resolved = filepath.Clean(absPath) | |
| } | |
| return fnv64a(resolved), true | |
| } | |
| // fnv64a is the standard FNV-1a 64-bit hash of s. | |
| func fnv64a(s string) uint64 { | |
| const ( | |
| offset = 1469598103934665603 | |
| prime = 1099511628211 | |
| ) | |
| h := uint64(offset) | |
| for i := 0; i < len(s); i++ { | |
| h ^= uint64(s[i]) | |
| h *= prime | |
| } | |
| return h | |
| } | |