You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							179 lines
						
					
					
						
							3.8 KiB
						
					
					
				
			
		
		
	
	
							179 lines
						
					
					
						
							3.8 KiB
						
					
					
				'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
 | 
						|
};
 |