@xiaoyuyu6420/dsh-backup 0.13.2 → 0.13.4
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/README.en.md +4 -1
- package/README.md +4 -1
- package/lib/client.js +5 -5
- package/lib/index.js +240 -67
- package/package.json +14 -2
- package/rescue/rescue.mjs +38 -10
package/rescue/rescue.mjs
CHANGED
|
@@ -37,7 +37,11 @@ const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
|
37
37
|
const SENSITIVE_DEFAULTS = ['.credentials.yaml', '.env', 'qq-bridge/config.json'];
|
|
38
38
|
const VAULT_DIR = 'vault';
|
|
39
39
|
const ZSTD_MAGIC = 0xfd2fb528;
|
|
40
|
-
|
|
40
|
+
// 与 lib/index.js 同源:会话日志名形如 session[.v<N>].jsonl[.zstd](宿主
|
|
41
|
+
// sessionFormatLogFilename 的形态)。写死具体名字会在格式换代当天整体失明
|
|
42
|
+
// (#117)——救援台是宿主起不来时的唯一通道,更不能看不见会话。
|
|
43
|
+
const SESSION_LOG_RE = /^session(?:\.v([1-9][0-9]*))?\.jsonl(?:\.zstd)?$/;
|
|
44
|
+
const isSessionLogName = (name) => SESSION_LOG_RE.test(name);
|
|
41
45
|
const SCAN_SKIP_DIRS = new Set(['node_modules', '.system', '.git', 'vault']);
|
|
42
46
|
const SCAN_MAX_FILES = 4000;
|
|
43
47
|
const SCAN_MAX_DEPTH = 8;
|
|
@@ -173,24 +177,48 @@ function parseTarEntry(line) {
|
|
|
173
177
|
}
|
|
174
178
|
}
|
|
175
179
|
if (nameIdx < 0 || nameIdx >= f.length) return null;
|
|
176
|
-
|
|
180
|
+
const rest = f.slice(nameIdx).join(' ');
|
|
181
|
+
// 链接目标单独摘出(硬链接 `<名> link to <目标>`、符号链接 `<名> -> <目标>`):
|
|
182
|
+
// 与插件侧 parseTarEntry 同语义,别把目标混进名字(#112)。
|
|
183
|
+
let name = rest;
|
|
184
|
+
let link = null;
|
|
185
|
+
const hardAt = rest.indexOf(' link to ');
|
|
186
|
+
if (hardAt >= 0) {
|
|
187
|
+
name = rest.slice(0, hardAt);
|
|
188
|
+
link = rest.slice(hardAt + ' link to '.length);
|
|
189
|
+
} else {
|
|
190
|
+
const symAt = rest.lastIndexOf(' -> ');
|
|
191
|
+
if (symAt >= 0) {
|
|
192
|
+
name = rest.slice(0, symAt);
|
|
193
|
+
link = rest.slice(symAt + 4);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
type: f[0][0],
|
|
198
|
+
name: name.replace(/\/$/, ''),
|
|
199
|
+
link: link === null ? null : link.replace(/\/$/, ''),
|
|
200
|
+
};
|
|
177
201
|
}
|
|
178
202
|
|
|
179
203
|
function safeEntries(listedText, base) {
|
|
180
204
|
const entries = [];
|
|
181
205
|
const bad = [];
|
|
206
|
+
const insideBase = (p) => Boolean(p)
|
|
207
|
+
&& !p.startsWith('/') && !/^[A-Za-z]:/.test(p)
|
|
208
|
+
&& !p.split('/').includes('..')
|
|
209
|
+
&& (p === base || p.startsWith(`${base}/`));
|
|
182
210
|
for (const line of listedText.split('\n')) {
|
|
183
211
|
const s = line.trim();
|
|
184
212
|
if (!s) continue;
|
|
185
213
|
const parsed = parseTarEntry(s);
|
|
186
214
|
const name = parsed ? parsed.name.replace(/\\/g, '/').replace(/\/$/, '') : null;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
) {
|
|
215
|
+
const link = parsed && parsed.link ? parsed.link.replace(/\\/g, '/').replace(/\/$/, '') : null;
|
|
216
|
+
// 与插件侧同语义:放行目标也在备份根内的硬链接 'h'(DSH 附件库的正常形态,
|
|
217
|
+
// 见 issue #112),符号链接/设备等仍拒绝。救援台是宿主起不来时的唯一通路,
|
|
218
|
+
// 这里漏判会让"插件写出的归档自己都恢复不了"。
|
|
219
|
+
const plainOk = Boolean(parsed) && Boolean(name) && (parsed.type === '-' || parsed.type === 'd') && insideBase(name);
|
|
220
|
+
const hardOk = Boolean(parsed) && parsed.type === 'h' && insideBase(name) && insideBase(link);
|
|
221
|
+
if (!plainOk && !hardOk) {
|
|
194
222
|
bad.push(parsed ? name : s);
|
|
195
223
|
} else {
|
|
196
224
|
entries.push(name);
|
|
@@ -338,7 +366,7 @@ async function collectSessionLogs(dir, relPrefix, depth, out) {
|
|
|
338
366
|
if (d.isDirectory()) {
|
|
339
367
|
if (SCAN_SKIP_DIRS.has(d.name)) continue;
|
|
340
368
|
await collectSessionLogs(`${dir}/${d.name}`, rel, depth + 1, out);
|
|
341
|
-
} else if (
|
|
369
|
+
} else if (isSessionLogName(d.name)) {
|
|
342
370
|
out.push({ abs: `${dir}/${d.name}`, rel });
|
|
343
371
|
}
|
|
344
372
|
}
|