| 363 | // because the central directory only stores the upper 16 bits and loses |
| 364 | // the file-type bits on some producers. |
| 365 | function readUnixMode(buf, localOff, lNameLen, lExtraLen, cdP, cdExtraLen) { |
| 366 | // Local extra: walk header-id 0x000d blocks. |
| 367 | let q = localOff + 30 + lNameLen; |
| 368 | const lEnd = q + lExtraLen; |
| 369 | while (q + 4 <= lEnd) { |
| 370 | const hid = buf.readUInt16LE(q); |
| 371 | const hsz = buf.readUInt16LE(q + 2); |
| 372 | if (hid === 0x000d && hsz >= 12) { |
| 373 | return buf.readUInt16LE(q + 10); // mode at offset 10 within the UNIX block |
| 374 | } |
| 375 | q += 4 + hsz; |
| 376 | } |
| 377 | // Central directory fallback: upper 16 bits of external file attributes |
| 378 | // are the Unix mode for entries with version-made-by's host = UNIX (3). |
| 379 | return (buf.readUInt32LE(cdP + 38) >>> 16) & 0xffff; |
| 380 | } |
| 381 | |
| 382 | // --------------------------------------------------------------------------- |
| 383 | // Detect macOS Rosetta 2 translation. |