Skip to content

Commit

Permalink
perf(detect-libc): faster musl check by looking for ldd file
Browse files Browse the repository at this point in the history
  • Loading branch information
H4ad committed Jun 17, 2023
1 parent 43e5a43 commit 1153b46
Show file tree
Hide file tree
Showing 5 changed files with 534 additions and 15 deletions.
34 changes: 34 additions & 0 deletions lib/cache.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @type {Record<string, string | undefined | null>}
*/
const cacheObject = {};

module.exports = {
cacheFn: (key, fn, async = false) => {
return () => {
const cachedValue = cacheObject[key];

if (cachedValue !== undefined) {
if (async) {
return Promise.resolve(cachedValue);
}

return cachedValue;
}

const result = fn();

if (async) {
return result.then(value => {
cacheObject[key] = value;

return value;
});
}

cacheObject[key] = result;

return result;
};
}
};
95 changes: 91 additions & 4 deletions lib/detect-libc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

const childProcess = require('child_process');
const { isLinux, getReport } = require('./process');
const { LDD_PATH, readFile, readFileSync } = require('./filesystem');

let cachedFamilyFilesystem;
let cachedVersionFilesystem;

const command = 'getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true';
let commandOut = '';
Expand Down Expand Up @@ -39,6 +43,13 @@ const safeCommandSync = () => {
*/
const GLIBC = 'glibc';

/**
* A Regexp constant to get the GLIBC Version.
* @type {string}
* @public
*/
const RE_GLIBC_VERSION = /GLIBC\s(\d+\.\d+)/;

/**
* A String constant containing the value `musl`.
* @type {string}
Expand Down Expand Up @@ -72,14 +83,49 @@ const familyFromCommand = (out) => {
return null;
};

const familyFromFilesystem = async () => {
if (cachedFamilyFilesystem !== undefined) {
return cachedFamilyFilesystem;
}
cachedFamilyFilesystem = null;
try {
const lddContent = await readFile(LDD_PATH);
if (lddContent.includes('musl')) {
cachedFamilyFilesystem = MUSL;
} else if (lddContent.includes('GLIBC')) {
cachedFamilyFilesystem = GLIBC;
}
} catch (e) {}
return cachedFamilyFilesystem;
};

const familyFromFilesystemSync = () => {
if (cachedFamilyFilesystem !== undefined) {
return cachedFamilyFilesystem;
}
cachedFamilyFilesystem = null;
try {
const lddContent = readFileSync(LDD_PATH);
if (lddContent.includes('musl')) {
cachedFamilyFilesystem = MUSL;
} else if (lddContent.includes('GLIBC')) {
cachedFamilyFilesystem = GLIBC;
}
} catch (e) {}
return cachedFamilyFilesystem;
};

/**
* 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();
family = await familyFromFilesystem();
if (!family) {
family = familyFromReport();
}
if (!family) {
const out = await safeCommand();
family = familyFromCommand(out);
Expand All @@ -95,7 +141,10 @@ const family = async () => {
const familySync = () => {
let family = null;
if (isLinux()) {
family = familyFromReport();
family = familyFromFilesystemSync();
if (!family) {
family = familyFromReport();
}
if (!family) {
const out = safeCommandSync();
family = familyFromCommand(out);
Expand All @@ -116,6 +165,38 @@ const isNonGlibcLinux = async () => isLinux() && await family() !== GLIBC;
*/
const isNonGlibcLinuxSync = () => isLinux() && familySync() !== GLIBC;

const versionFromFilesystem = async () => {
if (cachedVersionFilesystem !== undefined) {
return cachedVersionFilesystem;
}
cachedVersionFilesystem = null;
try {
const lddContent = await readFile(LDD_PATH);
const versionMatch = lddContent.match(RE_GLIBC_VERSION);

if (versionMatch) {
cachedVersionFilesystem = versionMatch[1];
}
} catch (e) {}
return cachedVersionFilesystem;
};

const versionFromFilesystemSync = () => {
if (cachedVersionFilesystem !== undefined) {
return cachedVersionFilesystem;
}
cachedVersionFilesystem = null;
try {
const lddContent = readFileSync(LDD_PATH);
const versionMatch = lddContent.match(RE_GLIBC_VERSION);

if (versionMatch) {
cachedVersionFilesystem = versionMatch[1];
}
} catch (e) {}
return cachedVersionFilesystem;
};

const versionFromReport = () => {
const report = getReport();
if (report.header && report.header.glibcVersionRuntime) {
Expand Down Expand Up @@ -144,7 +225,10 @@ const versionFromCommand = (out) => {
const version = async () => {
let version = null;
if (isLinux()) {
version = versionFromReport();
version = await versionFromFilesystem();
if (!version) {
version = versionFromReport();
}
if (!version) {
const out = await safeCommand();
version = versionFromCommand(out);
Expand All @@ -160,7 +244,10 @@ const version = async () => {
const versionSync = () => {
let version = null;
if (isLinux()) {
version = versionFromReport();
version = versionFromFilesystemSync();
if (!version) {
version = versionFromReport();
}
if (!version) {
const out = safeCommandSync();
version = versionFromCommand(out);
Expand Down
36 changes: 36 additions & 0 deletions lib/filesystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const fs = require('fs');

/**
* The path where we can find the ldd
*/
const LDD_PATH = '/usr/bin/ldd';

/**
* Read the content of a file synchronous
*
* @param {string} path
* @returns {string}
*/
const readFileSync = path => fs.readFileSync(path, 'utf-8');

/**
* Read the content of a file
*
* @param {string} path
* @returns {Promise<string>}
*/
const readFile = path => new Promise((resolve, reject) => {
fs.readFile(path, 'utf-8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});

module.exports = {
LDD_PATH,
readFileSync,
readFile
};
1 change: 1 addition & 0 deletions test/fixtexture-file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Loading

0 comments on commit 1153b46

Please sign in to comment.