UNPKG

extract-base-iterator

Version:

Base iterator for extract iterators like tar-iterator and zip-iterator

75 lines (74 loc) 3.65 kB
var _process_env_OSTYPE; import fs from 'fs'; import { rm } from 'fs-remove-compat'; import isAbsolute from 'is-absolute'; import mkdirp from 'mkdirp-classic'; import path from 'path'; import Queue from 'queue-cb'; import chmod from './fs/chmod.js'; import chown from './fs/chown.js'; import lutimes from './fs/lutimes.js'; import symlinkWin32 from './fs/symlinkWin32.js'; import { objectAssign } from './shared/index.js'; import safeJoinPath from './shared/safeJoinPath.js'; import stripPath from './shared/stripPath.js'; import validateAttributes from './validateAttributes.js'; import waitForAccess from './waitForAccess.js'; const isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test((_process_env_OSTYPE = process.env.OSTYPE) !== null && _process_env_OSTYPE !== void 0 ? _process_env_OSTYPE : ''); const MANDATORY_ATTRIBUTES = [ 'mode', 'mtime', 'path', 'linkpath' ]; let SymbolicLinkEntry = class SymbolicLinkEntry { create(dest, options, callback) { callback = typeof options === 'function' ? options : callback; options = typeof options === 'function' ? {} : options || {}; if (typeof callback === 'function') { try { const normalizedPath = path.normalize(this.path); const fullPath = safeJoinPath(dest, stripPath(normalizedPath, options)); if (isAbsolute(this.linkpath)) { const err = new Error(`Absolute linkpath rejected: '${this.linkpath}'`); err.code = 'ETRAVERSAL'; throw err; } // Resolve the symlink target against the symlink's own directory and verify it // stays within dest. safeJoinPath throws ETRAVERSAL if it escapes. const targetAbs = path.resolve(path.dirname(fullPath), this.linkpath); safeJoinPath(dest, path.relative(dest, targetAbs)); const normalizedLinkpath = path.relative(path.dirname(fullPath), targetAbs); const linkFullPath = targetAbs; const queue = new Queue(1); if (options.force) { queue.defer((callback)=>{ rm(fullPath, (err)=>{ err && err.code !== 'ENOENT' ? callback(err) : callback(); }); }); } queue.defer((cb)=>mkdirp(path.dirname(fullPath), (err)=>cb(err))); if (isWindows) queue.defer((cb)=>symlinkWin32(linkFullPath, normalizedLinkpath, fullPath, (err)=>cb(err))); else queue.defer((cb)=>fs.symlink(normalizedLinkpath, fullPath, (err)=>cb(err))); queue.defer((cb)=>waitForAccess(fullPath, true, cb)); // noFollow=true for symlinks queue.defer((cb)=>chmod(fullPath, this, options, (err)=>cb(err))); queue.defer((cb)=>chown(fullPath, this, options, (err)=>cb(err))); queue.defer((cb)=>lutimes(fullPath, this, options, (err)=>cb(err))); queue.await(callback); } catch (err) { callback(err); } return; } return new Promise((resolve, reject)=>this.create(dest, options, (err)=>err ? reject(err) : resolve(true))); } destroy() {} constructor(attributes){ validateAttributes(attributes, MANDATORY_ATTRIBUTES); objectAssign(this, attributes); if (this.basename === undefined) this.basename = path.basename(this.path); if (this.type === undefined) this.type = 'symlink'; } }; export { SymbolicLinkEntry as default };