| //go:build unix | |
| package bundle | |
| import ( | |
| "os" | |
| "syscall" | |
| ) | |
| // inodeOf returns a stable identity (device+inode) for the file at absPath, | |
| // used to break symlink loops and de-duplicate symlink targets that point at | |
| // the same underlying file. On Unix it follows symlinks (os.Stat) so a symlink | |
| // and its target share one identity. | |
| func inodeOf(absPath string) (uint64, bool) { | |
| info, err := os.Stat(absPath) | |
| if err != nil { | |
| return 0, false | |
| } | |
| st, ok := info.Sys().(*syscall.Stat_t) | |
| if !ok { | |
| return 0, false | |
| } | |
| // Combine device and inode so identities are unique across filesystems. | |
| // Inode alone can collide between two mounts; XOR-folding dev in keeps the | |
| // visited-set safe without an allocation-heavy composite key. | |
| return uint64(st.Dev)<<32 ^ uint64(st.Ino), true | |
| } | |