| 290 | // EEXIST race re-read so a symlink swapped in between our lstat and openSync |
| 291 | // can never be followed (Bugbot PR #557). |
| 292 | function _readWsIdGuarded(dir, file) { |
| 293 | try { |
| 294 | const dirStat = fs.lstatSync(dir, { throwIfNoEntry: false }); |
| 295 | if (dirStat && dirStat.isSymbolicLink()) return null; |
| 296 | const fileStat = fs.lstatSync(file, { throwIfNoEntry: false }); |
| 297 | if (!fileStat) return null; |
| 298 | if (fileStat.isSymbolicLink() || !fileStat.isFile()) return null; |
| 299 | const raw = fs.readFileSync(file, 'utf8').trim(); |
| 300 | return raw && /^[a-f0-9]{32,}$/i.test(raw) ? raw : null; |
| 301 | } catch { return null; } |
| 302 | } |
| 303 | |
| 304 | function _fsWorkspaceId(projectDir) { |
| 305 | // Whole body is wrapped: the documented contract is "returns null on ANY |