@tencent-ai/agent-sdk 0.3.206 → 0.3.209
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/CHANGELOG.md +53 -0
- package/cli/builtin/workflows/deep-research.workflow.js +77 -20
- package/cli/dist/codebuddy-headless.js +293 -245
- package/cli/dist/web-ui/assets/index-CH6e4vvI.css +32 -0
- package/cli/dist/web-ui/assets/index-GcU4pZms.js +1102 -0
- package/cli/dist/web-ui/index.html +2 -2
- package/cli/dist/web-ui/sw.js +1 -1
- package/cli/package.json +4 -4
- package/cli/product.cloudhosted.json +2 -2
- package/cli/product.internal.json +2 -2
- package/cli/product.ioa.json +2 -2
- package/cli/product.json +3 -3
- package/cli/product.selfhosted.json +2 -2
- package/cli/vendor/native-builds.json +18 -0
- package/cli/vendor/shim/broker-ipc-client.cjs +158 -0
- package/cli/vendor/shim/brokered-bin/codebuddy-toybox-dispatch +381 -0
- package/cli/vendor/shim/brokered-sandbox-bash-env.sh +10 -0
- package/cli/vendor/shim/genie-safe-delete.cjs +4 -781
- package/cli/vendor/shim/native/binding.gyp +13 -0
- package/cli/vendor/shim/native/brokered_sandbox_native.c +293 -0
- package/cli/vendor/shim/native/darwin-arm64/brokered-sandbox-native.node +0 -0
- package/cli/vendor/shim/native/darwin-x64/brokered-sandbox-native.node +0 -0
- package/cli/vendor/shim/node-brokered-fs-shim.cjs +932 -0
- package/cli/vendor/shim/node-language-shim.cjs +35 -0
- package/cli/vendor/shim/node-safe-delete-shim.cjs +810 -0
- package/cli/vendor/shim/safe-bin/safe-delete-bash-env.sh +1 -1
- package/cli/vendor/shim/safe-bin/safe-delete-common.sh +95 -34
- package/cli/vendor/shim/safe-delete-broker-delete.cjs +166 -0
- package/cli/vendor/shim/shell-runtime-bash-env.sh +8 -0
- package/cli/vendor/shim/sitecustomize.py +551 -22
- package/cli/vendor/toybox-macos/LICENSE +12 -0
- package/cli/vendor/toybox-macos/toybox +0 -0
- package/cli/vendor/toybox-macos/toybox.sb +19 -0
- package/cli/vendor/zsh-macos/LICENSE +37 -0
- package/cli/vendor/zsh-macos/bin/zsh +0 -0
- package/package.json +1 -1
- package/cli/dist/web-ui/assets/index-BZjhFKbY.js +0 -1051
- package/cli/dist/web-ui/assets/index-C5EhSt3C.css +0 -32
|
@@ -0,0 +1,932 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeBuddy Node brokered fs shim
|
|
3
|
+
*
|
|
4
|
+
* Loaded by node-language-shim.cjs. Installs brokered file-token and host-op hooks.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const url = require('url');
|
|
12
|
+
const brokerIpc = require('./broker-ipc-client.cjs');
|
|
13
|
+
|
|
14
|
+
const SESSION_ID = process.env.CODEBUDDY_SESSION_ID
|
|
15
|
+
|| process.env.CLAUDE_SESSION_ID;
|
|
16
|
+
|
|
17
|
+
if (!SESSION_ID) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const BROKERED_FS_HOOK_ENABLED = process.env.CODEBUDDY_BROKERED_FS_HOOK_ENABLED === '1'
|
|
22
|
+
|| process.env.CODEBUDDY_SAFE_DELETE_SANDBOX === '1';
|
|
23
|
+
|
|
24
|
+
if (!BROKERED_FS_HOOK_ENABLED) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (global.__CODEBUDDY_NODE_BROKERED_FS_SHIM_LOADED__) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
global.__CODEBUDDY_NODE_BROKERED_FS_SHIM_LOADED__ = true;
|
|
32
|
+
|
|
33
|
+
const PLATFORM = process.platform; // 'darwin' | 'win32' | 'linux' | ...
|
|
34
|
+
const BROKER_HOST_OP_DEFAULT_TIMEOUT_MS = 5_000;
|
|
35
|
+
const SHIM_DIR = __dirname;
|
|
36
|
+
const BROKER_FALLBACK_DEBUG = process.env.CODEBUDDY_SANDBOX_BROKER_DEBUG === '1';
|
|
37
|
+
let brokerRequestSeq = 0;
|
|
38
|
+
let brokerNativeAddonLoaded = false;
|
|
39
|
+
let brokerNativeAddon;
|
|
40
|
+
|
|
41
|
+
// broker 连接失败会静默退化为原生 fs 调用(fail-open)。默认不打印,避免污染被
|
|
42
|
+
// hook 的任意子进程的 stdout/stderr;排查问题时可设 CODEBUDDY_SANDBOX_BROKER_DEBUG=1 开启。
|
|
43
|
+
function logBrokerFallback(kind, operation, filePath, error) {
|
|
44
|
+
if (!BROKER_FALLBACK_DEBUG) { return; }
|
|
45
|
+
const reason = error && error.message ? error.message : String(error);
|
|
46
|
+
process.stderr.write(`[CodeBuddy][brokered-fs] fallback to native fs: kind=${kind} operation=${operation} path=${filePath == null ? '' : filePath} reason=${reason}\n`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 保存原始引用(必须在所有 patch 之前)
|
|
50
|
+
const origMkdirSync = fs.mkdirSync.bind(fs);
|
|
51
|
+
const origRenameSync = fs.renameSync.bind(fs);
|
|
52
|
+
const origCopyFileSync = fs.copyFileSync.bind(fs);
|
|
53
|
+
const origCpSync = fs.cpSync ? fs.cpSync.bind(fs) : null;
|
|
54
|
+
const origChmodSync = fs.chmodSync.bind(fs);
|
|
55
|
+
const origLinkSync = fs.linkSync.bind(fs);
|
|
56
|
+
const origSymlinkSync = fs.symlinkSync.bind(fs);
|
|
57
|
+
const origExistsSync = fs.existsSync.bind(fs);
|
|
58
|
+
|
|
59
|
+
const origMkdir = fs.mkdir.bind(fs);
|
|
60
|
+
const origRename = fs.rename.bind(fs);
|
|
61
|
+
const origCopyFile = fs.copyFile.bind(fs);
|
|
62
|
+
const origCp = fs.cp ? fs.cp.bind(fs) : null;
|
|
63
|
+
const origChmod = fs.chmod.bind(fs);
|
|
64
|
+
const origLink = fs.link.bind(fs);
|
|
65
|
+
const origSymlink = fs.symlink.bind(fs);
|
|
66
|
+
|
|
67
|
+
const origPromisesMkdir = fs.promises ? fs.promises.mkdir.bind(fs.promises) : null;
|
|
68
|
+
const origPromisesRename = fs.promises ? fs.promises.rename.bind(fs.promises) : null;
|
|
69
|
+
const origPromisesCopyFile = fs.promises ? fs.promises.copyFile.bind(fs.promises) : null;
|
|
70
|
+
const origPromisesCp = fs.promises && fs.promises.cp ? fs.promises.cp.bind(fs.promises) : null;
|
|
71
|
+
const origPromisesChmod = fs.promises ? fs.promises.chmod.bind(fs.promises) : null;
|
|
72
|
+
const origPromisesLink = fs.promises ? fs.promises.link.bind(fs.promises) : null;
|
|
73
|
+
const origPromisesSymlink = fs.promises ? fs.promises.symlink.bind(fs.promises) : null;
|
|
74
|
+
|
|
75
|
+
const origOpenSync = fs.openSync.bind(fs);
|
|
76
|
+
const origReadFileSync = fs.readFileSync.bind(fs);
|
|
77
|
+
const origWriteFileSync = fs.writeFileSync.bind(fs);
|
|
78
|
+
const origAppendFileSync = fs.appendFileSync.bind(fs);
|
|
79
|
+
const origCreateReadStream = fs.createReadStream.bind(fs);
|
|
80
|
+
const origCreateWriteStream = fs.createWriteStream.bind(fs);
|
|
81
|
+
|
|
82
|
+
const origOpen = fs.open.bind(fs);
|
|
83
|
+
const origReadFile = fs.readFile.bind(fs);
|
|
84
|
+
const origWriteFile = fs.writeFile.bind(fs);
|
|
85
|
+
const origAppendFile = fs.appendFile.bind(fs);
|
|
86
|
+
|
|
87
|
+
const origPromisesOpen = fs.promises ? fs.promises.open.bind(fs.promises) : null;
|
|
88
|
+
const origPromisesReadFile = fs.promises ? fs.promises.readFile.bind(fs.promises) : null;
|
|
89
|
+
const origPromisesWriteFile = fs.promises ? fs.promises.writeFile.bind(fs.promises) : null;
|
|
90
|
+
const origPromisesAppendFile = fs.promises ? fs.promises.appendFile.bind(fs.promises) : null;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 将 fs API 的 filePath 参数转为绝对路径。
|
|
94
|
+
* 处理 URL 对象(如 new URL('file:///tmp/x')),避免 String(URL) 产生无效路径绕过 shim。
|
|
95
|
+
* @param {string|Buffer|URL} filePath
|
|
96
|
+
* @returns {string} 绝对路径
|
|
97
|
+
*/
|
|
98
|
+
function toAbsPath(filePath) {
|
|
99
|
+
if (filePath instanceof URL) {
|
|
100
|
+
return url.fileURLToPath(filePath);
|
|
101
|
+
}
|
|
102
|
+
// 防御跨 VM context 的 URL 对象(instanceof 跨 realm 返回 false)
|
|
103
|
+
if (filePath && typeof filePath === 'object' && filePath.href && typeof filePath.protocol === 'string') {
|
|
104
|
+
return url.fileURLToPath(filePath);
|
|
105
|
+
}
|
|
106
|
+
return path.resolve(String(filePath));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
function isBrokerHostOperationEnabled() {
|
|
111
|
+
return PLATFORM === 'darwin'
|
|
112
|
+
&& BROKERED_FS_HOOK_ENABLED
|
|
113
|
+
&& !!process.env.CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS
|
|
114
|
+
&& !!process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID
|
|
115
|
+
&& !!process.env.CODEBUDDY_SANDBOX_HOST_FILE_OPERATION_COMMAND;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function loadBrokerNativeAddon() {
|
|
119
|
+
if (process.env.CODEBUDDY_SANDBOX_NATIVE_ADDON_DISABLED === '1') {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
if (brokerNativeAddonLoaded) {
|
|
123
|
+
return brokerNativeAddon;
|
|
124
|
+
}
|
|
125
|
+
brokerNativeAddonLoaded = true;
|
|
126
|
+
|
|
127
|
+
const candidates = [
|
|
128
|
+
process.env.CODEBUDDY_SANDBOX_NATIVE_ADDON_PATH,
|
|
129
|
+
path.join(__dirname, 'native', `${process.platform}-${process.arch}`, 'brokered-sandbox-native.node'),
|
|
130
|
+
path.join(__dirname, 'native', 'brokered-sandbox-native.node'),
|
|
131
|
+
].filter(Boolean);
|
|
132
|
+
|
|
133
|
+
for (const candidate of candidates) {
|
|
134
|
+
try {
|
|
135
|
+
const loaded = require(candidate);
|
|
136
|
+
if (loaded
|
|
137
|
+
&& typeof loaded.consumeSandboxExtension === 'function'
|
|
138
|
+
&& typeof loaded.requestBrokerSync === 'function') {
|
|
139
|
+
brokerNativeAddon = loaded;
|
|
140
|
+
return brokerNativeAddon;
|
|
141
|
+
}
|
|
142
|
+
} catch (_) {
|
|
143
|
+
// Optional native support. Without it, token-based Node fs access falls back to the OS sandbox.
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return undefined;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function isBrokerFileTokenEnabled() {
|
|
150
|
+
return PLATFORM === 'darwin'
|
|
151
|
+
&& BROKERED_FS_HOOK_ENABLED
|
|
152
|
+
&& !!process.env.CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS
|
|
153
|
+
&& !!process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID
|
|
154
|
+
&& !!process.env.CODEBUDDY_SANDBOX_FILE_TOKEN_OPERATION_COMMAND
|
|
155
|
+
&& !!loadBrokerNativeAddon();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function brokerTimeoutMs() {
|
|
159
|
+
return brokerIpc.brokerTimeoutMs ? brokerIpc.brokerTimeoutMs() : BROKER_HOST_OP_DEFAULT_TIMEOUT_MS;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function buildBrokerHostOperationRequest(operation, fields) {
|
|
163
|
+
const request = {
|
|
164
|
+
id: `node-${process.pid}-${++brokerRequestSeq}`,
|
|
165
|
+
runtime: 'node',
|
|
166
|
+
command: process.env.CODEBUDDY_SANDBOX_HOST_FILE_OPERATION_COMMAND || 'HostFileOperation',
|
|
167
|
+
operation,
|
|
168
|
+
sessionId: process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID || SESSION_ID,
|
|
169
|
+
...fields,
|
|
170
|
+
};
|
|
171
|
+
if (process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID) {
|
|
172
|
+
request.toolCallId = process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID;
|
|
173
|
+
}
|
|
174
|
+
if (process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID) {
|
|
175
|
+
request.brokerTraceId = process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID;
|
|
176
|
+
}
|
|
177
|
+
return request;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function buildBrokerFileTokenRequest(operation, filePath) {
|
|
181
|
+
const request = {
|
|
182
|
+
id: `node-${process.pid}-${++brokerRequestSeq}`,
|
|
183
|
+
runtime: 'node',
|
|
184
|
+
command: process.env.CODEBUDDY_SANDBOX_FILE_TOKEN_OPERATION_COMMAND || 'FileTokenRequest',
|
|
185
|
+
operation,
|
|
186
|
+
path: toAbsPath(filePath),
|
|
187
|
+
sessionId: process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID || SESSION_ID,
|
|
188
|
+
};
|
|
189
|
+
if (process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID) {
|
|
190
|
+
request.toolCallId = process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID;
|
|
191
|
+
}
|
|
192
|
+
if (process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID) {
|
|
193
|
+
request.brokerTraceId = process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID;
|
|
194
|
+
}
|
|
195
|
+
return request;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function buildBrokerFileWriteCompletedRequest(filePath) {
|
|
199
|
+
const request = {
|
|
200
|
+
id: `node-${process.pid}-${++brokerRequestSeq}`,
|
|
201
|
+
runtime: 'node',
|
|
202
|
+
command: 'FileWriteCompleted',
|
|
203
|
+
operation: 'write',
|
|
204
|
+
path: toAbsPath(filePath),
|
|
205
|
+
sessionId: process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID || SESSION_ID,
|
|
206
|
+
};
|
|
207
|
+
if (process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID) {
|
|
208
|
+
request.toolCallId = process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID;
|
|
209
|
+
}
|
|
210
|
+
if (process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID) {
|
|
211
|
+
request.brokerTraceId = process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID;
|
|
212
|
+
}
|
|
213
|
+
return request;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function createBrokerPolicyError(response) {
|
|
217
|
+
const message = response && response.error
|
|
218
|
+
? String(response.error)
|
|
219
|
+
: `Brokered Node host operation refused: ${response && response.operation ? response.operation : 'unknown'}`;
|
|
220
|
+
const error = new Error(message);
|
|
221
|
+
error.code = 'CODEBUDDY_BROKER_DENY';
|
|
222
|
+
error.decision = response && response.decision;
|
|
223
|
+
error.__codebuddyBrokerPolicyError = true;
|
|
224
|
+
return error;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function handleBrokerHostOperationResponse(response) {
|
|
228
|
+
if (response && response.ok === true) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
if (response && response.decision === 'sandbox') {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
throw createBrokerPolicyError(response);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function handleBrokerFileTokenResponse(response) {
|
|
238
|
+
if (response && response.ok === true && typeof response.token === 'string' && response.token) {
|
|
239
|
+
const nativeAddon = loadBrokerNativeAddon();
|
|
240
|
+
if (!nativeAddon) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
nativeAddon.consumeSandboxExtension(response.token);
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
if (response && response.decision === 'sandbox') {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
throw createBrokerPolicyError(response);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function parseBrokerHostOperationResponse(line) {
|
|
253
|
+
return brokerIpc.parseBrokerResponse(line);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function requestBrokerHostOperation(request) {
|
|
257
|
+
return brokerIpc.sendBrokerRequest(request);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function isPathLikeFileAccessTarget(filePath) {
|
|
261
|
+
return typeof filePath !== 'number';
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function existedBeforeWrite(filePath) {
|
|
265
|
+
if (!isPathLikeFileAccessTarget(filePath)) {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
try {
|
|
269
|
+
return origExistsSync(toAbsPath(filePath));
|
|
270
|
+
} catch (_) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function isUnderShimDir(absPath) {
|
|
276
|
+
const rel = path.relative(SHIM_DIR, absPath);
|
|
277
|
+
return rel === '' || (!!rel && !rel.startsWith('..') && !path.isAbsolute(rel));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Avoid broker file-token interception while require() reads sibling shim modules.
|
|
281
|
+
function shouldBypassBrokerFileToken(operation, filePath) {
|
|
282
|
+
return operation === 'read'
|
|
283
|
+
&& isPathLikeFileAccessTarget(filePath)
|
|
284
|
+
&& isUnderShimDir(toAbsPath(filePath));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function tryBrokerFileTokenSync(operation, filePath) {
|
|
288
|
+
if (!isPathLikeFileAccessTarget(filePath)
|
|
289
|
+
|| shouldBypassBrokerFileToken(operation, filePath)
|
|
290
|
+
|| !isBrokerFileTokenEnabled()) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
const nativeAddon = loadBrokerNativeAddon();
|
|
294
|
+
const request = buildBrokerFileTokenRequest(operation, filePath);
|
|
295
|
+
try {
|
|
296
|
+
const responseLine = nativeAddon.requestBrokerSync(
|
|
297
|
+
process.env.CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS,
|
|
298
|
+
JSON.stringify(request),
|
|
299
|
+
brokerTimeoutMs(),
|
|
300
|
+
);
|
|
301
|
+
return handleBrokerFileTokenResponse(parseBrokerHostOperationResponse(responseLine));
|
|
302
|
+
} catch (error) {
|
|
303
|
+
if (error && error.__codebuddyBrokerPolicyError) {
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
logBrokerFallback('file-token-sync', operation, filePath, error);
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
async function tryBrokerFileToken(operation, filePath) {
|
|
312
|
+
if (!isPathLikeFileAccessTarget(filePath)
|
|
313
|
+
|| shouldBypassBrokerFileToken(operation, filePath)
|
|
314
|
+
|| !isBrokerFileTokenEnabled()) {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
const request = buildBrokerFileTokenRequest(operation, filePath);
|
|
318
|
+
try {
|
|
319
|
+
return handleBrokerFileTokenResponse(await requestBrokerHostOperation(request));
|
|
320
|
+
} catch (error) {
|
|
321
|
+
if (error && error.__codebuddyBrokerPolicyError) {
|
|
322
|
+
throw error;
|
|
323
|
+
}
|
|
324
|
+
logBrokerFallback('file-token', operation, filePath, error);
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function isBrokerFileWriteCompletedEnabled(filePath) {
|
|
330
|
+
return PLATFORM === 'darwin'
|
|
331
|
+
&& BROKERED_FS_HOOK_ENABLED
|
|
332
|
+
&& isPathLikeFileAccessTarget(filePath)
|
|
333
|
+
&& !!process.env.CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS
|
|
334
|
+
&& !!process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function notifyBrokerFileWriteCompletedSync(filePath, existedBefore) {
|
|
338
|
+
if (existedBefore) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (!isBrokerFileWriteCompletedEnabled(filePath)) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
try {
|
|
345
|
+
requestBrokerHostOperationSync(buildBrokerFileWriteCompletedRequest(filePath));
|
|
346
|
+
} catch (error) {
|
|
347
|
+
logBrokerFallback('file-write-completed-sync', 'write', filePath, error);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async function notifyBrokerFileWriteCompleted(filePath, existedBefore) {
|
|
352
|
+
if (existedBefore) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (!isBrokerFileWriteCompletedEnabled(filePath)) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
await requestBrokerHostOperation(buildBrokerFileWriteCompletedRequest(filePath));
|
|
360
|
+
} catch (error) {
|
|
361
|
+
logBrokerFallback('file-write-completed', 'write', filePath, error);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function requestBrokerHostOperationSync(request) {
|
|
366
|
+
return brokerIpc.sendBrokerRequestSync(request, { nativeAddon: loadBrokerNativeAddon() });
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function tryBrokerHostOperationSync(operation, fields) {
|
|
370
|
+
if (!isBrokerHostOperationEnabled()) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
const request = buildBrokerHostOperationRequest(operation, fields);
|
|
374
|
+
try {
|
|
375
|
+
return handleBrokerHostOperationResponse(requestBrokerHostOperationSync(request));
|
|
376
|
+
} catch (error) {
|
|
377
|
+
if (error && error.__codebuddyBrokerPolicyError) {
|
|
378
|
+
throw error;
|
|
379
|
+
}
|
|
380
|
+
logBrokerFallback('host-op-sync', operation, fields && (fields.path || fields.to || fields.from), error);
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
async function tryBrokerHostOperation(operation, fields) {
|
|
386
|
+
if (!isBrokerHostOperationEnabled()) {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
const request = buildBrokerHostOperationRequest(operation, fields);
|
|
390
|
+
try {
|
|
391
|
+
return handleBrokerHostOperationResponse(await requestBrokerHostOperation(request));
|
|
392
|
+
} catch (error) {
|
|
393
|
+
if (error && error.__codebuddyBrokerPolicyError) {
|
|
394
|
+
throw error;
|
|
395
|
+
}
|
|
396
|
+
logBrokerFallback('host-op', operation, fields && (fields.path || fields.to || fields.from), error);
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function normalizeMode(mode) {
|
|
402
|
+
if (typeof mode === 'number' && Number.isFinite(mode)) {
|
|
403
|
+
return mode;
|
|
404
|
+
}
|
|
405
|
+
if (typeof mode === 'string' && mode.trim()) {
|
|
406
|
+
const parsed = Number.parseInt(mode, 8);
|
|
407
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
408
|
+
}
|
|
409
|
+
return undefined;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function normalizeMkdirOptions(options) {
|
|
413
|
+
if (typeof options === 'number' || typeof options === 'string') {
|
|
414
|
+
return { mode: normalizeMode(options) };
|
|
415
|
+
}
|
|
416
|
+
if (options && typeof options === 'object') {
|
|
417
|
+
return {
|
|
418
|
+
recursive: !!options.recursive,
|
|
419
|
+
mode: normalizeMode(options.mode),
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
return {};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function brokerOperationForOpenFlags(flags) {
|
|
426
|
+
const value = flags === undefined ? 'r' : flags;
|
|
427
|
+
if (typeof value === 'number') {
|
|
428
|
+
const constants = fs.constants || {};
|
|
429
|
+
const writeMask = (constants.O_WRONLY || 0)
|
|
430
|
+
| (constants.O_RDWR || 0)
|
|
431
|
+
| (constants.O_CREAT || 0)
|
|
432
|
+
| (constants.O_TRUNC || 0)
|
|
433
|
+
| (constants.O_APPEND || 0);
|
|
434
|
+
return (value & writeMask) ? 'write' : 'read';
|
|
435
|
+
}
|
|
436
|
+
const text = String(value);
|
|
437
|
+
return /[wa+]/.test(text) ? 'write' : 'read';
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function buildMkdirBrokerFields(filePath, options) {
|
|
441
|
+
const normalized = normalizeMkdirOptions(options);
|
|
442
|
+
return {
|
|
443
|
+
path: toAbsPath(filePath),
|
|
444
|
+
recursive: normalized.recursive,
|
|
445
|
+
...(normalized.mode !== undefined ? { mode: normalized.mode } : {}),
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function shouldBrokerCopyFileMode(mode) {
|
|
450
|
+
return mode === undefined || mode === 0;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function isSimpleCpOptions(options) {
|
|
454
|
+
if (options === undefined) {
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
if (!options || typeof options !== 'object') {
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
return Object.keys(options).every(key => key === 'recursive');
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
// ----- brokered file tokens(当前 Node 进程消费 sandbox token 后继续原生 fs)-----
|
|
465
|
+
|
|
466
|
+
function wrappedOpenSync(filePath, flags, mode) {
|
|
467
|
+
tryBrokerFileTokenSync(brokerOperationForOpenFlags(flags), filePath);
|
|
468
|
+
return origOpenSync(filePath, flags, mode);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function wrappedOpen(filePath, flags, mode, callback) {
|
|
472
|
+
const originalArgs = Array.prototype.slice.call(arguments);
|
|
473
|
+
let openFlags = flags;
|
|
474
|
+
let cb = callback;
|
|
475
|
+
if (typeof flags === 'function') {
|
|
476
|
+
openFlags = undefined;
|
|
477
|
+
cb = flags;
|
|
478
|
+
} else if (typeof mode === 'function') {
|
|
479
|
+
cb = mode;
|
|
480
|
+
}
|
|
481
|
+
if (typeof cb !== 'function') {
|
|
482
|
+
return origOpen(...originalArgs);
|
|
483
|
+
}
|
|
484
|
+
tryBrokerFileToken(brokerOperationForOpenFlags(openFlags), filePath)
|
|
485
|
+
.then(() => origOpen(...originalArgs))
|
|
486
|
+
.catch(error => process.nextTick(() => cb(error)));
|
|
487
|
+
return undefined;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async function wrappedPromisesOpen(filePath, flags, mode) {
|
|
491
|
+
await tryBrokerFileToken(brokerOperationForOpenFlags(flags), filePath);
|
|
492
|
+
return origPromisesOpen(filePath, flags, mode);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function wrappedReadFileSync(filePath, options) {
|
|
496
|
+
tryBrokerFileTokenSync('read', filePath);
|
|
497
|
+
return origReadFileSync(filePath, options);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function wrappedReadFile(filePath, options, callback) {
|
|
501
|
+
const originalArgs = Array.prototype.slice.call(arguments);
|
|
502
|
+
const cb = typeof options === 'function' ? options : callback;
|
|
503
|
+
if (typeof cb !== 'function') {
|
|
504
|
+
return origReadFile(...originalArgs);
|
|
505
|
+
}
|
|
506
|
+
tryBrokerFileToken('read', filePath)
|
|
507
|
+
.then(() => origReadFile(...originalArgs))
|
|
508
|
+
.catch(error => process.nextTick(() => cb(error)));
|
|
509
|
+
return undefined;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
async function wrappedPromisesReadFile(filePath, options) {
|
|
513
|
+
await tryBrokerFileToken('read', filePath);
|
|
514
|
+
return origPromisesReadFile(filePath, options);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Node's real appendFileSync/appendFile implementations delegate internally to
|
|
518
|
+
// fs.writeFileSync/fs.writeFile (the same mutable exported properties this shim
|
|
519
|
+
// patches), so a naive append wrapper that also instruments would double-fire
|
|
520
|
+
// the broker token/write-completed calls. This depth counter lets the write
|
|
521
|
+
// wrappers detect "we're already inside an append call we instrumented" and
|
|
522
|
+
// fall back to the un-instrumented original, regardless of whether a given
|
|
523
|
+
// Node version happens to implement append via delegation or not.
|
|
524
|
+
let suppressWriteInstrumentationDepth = 0;
|
|
525
|
+
|
|
526
|
+
function wrappedWriteFileSync(filePath, data, options) {
|
|
527
|
+
if (suppressWriteInstrumentationDepth > 0) {
|
|
528
|
+
return origWriteFileSync(filePath, data, options);
|
|
529
|
+
}
|
|
530
|
+
const existedBefore = existedBeforeWrite(filePath);
|
|
531
|
+
tryBrokerFileTokenSync('write', filePath);
|
|
532
|
+
const result = origWriteFileSync(filePath, data, options);
|
|
533
|
+
notifyBrokerFileWriteCompletedSync(filePath, existedBefore);
|
|
534
|
+
return result;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function wrappedWriteFile(filePath, data, options, callback) {
|
|
538
|
+
const cb = typeof options === 'function' ? options : callback;
|
|
539
|
+
if (typeof cb !== 'function') {
|
|
540
|
+
return origWriteFile.apply(fs, arguments);
|
|
541
|
+
}
|
|
542
|
+
if (suppressWriteInstrumentationDepth > 0) {
|
|
543
|
+
return origWriteFile.apply(fs, arguments);
|
|
544
|
+
}
|
|
545
|
+
const existedBefore = existedBeforeWrite(filePath);
|
|
546
|
+
const wrappedCallback = error => {
|
|
547
|
+
if (error) {
|
|
548
|
+
cb(error);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
void notifyBrokerFileWriteCompleted(filePath, existedBefore);
|
|
552
|
+
cb(null);
|
|
553
|
+
};
|
|
554
|
+
tryBrokerFileToken('write', filePath)
|
|
555
|
+
.then(() => {
|
|
556
|
+
if (typeof options === 'function') {
|
|
557
|
+
origWriteFile(filePath, data, wrappedCallback);
|
|
558
|
+
} else {
|
|
559
|
+
origWriteFile(filePath, data, options, wrappedCallback);
|
|
560
|
+
}
|
|
561
|
+
})
|
|
562
|
+
.catch(error => process.nextTick(() => cb(error)));
|
|
563
|
+
return undefined;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
async function wrappedPromisesWriteFile(filePath, data, options) {
|
|
567
|
+
const existedBefore = existedBeforeWrite(filePath);
|
|
568
|
+
await tryBrokerFileToken('write', filePath);
|
|
569
|
+
const result = await origPromisesWriteFile(filePath, data, options);
|
|
570
|
+
void notifyBrokerFileWriteCompleted(filePath, existedBefore);
|
|
571
|
+
return result;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
function wrappedAppendFileSync(filePath, data, options) {
|
|
575
|
+
const existedBefore = existedBeforeWrite(filePath);
|
|
576
|
+
tryBrokerFileTokenSync('write', filePath);
|
|
577
|
+
suppressWriteInstrumentationDepth++;
|
|
578
|
+
let result;
|
|
579
|
+
try {
|
|
580
|
+
result = origAppendFileSync(filePath, data, options);
|
|
581
|
+
} finally {
|
|
582
|
+
suppressWriteInstrumentationDepth--;
|
|
583
|
+
}
|
|
584
|
+
notifyBrokerFileWriteCompletedSync(filePath, existedBefore);
|
|
585
|
+
return result;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
function wrappedAppendFile(filePath, data, options, callback) {
|
|
589
|
+
const cb = typeof options === 'function' ? options : callback;
|
|
590
|
+
if (typeof cb !== 'function') {
|
|
591
|
+
return origAppendFile.apply(fs, arguments);
|
|
592
|
+
}
|
|
593
|
+
const existedBefore = existedBeforeWrite(filePath);
|
|
594
|
+
const wrappedCallback = error => {
|
|
595
|
+
if (error) {
|
|
596
|
+
cb(error);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
void notifyBrokerFileWriteCompleted(filePath, existedBefore);
|
|
600
|
+
cb(null);
|
|
601
|
+
};
|
|
602
|
+
tryBrokerFileToken('write', filePath)
|
|
603
|
+
.then(() => {
|
|
604
|
+
suppressWriteInstrumentationDepth++;
|
|
605
|
+
try {
|
|
606
|
+
if (typeof options === 'function') {
|
|
607
|
+
origAppendFile(filePath, data, wrappedCallback);
|
|
608
|
+
} else {
|
|
609
|
+
origAppendFile(filePath, data, options, wrappedCallback);
|
|
610
|
+
}
|
|
611
|
+
} finally {
|
|
612
|
+
suppressWriteInstrumentationDepth--;
|
|
613
|
+
}
|
|
614
|
+
})
|
|
615
|
+
.catch(error => process.nextTick(() => cb(error)));
|
|
616
|
+
return undefined;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
async function wrappedPromisesAppendFile(filePath, data, options) {
|
|
620
|
+
const existedBefore = existedBeforeWrite(filePath);
|
|
621
|
+
await tryBrokerFileToken('write', filePath);
|
|
622
|
+
const result = await origPromisesAppendFile(filePath, data, options);
|
|
623
|
+
void notifyBrokerFileWriteCompleted(filePath, existedBefore);
|
|
624
|
+
return result;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function wrappedCreateReadStream(filePath, options) {
|
|
628
|
+
tryBrokerFileTokenSync('read', filePath);
|
|
629
|
+
return origCreateReadStream(filePath, options);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function wrappedCreateWriteStream(filePath, options) {
|
|
633
|
+
tryBrokerFileTokenSync('write', filePath);
|
|
634
|
+
return origCreateWriteStream(filePath, options);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// ----- brokered host operations(非删除类文件变更)-----
|
|
638
|
+
|
|
639
|
+
function wrappedMkdirSync(filePath, options) {
|
|
640
|
+
if (tryBrokerHostOperationSync('mkdir', buildMkdirBrokerFields(filePath, options))) {
|
|
641
|
+
return undefined;
|
|
642
|
+
}
|
|
643
|
+
return origMkdirSync(filePath, options);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
function wrappedMkdir(filePath, options, callback) {
|
|
647
|
+
let opts = options;
|
|
648
|
+
let cb = callback;
|
|
649
|
+
if (typeof options === 'function') {
|
|
650
|
+
opts = undefined;
|
|
651
|
+
cb = options;
|
|
652
|
+
}
|
|
653
|
+
if (typeof cb !== 'function') {
|
|
654
|
+
return origMkdir(filePath, options, callback);
|
|
655
|
+
}
|
|
656
|
+
tryBrokerHostOperation('mkdir', buildMkdirBrokerFields(filePath, opts))
|
|
657
|
+
.then(handled => {
|
|
658
|
+
if (handled) {
|
|
659
|
+
process.nextTick(() => cb(null));
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
origMkdir(filePath, options, callback);
|
|
663
|
+
})
|
|
664
|
+
.catch(error => process.nextTick(() => cb(error)));
|
|
665
|
+
return undefined;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
async function wrappedPromisesMkdir(filePath, options) {
|
|
669
|
+
if (await tryBrokerHostOperation('mkdir', buildMkdirBrokerFields(filePath, options))) {
|
|
670
|
+
return undefined;
|
|
671
|
+
}
|
|
672
|
+
return origPromisesMkdir(filePath, options);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function wrappedRenameSync(from, to) {
|
|
676
|
+
if (tryBrokerHostOperationSync('rename', { from: toAbsPath(from), to: toAbsPath(to) })) {
|
|
677
|
+
return undefined;
|
|
678
|
+
}
|
|
679
|
+
return origRenameSync(from, to);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function wrappedRename(from, to, callback) {
|
|
683
|
+
if (typeof callback !== 'function') {
|
|
684
|
+
return origRename(from, to, callback);
|
|
685
|
+
}
|
|
686
|
+
tryBrokerHostOperation('rename', { from: toAbsPath(from), to: toAbsPath(to) })
|
|
687
|
+
.then(handled => {
|
|
688
|
+
if (handled) {
|
|
689
|
+
process.nextTick(() => callback(null));
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
origRename(from, to, callback);
|
|
693
|
+
})
|
|
694
|
+
.catch(error => process.nextTick(() => callback(error)));
|
|
695
|
+
return undefined;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
async function wrappedPromisesRename(from, to) {
|
|
699
|
+
if (await tryBrokerHostOperation('rename', { from: toAbsPath(from), to: toAbsPath(to) })) {
|
|
700
|
+
return undefined;
|
|
701
|
+
}
|
|
702
|
+
return origPromisesRename(from, to);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
function wrappedCopyFileSync(from, to, mode) {
|
|
706
|
+
if (shouldBrokerCopyFileMode(mode)
|
|
707
|
+
&& tryBrokerHostOperationSync('copy', { from: toAbsPath(from), to: toAbsPath(to), recursive: false })) {
|
|
708
|
+
return undefined;
|
|
709
|
+
}
|
|
710
|
+
return origCopyFileSync(from, to, mode);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function wrappedCopyFile(from, to, mode, callback) {
|
|
714
|
+
let copyMode = mode;
|
|
715
|
+
let cb = callback;
|
|
716
|
+
if (typeof mode === 'function') {
|
|
717
|
+
copyMode = undefined;
|
|
718
|
+
cb = mode;
|
|
719
|
+
}
|
|
720
|
+
if (typeof cb !== 'function' || !shouldBrokerCopyFileMode(copyMode)) {
|
|
721
|
+
return origCopyFile(from, to, mode, callback);
|
|
722
|
+
}
|
|
723
|
+
tryBrokerHostOperation('copy', { from: toAbsPath(from), to: toAbsPath(to), recursive: false })
|
|
724
|
+
.then(handled => {
|
|
725
|
+
if (handled) {
|
|
726
|
+
process.nextTick(() => cb(null));
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
origCopyFile(from, to, mode, callback);
|
|
730
|
+
})
|
|
731
|
+
.catch(error => process.nextTick(() => cb(error)));
|
|
732
|
+
return undefined;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
async function wrappedPromisesCopyFile(from, to, mode) {
|
|
736
|
+
if (shouldBrokerCopyFileMode(mode)
|
|
737
|
+
&& await tryBrokerHostOperation('copy', { from: toAbsPath(from), to: toAbsPath(to), recursive: false })) {
|
|
738
|
+
return undefined;
|
|
739
|
+
}
|
|
740
|
+
return origPromisesCopyFile(from, to, mode);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
function wrappedCpSync(from, to, options) {
|
|
744
|
+
if (isSimpleCpOptions(options)
|
|
745
|
+
&& tryBrokerHostOperationSync('copy', { from: toAbsPath(from), to: toAbsPath(to), recursive: !!(options && options.recursive) })) {
|
|
746
|
+
return undefined;
|
|
747
|
+
}
|
|
748
|
+
return origCpSync(from, to, options);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
function wrappedCp(from, to, options, callback) {
|
|
752
|
+
let opts = options;
|
|
753
|
+
let cb = callback;
|
|
754
|
+
if (typeof options === 'function') {
|
|
755
|
+
opts = undefined;
|
|
756
|
+
cb = options;
|
|
757
|
+
}
|
|
758
|
+
if (typeof cb !== 'function' || !isSimpleCpOptions(opts)) {
|
|
759
|
+
return origCp(from, to, options, callback);
|
|
760
|
+
}
|
|
761
|
+
tryBrokerHostOperation('copy', { from: toAbsPath(from), to: toAbsPath(to), recursive: !!(opts && opts.recursive) })
|
|
762
|
+
.then(handled => {
|
|
763
|
+
if (handled) {
|
|
764
|
+
process.nextTick(() => cb(null));
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
origCp(from, to, options, callback);
|
|
768
|
+
})
|
|
769
|
+
.catch(error => process.nextTick(() => cb(error)));
|
|
770
|
+
return undefined;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
async function wrappedPromisesCp(from, to, options) {
|
|
774
|
+
if (isSimpleCpOptions(options)
|
|
775
|
+
&& await tryBrokerHostOperation('copy', { from: toAbsPath(from), to: toAbsPath(to), recursive: !!(options && options.recursive) })) {
|
|
776
|
+
return undefined;
|
|
777
|
+
}
|
|
778
|
+
return origPromisesCp(from, to, options);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
function wrappedChmodSync(filePath, mode) {
|
|
782
|
+
const normalizedMode = normalizeMode(mode);
|
|
783
|
+
if (normalizedMode !== undefined
|
|
784
|
+
&& tryBrokerHostOperationSync('chmod', { path: toAbsPath(filePath), mode: normalizedMode })) {
|
|
785
|
+
return undefined;
|
|
786
|
+
}
|
|
787
|
+
return origChmodSync(filePath, mode);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
function wrappedChmod(filePath, mode, callback) {
|
|
791
|
+
const normalizedMode = normalizeMode(mode);
|
|
792
|
+
if (typeof callback !== 'function' || normalizedMode === undefined) {
|
|
793
|
+
return origChmod(filePath, mode, callback);
|
|
794
|
+
}
|
|
795
|
+
tryBrokerHostOperation('chmod', { path: toAbsPath(filePath), mode: normalizedMode })
|
|
796
|
+
.then(handled => {
|
|
797
|
+
if (handled) {
|
|
798
|
+
process.nextTick(() => callback(null));
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
origChmod(filePath, mode, callback);
|
|
802
|
+
})
|
|
803
|
+
.catch(error => process.nextTick(() => callback(error)));
|
|
804
|
+
return undefined;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
async function wrappedPromisesChmod(filePath, mode) {
|
|
808
|
+
const normalizedMode = normalizeMode(mode);
|
|
809
|
+
if (normalizedMode !== undefined
|
|
810
|
+
&& await tryBrokerHostOperation('chmod', { path: toAbsPath(filePath), mode: normalizedMode })) {
|
|
811
|
+
return undefined;
|
|
812
|
+
}
|
|
813
|
+
return origPromisesChmod(filePath, mode);
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
function wrappedLinkSync(from, to) {
|
|
817
|
+
if (tryBrokerHostOperationSync('link', { from: toAbsPath(from), to: toAbsPath(to), symbolic: false })) {
|
|
818
|
+
return undefined;
|
|
819
|
+
}
|
|
820
|
+
return origLinkSync(from, to);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function wrappedLink(from, to, callback) {
|
|
824
|
+
if (typeof callback !== 'function') {
|
|
825
|
+
return origLink(from, to, callback);
|
|
826
|
+
}
|
|
827
|
+
tryBrokerHostOperation('link', { from: toAbsPath(from), to: toAbsPath(to), symbolic: false })
|
|
828
|
+
.then(handled => {
|
|
829
|
+
if (handled) {
|
|
830
|
+
process.nextTick(() => callback(null));
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
origLink(from, to, callback);
|
|
834
|
+
})
|
|
835
|
+
.catch(error => process.nextTick(() => callback(error)));
|
|
836
|
+
return undefined;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
async function wrappedPromisesLink(from, to) {
|
|
840
|
+
if (await tryBrokerHostOperation('link', { from: toAbsPath(from), to: toAbsPath(to), symbolic: false })) {
|
|
841
|
+
return undefined;
|
|
842
|
+
}
|
|
843
|
+
return origPromisesLink(from, to);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
function wrappedSymlinkSync(from, to, type) {
|
|
847
|
+
if (tryBrokerHostOperationSync('link', { from: String(from), to: toAbsPath(to), symbolic: true })) {
|
|
848
|
+
return undefined;
|
|
849
|
+
}
|
|
850
|
+
return origSymlinkSync(from, to, type);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
function wrappedSymlink(from, to, type, callback) {
|
|
854
|
+
let linkType = type;
|
|
855
|
+
let cb = callback;
|
|
856
|
+
if (typeof type === 'function') {
|
|
857
|
+
linkType = undefined;
|
|
858
|
+
cb = type;
|
|
859
|
+
}
|
|
860
|
+
if (typeof cb !== 'function') {
|
|
861
|
+
return origSymlink(from, to, type, callback);
|
|
862
|
+
}
|
|
863
|
+
tryBrokerHostOperation('link', { from: String(from), to: toAbsPath(to), symbolic: true })
|
|
864
|
+
.then(handled => {
|
|
865
|
+
if (handled) {
|
|
866
|
+
process.nextTick(() => cb(null));
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
origSymlink(from, to, linkType, cb);
|
|
870
|
+
})
|
|
871
|
+
.catch(error => process.nextTick(() => cb(error)));
|
|
872
|
+
return undefined;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
async function wrappedPromisesSymlink(from, to, type) {
|
|
876
|
+
if (await tryBrokerHostOperation('link', { from: String(from), to: toAbsPath(to), symbolic: true })) {
|
|
877
|
+
return undefined;
|
|
878
|
+
}
|
|
879
|
+
return origPromisesSymlink(from, to, type);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
// ---------------------------------------------------------------------------
|
|
884
|
+
// 安装 brokered fs patch
|
|
885
|
+
// ---------------------------------------------------------------------------
|
|
886
|
+
|
|
887
|
+
fs.openSync = wrappedOpenSync;
|
|
888
|
+
fs.readFileSync = wrappedReadFileSync;
|
|
889
|
+
fs.writeFileSync = wrappedWriteFileSync;
|
|
890
|
+
fs.appendFileSync = wrappedAppendFileSync;
|
|
891
|
+
fs.createReadStream = wrappedCreateReadStream;
|
|
892
|
+
fs.createWriteStream = wrappedCreateWriteStream;
|
|
893
|
+
|
|
894
|
+
fs.open = wrappedOpen;
|
|
895
|
+
fs.readFile = wrappedReadFile;
|
|
896
|
+
fs.writeFile = wrappedWriteFile;
|
|
897
|
+
fs.appendFile = wrappedAppendFile;
|
|
898
|
+
fs.mkdirSync = wrappedMkdirSync;
|
|
899
|
+
fs.renameSync = wrappedRenameSync;
|
|
900
|
+
fs.copyFileSync = wrappedCopyFileSync;
|
|
901
|
+
if (origCpSync) fs.cpSync = wrappedCpSync;
|
|
902
|
+
fs.chmodSync = wrappedChmodSync;
|
|
903
|
+
fs.linkSync = wrappedLinkSync;
|
|
904
|
+
fs.symlinkSync = wrappedSymlinkSync;
|
|
905
|
+
|
|
906
|
+
fs.mkdir = wrappedMkdir;
|
|
907
|
+
fs.rename = wrappedRename;
|
|
908
|
+
fs.copyFile = wrappedCopyFile;
|
|
909
|
+
if (origCp) fs.cp = wrappedCp;
|
|
910
|
+
fs.chmod = wrappedChmod;
|
|
911
|
+
fs.link = wrappedLink;
|
|
912
|
+
fs.symlink = wrappedSymlink;
|
|
913
|
+
|
|
914
|
+
if (fs.promises) {
|
|
915
|
+
fs.promises.open = wrappedPromisesOpen;
|
|
916
|
+
fs.promises.readFile = wrappedPromisesReadFile;
|
|
917
|
+
fs.promises.writeFile = wrappedPromisesWriteFile;
|
|
918
|
+
fs.promises.appendFile = wrappedPromisesAppendFile;
|
|
919
|
+
fs.promises.mkdir = wrappedPromisesMkdir;
|
|
920
|
+
fs.promises.rename = wrappedPromisesRename;
|
|
921
|
+
fs.promises.copyFile = wrappedPromisesCopyFile;
|
|
922
|
+
if (origPromisesCp) fs.promises.cp = wrappedPromisesCp;
|
|
923
|
+
fs.promises.chmod = wrappedPromisesChmod;
|
|
924
|
+
fs.promises.link = wrappedPromisesLink;
|
|
925
|
+
fs.promises.symlink = wrappedPromisesSymlink;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
try {
|
|
929
|
+
require('module').syncBuiltinESMExports?.();
|
|
930
|
+
} catch (_) {
|
|
931
|
+
// Best-effort only. CommonJS fs patching above remains active.
|
|
932
|
+
}
|