tgz: handle addEntryToPack to error
This commit is contained in:
@@ -34,7 +34,7 @@ function getBackupFilePath(backupConfig, remotePath) {
|
||||
return path.join(rootPath, remotePath + fileType);
|
||||
}
|
||||
|
||||
function addToPack(pack, header, options) {
|
||||
function addEntryToPack(pack, header, options) {
|
||||
assert.strictEqual(typeof pack, 'object');
|
||||
assert.strictEqual(typeof header, 'object');
|
||||
assert.strictEqual(typeof options, 'object'); // { input }
|
||||
@@ -56,6 +56,52 @@ function addToPack(pack, header, options) {
|
||||
});
|
||||
}
|
||||
|
||||
async function addPathToPack(pack, localPath, dataLayout) {
|
||||
assert.strictEqual(typeof pack, 'object');
|
||||
assert(dataLayout instanceof DataLayout, 'dataLayout must be a DataLayout');
|
||||
assert.strictEqual(typeof localPath, 'string');
|
||||
|
||||
const queue = [ localPath ];
|
||||
while (queue.length) {
|
||||
// if (pack.destroyed || outStream.destroyed) break;
|
||||
const dir = queue.shift();
|
||||
debug(`tarPack: processing ${dir}`);
|
||||
const [readdirError, entries] = await safe(fs.promises.readdir(dir, { withFileTypes: true }));
|
||||
if (!entries) {
|
||||
debug(`tarPack: skipping directory ${dir}: ${readdirError.message}`);
|
||||
continue;
|
||||
}
|
||||
const subdirs = [];
|
||||
for (const entry of entries) {
|
||||
const abspath = path.join(dir, entry.name);
|
||||
const headerName = dataLayout.toRemotePath(abspath);
|
||||
if (entry.isFile()) {
|
||||
const [openError, handle] = await safe(fs.promises.open(abspath, 'r'));
|
||||
if (!handle) { debug(`tarPack: skipping file, could not open ${abspath}: ${openError.message}`); continue; }
|
||||
const [statError, stat] = await safe(handle.stat());
|
||||
if (!stat) { debug(`tarPack: skipping file, could not stat ${abspath}: ${statError.message}`); continue; }
|
||||
const header = { name: headerName, type: 'file', mode: stat.mode, size: stat.size, uid: process.getuid(), gid: process.getgid() };
|
||||
if (stat.size > 8589934590 || entry.name.length > 99) header.pax = { size: stat.size };
|
||||
const input = handle.createReadStream({ autoClose: true });
|
||||
await addEntryToPack(pack, header, { input });
|
||||
} else if (entry.isDirectory()) {
|
||||
const header = { name: headerName, type: 'directory', uid: process.getuid(), gid: process.getgid() };
|
||||
subdirs.push(abspath);
|
||||
await addEntryToPack(pack, header, { /* options */ });
|
||||
} else if (entry.isSymbolicLink()) {
|
||||
const [readlinkError, target] = await safe(fs.promises.readlink(abspath));
|
||||
if (!target) { debug(`tarPack: skipping link, could not readlink ${abspath}: ${readlinkError.message}`); continue; }
|
||||
const header = { name: headerName, type: 'symlink', linkname: target, uid: process.getuid(), gid: process.getgid() };
|
||||
await addEntryToPack(pack, header, { /* options */ });
|
||||
} else {
|
||||
debug(`tarPack: ignoring unknown type ${entry.name} ${entry.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
queue.unshift(...subdirs); // add to front of queue and in order of readdir listing
|
||||
}
|
||||
}
|
||||
|
||||
async function tarPack(dataLayout, encryption, uploader, progressCallback) {
|
||||
assert(dataLayout instanceof DataLayout, 'dataLayout must be a DataLayout');
|
||||
assert.strictEqual(typeof encryption, 'object');
|
||||
@@ -81,48 +127,11 @@ async function tarPack(dataLayout, encryption, uploader, progressCallback) {
|
||||
}
|
||||
|
||||
for (const localPath of dataLayout.localPaths()) {
|
||||
const queue = [ localPath ];
|
||||
while (queue.length) {
|
||||
// if (pack.destroyed || outStream.destroyed) break;
|
||||
const dir = queue.shift();
|
||||
debug(`tarPack: processing ${dir}`);
|
||||
const [readdirError, entries] = await safe(fs.promises.readdir(dir, { withFileTypes: true }));
|
||||
if (!entries) {
|
||||
debug(`tarPack: skipping directory ${dir}: ${readdirError.message}`);
|
||||
continue;
|
||||
}
|
||||
const subdirs = [];
|
||||
for (const entry of entries) {
|
||||
const abspath = path.join(dir, entry.name);
|
||||
const headerName = dataLayout.toRemotePath(abspath);
|
||||
if (entry.isFile()) {
|
||||
const [openError, handle] = await safe(fs.promises.open(abspath, 'r'));
|
||||
if (!handle) { debug(`tarPack: skipping file, could not open ${abspath}: ${openError.message}`); continue; }
|
||||
const [statError, stat] = await safe(handle.stat());
|
||||
if (!stat) { debug(`tarPack: skipping file, could not stat ${abspath}: ${statError.message}`); continue; }
|
||||
const header = { name: headerName, type: 'file', mode: stat.mode, size: stat.size, uid: process.getuid(), gid: process.getgid() };
|
||||
if (stat.size > 8589934590 || entry.name.length > 99) header.pax = { size: stat.size };
|
||||
const input = handle.createReadStream({ autoClose: true });
|
||||
await addToPack(pack, header, { input });
|
||||
} else if (entry.isDirectory()) {
|
||||
const header = { name: headerName, type: 'directory', uid: process.getuid(), gid: process.getgid() };
|
||||
await addToPack(pack, header);
|
||||
subdirs.push(abspath);
|
||||
} else if (entry.isSymbolicLink()) {
|
||||
const [readlinkError, target] = await safe(fs.promises.readlink(abspath));
|
||||
if (!target) { debug(`tarPack: skipping link, could not readlink ${abspath}: ${readlinkError.message}`); continue; }
|
||||
const header = { name: headerName, type: 'symlink', linkname: target, uid: process.getuid(), gid: process.getgid() };
|
||||
await addToPack(pack, header);
|
||||
} else {
|
||||
debug(`tarPack: ignoring unknown type ${entry.name} ${entry.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
queue.unshift(...subdirs); // add to front of queue and in order of readdir listing
|
||||
}
|
||||
const [error] = await safe(addPathToPack(pack, localPath, dataLayout), { debug });
|
||||
if (error) break; // the pipeline will error and we will retry the whole packing all over
|
||||
}
|
||||
|
||||
pack.finalize();
|
||||
pack.finalize(); // harmless to call if already in error state
|
||||
|
||||
const [error] = await pipeline; // already wrapped in safe()
|
||||
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `tarPack pipeline error: ${error.message}`);
|
||||
|
||||
Reference in New Issue
Block a user