|
- 'use strict';
-
- const childProcess = require('child_process');
- const { isLinux, getReport } = require('./process');
-
- const command = 'getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true';
- let commandOut = '';
-
- const safeCommand = () => {
- if (!commandOut) {
- return new Promise((resolve) => {
- childProcess.exec(command, (err, out) => {
- commandOut = err ? ' ' : out;
- resolve(commandOut);
- });
- });
- }
- return commandOut;
- };
-
- const safeCommandSync = () => {
- if (!commandOut) {
- try {
- commandOut = childProcess.execSync(command, { encoding: 'utf8' });
- } catch (_err) {
- commandOut = ' ';
- }
- }
- return commandOut;
- };
-
- /**
- * A String constant containing the value `glibc`.
- * @type {string}
- * @public
- */
- const GLIBC = 'glibc';
-
- /**
- * A String constant containing the value `musl`.
- * @type {string}
- * @public
- */
- const MUSL = 'musl';
-
- const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-');
-
- const familyFromReport = () => {
- const report = getReport();
- if (report.header && report.header.glibcVersionRuntime) {
- return GLIBC;
- }
- if (Array.isArray(report.sharedObjects)) {
- if (report.sharedObjects.some(isFileMusl)) {
- return MUSL;
- }
- }
- return null;
- };
-
- const familyFromCommand = (out) => {
- const [getconf, ldd1] = out.split(/[\r\n]+/);
- if (getconf && getconf.includes(GLIBC)) {
- return GLIBC;
- }
- if (ldd1 && ldd1.includes(MUSL)) {
- return MUSL;
- }
- return null;
- };
-
- /**
- * Resolves with the libc family when it can be determined, `null` otherwise.
- * @returns {Promise<?string>}
- */
- const family = async () => {
- let family = null;
- if (isLinux()) {
- family = familyFromReport();
- if (!family) {
- const out = await safeCommand();
- family = familyFromCommand(out);
- }
- }
- return family;
- };
-
- /**
- * Returns the libc family when it can be determined, `null` otherwise.
- * @returns {?string}
- */
- const familySync = () => {
- let family = null;
- if (isLinux()) {
- family = familyFromReport();
- if (!family) {
- const out = safeCommandSync();
- family = familyFromCommand(out);
- }
- }
- return family;
- };
-
- /**
- * Resolves `true` only when the platform is Linux and the libc family is not `glibc`.
- * @returns {Promise<boolean>}
- */
- const isNonGlibcLinux = async () => isLinux() && await family() !== GLIBC;
-
- /**
- * Returns `true` only when the platform is Linux and the libc family is not `glibc`.
- * @returns {boolean}
- */
- const isNonGlibcLinuxSync = () => isLinux() && familySync() !== GLIBC;
-
- const versionFromReport = () => {
- const report = getReport();
- if (report.header && report.header.glibcVersionRuntime) {
- return report.header.glibcVersionRuntime;
- }
- return null;
- };
-
- const versionSuffix = (s) => s.trim().split(/\s+/)[1];
-
- const versionFromCommand = (out) => {
- const [getconf, ldd1, ldd2] = out.split(/[\r\n]+/);
- if (getconf && getconf.includes(GLIBC)) {
- return versionSuffix(getconf);
- }
- if (ldd1 && ldd2 && ldd1.includes(MUSL)) {
- return versionSuffix(ldd2);
- }
- return null;
- };
-
- /**
- * Resolves with the libc version when it can be determined, `null` otherwise.
- * @returns {Promise<?string>}
- */
- const version = async () => {
- let version = null;
- if (isLinux()) {
- version = versionFromReport();
- if (!version) {
- const out = await safeCommand();
- version = versionFromCommand(out);
- }
- }
- return version;
- };
-
- /**
- * Returns the libc version when it can be determined, `null` otherwise.
- * @returns {?string}
- */
- const versionSync = () => {
- let version = null;
- if (isLinux()) {
- version = versionFromReport();
- if (!version) {
- const out = safeCommandSync();
- version = versionFromCommand(out);
- }
- }
- return version;
- };
-
- module.exports = {
- GLIBC,
- MUSL,
- family,
- familySync,
- isNonGlibcLinux,
- isNonGlibcLinuxSync,
- version,
- versionSync
- };
|