source: node_modules/detect-libc/lib/detect-libc.js@ 81bc7da

finki-main main
Last change on this file since 81bc7da was 81bc7da, checked in by Klimentina Efremova <klimentina08642@…>, 3 months ago

Initial commit

  • Property mode set to 100644
File size: 7.3 KB
RevLine 
[81bc7da]1// Copyright 2017 Lovell Fuller and others.
2// SPDX-License-Identifier: Apache-2.0
3
4'use strict';
5
6const childProcess = require('child_process');
7const { isLinux, getReport } = require('./process');
8const { LDD_PATH, SELF_PATH, readFile, readFileSync } = require('./filesystem');
9const { interpreterPath } = require('./elf');
10
11let cachedFamilyInterpreter;
12let cachedFamilyFilesystem;
13let cachedVersionFilesystem;
14
15const command = 'getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true';
16let commandOut = '';
17
18const safeCommand = () => {
19 if (!commandOut) {
20 return new Promise((resolve) => {
21 childProcess.exec(command, (err, out) => {
22 commandOut = err ? ' ' : out;
23 resolve(commandOut);
24 });
25 });
26 }
27 return commandOut;
28};
29
30const safeCommandSync = () => {
31 if (!commandOut) {
32 try {
33 commandOut = childProcess.execSync(command, { encoding: 'utf8' });
34 } catch (_err) {
35 commandOut = ' ';
36 }
37 }
38 return commandOut;
39};
40
41/**
42 * A String constant containing the value `glibc`.
43 * @type {string}
44 * @public
45 */
46const GLIBC = 'glibc';
47
48/**
49 * A Regexp constant to get the GLIBC Version.
50 * @type {string}
51 */
52const RE_GLIBC_VERSION = /LIBC[a-z0-9 \-).]*?(\d+\.\d+)/i;
53
54/**
55 * A String constant containing the value `musl`.
56 * @type {string}
57 * @public
58 */
59const MUSL = 'musl';
60
61const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-');
62
63const familyFromReport = () => {
64 const report = getReport();
65 if (report.header && report.header.glibcVersionRuntime) {
66 return GLIBC;
67 }
68 if (Array.isArray(report.sharedObjects)) {
69 if (report.sharedObjects.some(isFileMusl)) {
70 return MUSL;
71 }
72 }
73 return null;
74};
75
76const familyFromCommand = (out) => {
77 const [getconf, ldd1] = out.split(/[\r\n]+/);
78 if (getconf && getconf.includes(GLIBC)) {
79 return GLIBC;
80 }
81 if (ldd1 && ldd1.includes(MUSL)) {
82 return MUSL;
83 }
84 return null;
85};
86
87const familyFromInterpreterPath = (path) => {
88 if (path) {
89 if (path.includes('/ld-musl-')) {
90 return MUSL;
91 } else if (path.includes('/ld-linux-')) {
92 return GLIBC;
93 }
94 }
95 return null;
96};
97
98const getFamilyFromLddContent = (content) => {
99 content = content.toString();
100 if (content.includes('musl')) {
101 return MUSL;
102 }
103 if (content.includes('GNU C Library')) {
104 return GLIBC;
105 }
106 return null;
107};
108
109const familyFromFilesystem = async () => {
110 if (cachedFamilyFilesystem !== undefined) {
111 return cachedFamilyFilesystem;
112 }
113 cachedFamilyFilesystem = null;
114 try {
115 const lddContent = await readFile(LDD_PATH);
116 cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
117 } catch (e) {}
118 return cachedFamilyFilesystem;
119};
120
121const familyFromFilesystemSync = () => {
122 if (cachedFamilyFilesystem !== undefined) {
123 return cachedFamilyFilesystem;
124 }
125 cachedFamilyFilesystem = null;
126 try {
127 const lddContent = readFileSync(LDD_PATH);
128 cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
129 } catch (e) {}
130 return cachedFamilyFilesystem;
131};
132
133const familyFromInterpreter = async () => {
134 if (cachedFamilyInterpreter !== undefined) {
135 return cachedFamilyInterpreter;
136 }
137 cachedFamilyInterpreter = null;
138 try {
139 const selfContent = await readFile(SELF_PATH);
140 const path = interpreterPath(selfContent);
141 cachedFamilyInterpreter = familyFromInterpreterPath(path);
142 } catch (e) {}
143 return cachedFamilyInterpreter;
144};
145
146const familyFromInterpreterSync = () => {
147 if (cachedFamilyInterpreter !== undefined) {
148 return cachedFamilyInterpreter;
149 }
150 cachedFamilyInterpreter = null;
151 try {
152 const selfContent = readFileSync(SELF_PATH);
153 const path = interpreterPath(selfContent);
154 cachedFamilyInterpreter = familyFromInterpreterPath(path);
155 } catch (e) {}
156 return cachedFamilyInterpreter;
157};
158
159/**
160 * Resolves with the libc family when it can be determined, `null` otherwise.
161 * @returns {Promise<?string>}
162 */
163const family = async () => {
164 let family = null;
165 if (isLinux()) {
166 family = await familyFromInterpreter();
167 if (!family) {
168 family = await familyFromFilesystem();
169 if (!family) {
170 family = familyFromReport();
171 }
172 if (!family) {
173 const out = await safeCommand();
174 family = familyFromCommand(out);
175 }
176 }
177 }
178 return family;
179};
180
181/**
182 * Returns the libc family when it can be determined, `null` otherwise.
183 * @returns {?string}
184 */
185const familySync = () => {
186 let family = null;
187 if (isLinux()) {
188 family = familyFromInterpreterSync();
189 if (!family) {
190 family = familyFromFilesystemSync();
191 if (!family) {
192 family = familyFromReport();
193 }
194 if (!family) {
195 const out = safeCommandSync();
196 family = familyFromCommand(out);
197 }
198 }
199 }
200 return family;
201};
202
203/**
204 * Resolves `true` only when the platform is Linux and the libc family is not `glibc`.
205 * @returns {Promise<boolean>}
206 */
207const isNonGlibcLinux = async () => isLinux() && await family() !== GLIBC;
208
209/**
210 * Returns `true` only when the platform is Linux and the libc family is not `glibc`.
211 * @returns {boolean}
212 */
213const isNonGlibcLinuxSync = () => isLinux() && familySync() !== GLIBC;
214
215const versionFromFilesystem = async () => {
216 if (cachedVersionFilesystem !== undefined) {
217 return cachedVersionFilesystem;
218 }
219 cachedVersionFilesystem = null;
220 try {
221 const lddContent = await readFile(LDD_PATH);
222 const versionMatch = lddContent.match(RE_GLIBC_VERSION);
223 if (versionMatch) {
224 cachedVersionFilesystem = versionMatch[1];
225 }
226 } catch (e) {}
227 return cachedVersionFilesystem;
228};
229
230const versionFromFilesystemSync = () => {
231 if (cachedVersionFilesystem !== undefined) {
232 return cachedVersionFilesystem;
233 }
234 cachedVersionFilesystem = null;
235 try {
236 const lddContent = readFileSync(LDD_PATH);
237 const versionMatch = lddContent.match(RE_GLIBC_VERSION);
238 if (versionMatch) {
239 cachedVersionFilesystem = versionMatch[1];
240 }
241 } catch (e) {}
242 return cachedVersionFilesystem;
243};
244
245const versionFromReport = () => {
246 const report = getReport();
247 if (report.header && report.header.glibcVersionRuntime) {
248 return report.header.glibcVersionRuntime;
249 }
250 return null;
251};
252
253const versionSuffix = (s) => s.trim().split(/\s+/)[1];
254
255const versionFromCommand = (out) => {
256 const [getconf, ldd1, ldd2] = out.split(/[\r\n]+/);
257 if (getconf && getconf.includes(GLIBC)) {
258 return versionSuffix(getconf);
259 }
260 if (ldd1 && ldd2 && ldd1.includes(MUSL)) {
261 return versionSuffix(ldd2);
262 }
263 return null;
264};
265
266/**
267 * Resolves with the libc version when it can be determined, `null` otherwise.
268 * @returns {Promise<?string>}
269 */
270const version = async () => {
271 let version = null;
272 if (isLinux()) {
273 version = await versionFromFilesystem();
274 if (!version) {
275 version = versionFromReport();
276 }
277 if (!version) {
278 const out = await safeCommand();
279 version = versionFromCommand(out);
280 }
281 }
282 return version;
283};
284
285/**
286 * Returns the libc version when it can be determined, `null` otherwise.
287 * @returns {?string}
288 */
289const versionSync = () => {
290 let version = null;
291 if (isLinux()) {
292 version = versionFromFilesystemSync();
293 if (!version) {
294 version = versionFromReport();
295 }
296 if (!version) {
297 const out = safeCommandSync();
298 version = versionFromCommand(out);
299 }
300 }
301 return version;
302};
303
304module.exports = {
305 GLIBC,
306 MUSL,
307 family,
308 familySync,
309 isNonGlibcLinux,
310 isNonGlibcLinuxSync,
311 version,
312 versionSync
313};
Note: See TracBrowser for help on using the repository browser.