Skip to content

Commit bd1270d

Browse files
committed
feat: auto-detect musl-specific dynamic linker files in the filesystem
1 parent f4b8c9b commit bd1270d

2 files changed

Lines changed: 52 additions & 43 deletions

File tree

src/releases/github.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@
4444
* ```
4545
*/
4646

47-
import { chmodSync, existsSync } from 'node:fs'
48-
import { readFile, writeFile } from 'node:fs/promises'
49-
import path from 'node:path'
47+
import { chmodSync, existsSync } from 'fs'
48+
import { readFile, writeFile } from 'fs/promises'
49+
import path from 'path'
5050

5151
import { safeMkdir } from '../fs.js'
5252
import { httpDownload, httpRequest } from '../http-request.js'

src/releases/socket-btm.ts

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
* @fileoverview Socket-btm release download utilities.
33
*
44
* Provides utilities for downloading binaries and assets from the
5-
* SocketDev/socket-btm GitHub repository. This includes build tools (binject,
6-
* binflate, binpress), Node.js binaries (node-smol), and WASM assets
7-
* (yoga-layout).
5+
* SocketDev/socket-btm GitHub repository. This includes build tools,
6+
* Node.js binaries, and WASM assets.
87
*
98
* Features:
109
* - Generic function for any socket-btm release asset or binary
@@ -20,40 +19,10 @@
2019
* ├── {binaryName}
2120
* └── .version
2221
* ```
23-
*
24-
* @example
25-
* ```ts
26-
* import { downloadSocketBtmRelease } from '@socketsecurity/lib/releases/socket-btm'
27-
*
28-
* // Download node-smol binary (like: brew install nodejs → /usr/local/bin/node)
29-
* const nodePath = await downloadSocketBtmRelease({
30-
* tool: 'node-smol',
31-
* bin: 'node' // Presence of 'bin' = binary download
32-
* })
33-
*
34-
* // Download binject binary (like: cargo install binject → binject)
35-
* const binjectPath = await downloadSocketBtmRelease({
36-
* tool: 'binject' // No 'bin' or 'asset' = binary with bin=tool
37-
* })
38-
*
39-
* // Cross-platform binary (like: cargo install --target)
40-
* const nodePathLinux = await downloadSocketBtmRelease({
41-
* tool: 'node-smol',
42-
* bin: 'node',
43-
* targetPlatform: 'linux',
44-
* targetArch: 'x64',
45-
* libc: 'musl'
46-
* })
47-
*
48-
* // Download WASM asset (like: gh release download --pattern)
49-
* const yogaPath = await downloadSocketBtmRelease({
50-
* tool: 'yoga-layout',
51-
* asset: 'yoga-sync.mjs' // Presence of 'asset' = asset download
52-
* })
53-
* ```
5422
*/
5523

56-
import os from 'node:os'
24+
import { existsSync } from 'fs'
25+
import os from 'os'
5726

5827
import {
5928
downloadGitHubRelease,
@@ -128,7 +97,7 @@ export interface SocketBtmBinaryConfig {
12897
targetArch?: Arch
12998
/**
13099
* Linux libc variant (musl or glibc).
131-
* Defaults to musl for Linux for broader compatibility.
100+
* Auto-detected from the Node.js binary if not specified.
132101
* Ignored for non-Linux platforms.
133102
*/
134103
libc?: Libc
@@ -241,6 +210,46 @@ const ARCH_MAP: Record<string, string> = {
241210
x64: 'x64',
242211
}
243212

213+
/**
214+
* Detect the libc variant (musl or glibc) on Linux systems.
215+
* Returns undefined for non-Linux platforms.
216+
*
217+
* Detection method: Check for musl-specific files in the filesystem.
218+
* This is more reliable than checking the Node.js binary, especially for
219+
* statically-linked binaries that may contain references to both libc variants.
220+
*
221+
* @returns 'musl', 'glibc', or undefined (for non-Linux)
222+
*/
223+
function detectLibc(): Libc | undefined {
224+
const platform = os.platform()
225+
if (platform !== 'linux') {
226+
return undefined
227+
}
228+
229+
try {
230+
// Check for musl-specific dynamic linker
231+
// These files only exist on musl systems
232+
const muslPaths = [
233+
'/lib/ld-musl-x86_64.so.1',
234+
'/lib/ld-musl-aarch64.so.1',
235+
'/usr/lib/ld-musl-x86_64.so.1',
236+
'/usr/lib/ld-musl-aarch64.so.1',
237+
]
238+
239+
for (const path of muslPaths) {
240+
if (existsSync(path)) {
241+
return 'musl'
242+
}
243+
}
244+
245+
// If no musl files found, assume glibc
246+
return 'glibc'
247+
} catch {
248+
// If detection fails, default to glibc (most common)
249+
return 'glibc'
250+
}
251+
}
252+
244253
/**
245254
* Get asset name for a socket-btm binary.
246255
*
@@ -259,7 +268,7 @@ function getBinaryAssetName(
259268
binaryBaseName: string,
260269
platform: Platform,
261270
arch: Arch,
262-
libc?: Libc,
271+
libc?: Libc | undefined,
263272
): string {
264273
const mappedArch = ARCH_MAP[arch]
265274
if (!mappedArch) {
@@ -431,12 +440,12 @@ export async function downloadSocketBtmRelease(
431440
// Default bin to tool if not provided (like brew/cargo)
432441
const baseName = bin || tool
433442

434-
// Resolve platform and arch
443+
// Resolve platform and arch based on host if not specified
435444
const platform = (targetPlatform || os.platform()) as Platform
436445
const arch = (targetArch || os.arch()) as Arch
437446

438-
// Default to musl for Linux for broader compatibility (works on both musl and glibc systems)
439-
const libcType = libc || (platform === 'linux' ? 'musl' : undefined)
447+
// Auto-detect libc variant on Linux if not specified
448+
const libcType = libc || detectLibc()
440449

441450
// Build asset name and platform-arch identifier
442451
const assetName = getBinaryAssetName(baseName, platform, arch, libcType)

0 commit comments

Comments
 (0)