/** * Extract embedded native helpers next to the agent storage dir * (or PEARDATA_HELPER_DIR) so they can be exec'd from Bare/Node. */ import fs from 'fs' import path from 'path' import os from 'os' import { EMBEDDED_HELPERS } from './embedded-helpers.js' function helperDir() { if (process.env.PEARDATA_HELPER_DIR) return process.env.PEARDATA_HELPER_DIR if (process.env.PEARDATA_HOME) return path.join(process.env.PEARDATA_HOME, 'helpers') if (process.env.PEARDATA_DATA_DIR) return path.join(process.env.PEARDATA_DATA_DIR, 'helpers') return path.join(os.tmpdir(), 'peardata-helpers') } function hostKey() { return `${process.platform}-${process.arch}` } /** * @param {string} name e.g. peardata-ebpf * @returns {string|null} absolute path to executable */ export function extractHelper(name) { const keyed = `${name}-${hostKey()}` const b64 = EMBEDDED_HELPERS[keyed] || EMBEDDED_HELPERS[name] if (!b64) { // Fall back to sibling of process.execPath / PATH const siblings = [ path.join(path.dirname(process.execPath || ''), name), path.join(process.cwd(), 'native', 'prebuilds', `${name}-${hostKey()}`), path.join(process.cwd(), 'native', 'prebuilds', name), `/usr/local/lib/peardata/${name}`, ] for (const p of siblings) { try { if (fs.existsSync(p)) { fs.accessSync(p, fs.constants.X_OK) return p } } catch { // continue } } return null } const dir = helperDir() fs.mkdirSync(dir, { recursive: true }) const dest = path.join(dir, name) const buf = Buffer.from(b64, 'base64') let needWrite = true try { const st = fs.statSync(dest) if (st.size === buf.length) needWrite = false } catch { needWrite = true } if (needWrite) { fs.writeFileSync(dest, buf, { mode: 0o755 }) try { fs.chmodSync(dest, 0o755) } catch { // ignore } } return dest } export function hasEmbeddedHelper(name) { const keyed = `${name}-${hostKey()}` return Boolean(EMBEDDED_HELPERS[keyed] || EMBEDDED_HELPERS[name]) }