Skip to content

Commit 1a66ea7

Browse files
committed
perf(detect-libc): faster musl check by looking for ldd file
1 parent 43e5a43 commit 1a66ea7

File tree

4 files changed

+513
-15
lines changed

4 files changed

+513
-15
lines changed

lib/detect-libc.js

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
const childProcess = require('child_process');
77
const { isLinux, getReport } = require('./process');
8+
const { LDD_PATH, readFile, readFileSync } = require('./filesystem');
9+
10+
let cachedFamilyFilesystem;
11+
let cachedVersionFilesystem;
812

913
const command = 'getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true';
1014
let commandOut = '';
@@ -39,13 +43,31 @@ const safeCommandSync = () => {
3943
*/
4044
const GLIBC = 'glibc';
4145

46+
/**
47+
* A Regexp constant to get the GLIBC Version.
48+
* @type {string}
49+
*/
50+
const RE_GLIBC_VERSION = /GLIBC\s(\d+\.\d+)/;
51+
4252
/**
4353
* A String constant containing the value `musl`.
4454
* @type {string}
4555
* @public
4656
*/
4757
const MUSL = 'musl';
4858

59+
/**
60+
* This string is used to find if the {@link LDD_PATH} is GLIBC
61+
* @type {string}
62+
*/
63+
const GLIBC_ON_LDD = GLIBC.toUpperCase();
64+
65+
/**
66+
* This string is used to find if the {@link LDD_PATH} is musl
67+
* @type {string}
68+
*/
69+
const MUSL_ON_LDD = MUSL.toLowerCase();
70+
4971
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-');
5072

5173
const familyFromReport = () => {
@@ -72,14 +94,51 @@ const familyFromCommand = (out) => {
7294
return null;
7395
};
7496

97+
const getFamilyFromLddContent = (content) => {
98+
if (content.includes(MUSL_ON_LDD)) {
99+
return MUSL;
100+
}
101+
if (content.includes(GLIBC_ON_LDD)) {
102+
return GLIBC;
103+
}
104+
return null;
105+
};
106+
107+
const familyFromFilesystem = async () => {
108+
if (cachedFamilyFilesystem !== undefined) {
109+
return cachedFamilyFilesystem;
110+
}
111+
cachedFamilyFilesystem = null;
112+
try {
113+
const lddContent = await readFile(LDD_PATH);
114+
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
115+
} catch (e) {}
116+
return cachedFamilyFilesystem;
117+
};
118+
119+
const familyFromFilesystemSync = () => {
120+
if (cachedFamilyFilesystem !== undefined) {
121+
return cachedFamilyFilesystem;
122+
}
123+
cachedFamilyFilesystem = null;
124+
try {
125+
const lddContent = readFileSync(LDD_PATH);
126+
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
127+
} catch (e) {}
128+
return cachedFamilyFilesystem;
129+
};
130+
75131
/**
76132
* Resolves with the libc family when it can be determined, `null` otherwise.
77133
* @returns {Promise<?string>}
78134
*/
79135
const family = async () => {
80136
let family = null;
81137
if (isLinux()) {
82-
family = familyFromReport();
138+
family = await familyFromFilesystem();
139+
if (!family) {
140+
family = familyFromReport();
141+
}
83142
if (!family) {
84143
const out = await safeCommand();
85144
family = familyFromCommand(out);
@@ -95,7 +154,10 @@ const family = async () => {
95154
const familySync = () => {
96155
let family = null;
97156
if (isLinux()) {
98-
family = familyFromReport();
157+
family = familyFromFilesystemSync();
158+
if (!family) {
159+
family = familyFromReport();
160+
}
99161
if (!family) {
100162
const out = safeCommandSync();
101163
family = familyFromCommand(out);
@@ -116,6 +178,38 @@ const isNonGlibcLinux = async () => isLinux() && await family() !== GLIBC;
116178
*/
117179
const isNonGlibcLinuxSync = () => isLinux() && familySync() !== GLIBC;
118180

181+
const versionFromFilesystem = async () => {
182+
if (cachedVersionFilesystem !== undefined) {
183+
return cachedVersionFilesystem;
184+
}
185+
cachedVersionFilesystem = null;
186+
try {
187+
const lddContent = await readFile(LDD_PATH);
188+
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
189+
190+
if (versionMatch) {
191+
cachedVersionFilesystem = versionMatch[1];
192+
}
193+
} catch (e) {}
194+
return cachedVersionFilesystem;
195+
};
196+
197+
const versionFromFilesystemSync = () => {
198+
if (cachedVersionFilesystem !== undefined) {
199+
return cachedVersionFilesystem;
200+
}
201+
cachedVersionFilesystem = null;
202+
try {
203+
const lddContent = readFileSync(LDD_PATH);
204+
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
205+
206+
if (versionMatch) {
207+
cachedVersionFilesystem = versionMatch[1];
208+
}
209+
} catch (e) {}
210+
return cachedVersionFilesystem;
211+
};
212+
119213
const versionFromReport = () => {
120214
const report = getReport();
121215
if (report.header && report.header.glibcVersionRuntime) {
@@ -144,7 +238,10 @@ const versionFromCommand = (out) => {
144238
const version = async () => {
145239
let version = null;
146240
if (isLinux()) {
147-
version = versionFromReport();
241+
version = await versionFromFilesystem();
242+
if (!version) {
243+
version = versionFromReport();
244+
}
148245
if (!version) {
149246
const out = await safeCommand();
150247
version = versionFromCommand(out);
@@ -160,7 +257,10 @@ const version = async () => {
160257
const versionSync = () => {
161258
let version = null;
162259
if (isLinux()) {
163-
version = versionFromReport();
260+
version = versionFromFilesystemSync();
261+
if (!version) {
262+
version = versionFromReport();
263+
}
164264
if (!version) {
165265
const out = safeCommandSync();
166266
version = versionFromCommand(out);

lib/filesystem.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
const fs = require('fs');
2+
3+
/**
4+
* The path where we can find the ldd
5+
*/
6+
const LDD_PATH = '/usr/bin/ldd';
7+
8+
/**
9+
* Read the content of a file synchronous
10+
*
11+
* @param {string} path
12+
* @returns {string}
13+
*/
14+
const readFileSync = path => fs.readFileSync(path, 'utf-8');
15+
16+
/**
17+
* Read the content of a file
18+
*
19+
* @param {string} path
20+
* @returns {Promise<string>}
21+
*/
22+
const readFile = path => new Promise((resolve, reject) => {
23+
fs.readFile(path, 'utf-8', (err, data) => {
24+
if (err) {
25+
reject(err);
26+
} else {
27+
resolve(data);
28+
}
29+
});
30+
});
31+
32+
module.exports = {
33+
LDD_PATH,
34+
readFileSync,
35+
readFile
36+
};

test/fixtexture-file.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1

0 commit comments

Comments
 (0)