import { spawnSync , SpawnSyncOptionsWithStringEncoding } from "child_process" ; import { readdirSync } from "fs" ; import { platform } from "os" ; export function detectLibc ( ) { const GLIBC = "glibc" ; const MUSL = "musl" ; const spawnOptions = { encoding : "utf8" , env : process . env } ; function contains ( needle ) { return ( haystack ) => { return haystack . indexOf ( needle ) !== - 1 ; } ; } function versionFromMuslLdd ( out ) { return out . split ( /[\r\n]+/ ) [ 1 ] . trim ( ) . split ( /\s/ ) [ 1 ] ; } function safeReaddirSync ( path ) { try { return readdirSync ( path ) ; } catch ( e ) { } return [ ] ; } let family = "" ; let version = "" ; let method = "" ; if ( platform ( ) === "linux" ) { const glibc = spawnSync ( "getconf" , [ "GNU_LIBC_VERSION" ] , spawnOptions ) ; if ( glibc . status === 0 ) { family = GLIBC ; version = glibc . stdout . trim ( ) . split ( " " ) [ 1 ] ; method = "getconf" ; } else { const ldd = spawnSync ( "ldd" , [ "--version" ] , spawnOptions ) ; if ( ldd . status === 0 && ldd . stdout . indexOf ( MUSL ) !== - 1 ) { family = MUSL ; version = versionFromMuslLdd ( ldd . stdout ) ; method = "ldd" ; } else if ( ldd . status === 1 && ldd . stderr . indexOf ( MUSL ) !== - 1 ) { family = MUSL ; version = versionFromMuslLdd ( ldd . stderr ) ; method = "ldd" ; } else { const lib = safeReaddirSync ( "/lib" ) ; if ( lib . some ( contains ( "-linux-gnu" ) ) ) { family = GLIBC ; method = "filesystem" ; } else if ( lib . some ( contains ( "libc.musl-" ) ) ) { family = MUSL ; method = "filesystem" ; } else if ( lib . some ( contains ( "ld-musl-" ) ) ) { family = MUSL ; method = "filesystem" ; } else { const usrSbin = safeReaddirSync ( "/usr/sbin" ) ; if ( usrSbin . some ( contains ( "glibc" ) ) ) { family = GLIBC ; method = "filesystem" ; } } } } } const isNonGlibcLinux = family !== "" && family !== GLIBC ; return { GLIBC : GLIBC , MUSL : MUSL , family : family , version : version , method : method , isNonGlibcLinux : isNonGlibcLinux } ; }