diff --git a/lib/tar/file_stream.js b/lib/tar/file_stream.js index 8f45a05..2fc33df 100644 --- a/lib/tar/file_stream.js +++ b/lib/tar/file_stream.js @@ -19,8 +19,7 @@ class TarFileStream extends stream.Transform { if (sourceType === 'file') { // stat file to get file size - fs.stat(opts.source, (err, stat) => { - if (err) return this.emit('error', err); + fs.promises.stat(opts.source).then(stat => { this.entry = pack.entry({ name: opts.relativePath || path.basename(opts.source), size: stat.size, mode: stat.mode & 0o777 }, err => { if (err) return this.emit('error', err); pack.finalize(); @@ -28,7 +27,7 @@ class TarFileStream extends stream.Transform { const stream = fs.createReadStream(opts.source, opts.fs); stream.on('error', err => this.emit('error', err)); stream.pipe(this); - }); + }).catch(err => this.emit('error', err)); } else if (sourceType === 'buffer') { if (!opts.relativePath) return this.emit('error', 'opts.relativePath is required if opts.source is a buffer'); diff --git a/lib/tar/stream.js b/lib/tar/stream.js index 6e64625..4a31ab3 100644 --- a/lib/tar/stream.js +++ b/lib/tar/stream.js @@ -45,32 +45,28 @@ class TarStream extends BaseStream { } _addFileOrDirEntry(entry, opts) { - fs.stat(entry, (err, stat) => { - if (err) return this.emit('error', err); + fs.promises.stat(entry).then(stat => { if (stat.isDirectory()) return this._addDirEntry(entry, opts); if (stat.isFile()) return this._addFileEntry(entry, opts); const illigalEntryError = new Error('Type is not supported, must be a file path, directory path, file buffer, or a readable stream'); illigalEntryError.name = 'IlligalEntryError'; this.emit('error', illigalEntryError); - }); + }).catch(err => this.emit('error', err)); } _addFileEntry(entry, opts) { // stat file to get file size - fs.stat(entry, (err, stat) => { - if (err) return this.emit('error', err); + fs.promises.stat(entry).then(stat => { const entryStream = this._pack.entry({ name: opts.relativePath || path.basename(entry), size: stat.size, mode: stat.mode & 0o777 }, this._onEntryFinish.bind(this)); const stream = fs.createReadStream(entry, opts.fs); stream.on('error', err => this.emit('error', err)); stream.pipe(entryStream); - }); + }).catch(err => this.emit('error', err)); } _addDirEntry(entry, opts) { - fs.readdir(entry, (err, files) => { - if (err) return this.emit('error', err); - + fs.promises.readdir(entry).then(files => { const relativePath = opts.relativePath || ''; files.forEach(fileOrDir => { const newOpts = utils.clone(opts); @@ -83,7 +79,7 @@ class TarStream extends BaseStream { this.addEntry(path.posix.join(entry, fileOrDir), newOpts); }); this._onEntryFinish(); - }); + }).catch(err => this.emit('error', err)); } _addBufferEntry(entry, opts) { diff --git a/lib/utils.js b/lib/utils.js index 0a85cfc..8d42944 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -52,7 +52,7 @@ async function realpathWithMissingDirectories(dir) { * Check if childPath is within parentPath (prevents path traversal attacks) * @param {string} childPath - The path to check * @param {string} parentPath - The parent directory path - * @returns {boolean} - True if childPath is within parentPath + * @return {boolean} - True if childPath is within parentPath */ function isPathWithinParent(childPath, parentPath) { const normalizedChild = path.resolve(childPath); @@ -225,9 +225,7 @@ exports.makeUncompressFn = StreamClass => { delete opts.strip; return new Promise((resolve, reject) => { - fs.mkdir(destDir, { recursive: true }, err => { - if (err) return reject(err); - + fs.promises.mkdir(destDir, { recursive: true }).then(() => { // Resolve destDir to absolute path for security validation const resolvedDestDir = path.resolve(destDir); // Resolve once for the entire extraction to handle OS-level symlinks @@ -323,7 +321,7 @@ exports.makeUncompressFn = StreamClass => { stream.on('end', next); processEntry(header, stream).catch(reject); }); - }); + }).catch(reject); }); }; }; diff --git a/test/tar/uncompress_stream.test.js b/test/tar/uncompress_stream.test.js index 781687d..8dbadf3 100644 --- a/test/tar/uncompress_stream.test.js +++ b/test/tar/uncompress_stream.test.js @@ -38,10 +38,9 @@ describe('test/tar/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -68,10 +67,9 @@ describe('test/tar/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -102,10 +100,9 @@ describe('test/tar/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name)) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -133,10 +130,9 @@ describe('test/tar/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); diff --git a/test/tgz/uncompress_stream.test.js b/test/tgz/uncompress_stream.test.js index d89fe84..7656a9a 100644 --- a/test/tgz/uncompress_stream.test.js +++ b/test/tgz/uncompress_stream.test.js @@ -38,10 +38,9 @@ describe('test/tgz/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -69,10 +68,9 @@ describe('test/tgz/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -100,10 +98,9 @@ describe('test/tgz/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -134,10 +131,9 @@ describe('test/tgz/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); diff --git a/test/zip/uncompress_stream.test.js b/test/zip/uncompress_stream.test.js index cf2ef56..a683ec2 100644 --- a/test/zip/uncompress_stream.test.js +++ b/test/zip/uncompress_stream.test.js @@ -38,10 +38,9 @@ describe('test/zip/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -78,10 +77,9 @@ describe('test/zip/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -111,10 +109,9 @@ describe('test/zip/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -144,10 +141,9 @@ describe('test/zip/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -206,10 +202,9 @@ describe('test/zip/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } }); @@ -237,10 +232,9 @@ describe('test/zip/uncompress_stream.test.js', () => { .then(next) .catch(done); } else { // directory - fs.mkdir(path.join(destDir, header.name), { recursive: true }, err => { - if (err) return done(err); - stream.resume(); - }); + fs.promises.mkdir(path.join(destDir, header.name), { recursive: true }) + .then(() => stream.resume()) + .catch(done); stream.on('end', next); } });