extract-base-iterator
Version:
Base iterator for extract iterators like tar-iterator and zip-iterator
75 lines (74 loc) • 3.65 kB
JavaScript
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 };