donsetch 3.2.2 → 3.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/install.js +66 -10
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -60,17 +60,73 @@ if (!plat) {
60
60
  // The Linux binaries are glibc-linked. On musl systems they install
61
61
  // fine but can never exec (missing ld-linux loader) — fail HERE with
62
62
  // the actual cause instead of a cryptic spawn error on first run.
63
+ //
64
+ // Checking for /lib/ld-musl-*.so.1 existence is a false positive on
65
+ // glibc systems that also have musl installed as a secondary libc
66
+ // (e.g. Arch/Manjaro with the `musl` package). Instead, check what
67
+ // the RUNNING Node process actually uses: read /proc/self/exe's ELF
68
+ // interpreter (.interp section). On glibc it's ld-linux-*.so.2, on
69
+ // musl it's ld-musl-*.so.1. An env var escape hatch is also provided.
63
70
  if (process.platform === 'linux') {
64
- const isMusl = fs.existsSync('/lib/ld-musl-x86_64.so.1')
65
- || fs.existsSync('/lib/ld-musl-aarch64.so.1');
66
- if (isMusl) {
67
- console.error('donsetch: musl libc detected (Alpine?).');
68
- console.error('The prebuilt Linux binaries are glibc-linked and will not run.');
69
- console.error('');
70
- console.error('Options:');
71
- console.error(' - build from source: git clone https://github.com/' + REPO + ' && cargo build --release');
72
- console.error(' - use a glibc-based image/dist (debian, ubuntu, fedora)');
73
- process.exit(1);
71
+ // Escape hatch: force glibc path even on a musl system (user knows
72
+ // the binary will run, e.g. via gcompat or a glibc chroot).
73
+ if (process.env.DONSETCH_FORCE_GLIBC === '1') {
74
+ // skip musl check
75
+ } else {
76
+ let isMusl = false;
77
+ let detected = false;
78
+ try {
79
+ // Read the ELF interpreter of /proc/self/exe (this Node process).
80
+ // The .interp section starts at offset 0x18 in the ELF header
81
+ // for the program header table, but the reliable way is to parse
82
+ // the program headers for PT_INTERP.
83
+ const exe = '/proc/self/exe';
84
+ const fd = fs.openSync(exe, 'r');
85
+ // ELF header: first 64 bytes for 64-bit.
86
+ const hdr = Buffer.alloc(64);
87
+ fs.readSync(fd, hdr, 0, 64, 0);
88
+ // e_phoff at offset 0x20 (64-bit), e_phentsize at 0x36, e_phnum at 0x38.
89
+ const e_phoff = hdr.readBigUInt64LE(0x20);
90
+ const e_phentsize = hdr.readUInt16LE(0x36);
91
+ const e_phnum = hdr.readUInt16LE(0x38);
92
+ for (let i = 0; i < e_phnum; i++) {
93
+ const ph = Buffer.alloc(e_phentsize);
94
+ fs.readSync(fd, ph, 0, e_phentsize, Number(e_phoff) + i * e_phentsize);
95
+ // PT_INTERP = 3
96
+ if (ph.readUInt32LE(0) === 3) {
97
+ // p_offset at 0x08 (64-bit), p_filesz at 0x20.
98
+ const p_offset = Number(ph.readBigUInt64LE(0x08));
99
+ const p_filesz = ph.readBigUInt64LE(0x20);
100
+ const interp = Buffer.alloc(Number(p_filesz));
101
+ fs.readSync(fd, interp, 0, Number(p_filesz), p_offset);
102
+ const loaderPath = interp.toString('ascii').replace(/\0/g, '').trim();
103
+ isMusl = loaderPath.includes('ld-musl');
104
+ detected = true;
105
+ break;
106
+ }
107
+ }
108
+ fs.closeSync(fd);
109
+ } catch (_) {
110
+ // /proc/self/exe not readable (some containers). Fall back to
111
+ // the old existence check, but only as a last resort.
112
+ }
113
+ // Only fall back to the existence check if we could not read
114
+ // the ELF interpreter at all. A successful read that found glibc
115
+ // (isMusl=false, detected=true) must NOT fall back.
116
+ if (!detected) {
117
+ isMusl = fs.existsSync('/lib/ld-musl-x86_64.so.1')
118
+ || fs.existsSync('/lib/ld-musl-aarch64.so.1');
119
+ }
120
+ if (isMusl) {
121
+ console.error('donsetch: musl libc detected (Alpine?).');
122
+ console.error('The prebuilt Linux binaries are glibc-linked and will not run.');
123
+ console.error('');
124
+ console.error('Options:');
125
+ console.error(' - build from source: git clone https://github.com/' + REPO + ' && cargo build --release');
126
+ console.error(' - use a glibc-based image/dist (debian, ubuntu, fedora)');
127
+ console.error(' - set DONSETCH_FORCE_GLIBC=1 if you have a glibc compat layer (gcompat)');
128
+ process.exit(1);
129
+ }
74
130
  }
75
131
  }
76
132
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "donsetch",
3
- "version": "3.2.2",
3
+ "version": "3.2.4",
4
4
  "description": "Web fetch, search and crawl for AI agents. Zero API keys. Chrome-true TLS.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "author": "Bishesh Bhandari",