�PNG  IHDR��;���IDATx��ܻn�0���K�� �)(�pA��� ���7�LeG{�� �§㻢|��ذaÆ 6lذaÆ 6lذaÆ 6lom��$^�y���ذag�5bÆ 6lذaÆ 6lذa{���� 6lذaÆ �`����}H�Fkm�,�m����Ӫ���ô�ô!� �x�|'ܢ˟;�E:���9�&ᶒ�}�{�v]�n&�6� �h��_��t�ڠ͵-ҫ���Z;��Z$�.�P���k�ž)�!��o���>}l�eQfJ�T��u і���چ��\��X=8��Rن4`Vw�l�>����n�G�^��i�s��"ms�$�u��i��?w�bs[m�6�K4���O���.�4��%����/����b�C%��t ��M�ז� �-l�G6�mrz2���s�%�9��s@���-�k�9�=���)������k�B5����\��+͂�Zsٲ ��Rn��~G���R���C����� �wIcI��n7jJ���hۛNCS|���j0��8y�iHKֶۛ�k�Ɉ+;Sz������L/��F�*\��Ԕ�#"5��m�2��[S��������=�g��n�a�P�e�ғ�L�� lذaÆ 6l�^k��̱aÆ 6lذaÆ 6lذa;���� �_��ذaÆ 6lذaÆ 6lذaÆ ���R���IEND�B` 'use strict' const fs = require('../fs') const path = require('path') const util = require('util') function getStats (src, dest, opts) { const statFunc = opts.dereference ? (file) => fs.stat(file, { bigint: true }) : (file) => fs.lstat(file, { bigint: true }) return Promise.all([ statFunc(src), statFunc(dest).catch(err => { if (err.code === 'ENOENT') return null throw err }) ]).then(([srcStat, destStat]) => ({ srcStat, destStat })) } function getStatsSync (src, dest, opts) { let destStat const statFunc = opts.dereference ? (file) => fs.statSync(file, { bigint: true }) : (file) => fs.lstatSync(file, { bigint: true }) const srcStat = statFunc(src) try { destStat = statFunc(dest) } catch (err) { if (err.code === 'ENOENT') return { srcStat, destStat: null } throw err } return { srcStat, destStat } } function checkPaths (src, dest, funcName, opts, cb) { util.callbackify(getStats)(src, dest, opts, (err, stats) => { if (err) return cb(err) const { srcStat, destStat } = stats if (destStat) { if (areIdentical(srcStat, destStat)) { const srcBaseName = path.basename(src) const destBaseName = path.basename(dest) if (funcName === 'move' && srcBaseName !== destBaseName && srcBaseName.toLowerCase() === destBaseName.toLowerCase()) { return cb(null, { srcStat, destStat, isChangingCase: true }) } return cb(new Error('Source and destination must not be the same.')) } if (srcStat.isDirectory() && !destStat.isDirectory()) { return cb(new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`)) } if (!srcStat.isDirectory() && destStat.isDirectory()) { return cb(new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`)) } } if (srcStat.isDirectory() && isSrcSubdir(src, dest)) { return cb(new Error(errMsg(src, dest, funcName))) } return cb(null, { srcStat, destStat }) }) } function checkPathsSync (src, dest, funcName, opts) { const { srcStat, destStat } = getStatsSync(src, dest, opts) if (destStat) { if (areIdentical(srcStat, destStat)) { const srcBaseName = path.basename(src) const destBaseName = path.basename(dest) if (funcName === 'move' && srcBaseName !== destBaseName && srcBaseName.toLowerCase() === destBaseName.toLowerCase()) { return { srcStat, destStat, isChangingCase: true } } throw new Error('Source and destination must not be the same.') } if (srcStat.isDirectory() && !destStat.isDirectory()) { throw new Error(`Cannot overwrite non-directory '${dest}' with directory '${src}'.`) } if (!srcStat.isDirectory() && destStat.isDirectory()) { throw new Error(`Cannot overwrite directory '${dest}' with non-directory '${src}'.`) } } if (srcStat.isDirectory() && isSrcSubdir(src, dest)) { throw new Error(errMsg(src, dest, funcName)) } return { srcStat, destStat } } // recursively check if dest parent is a subdirectory of src. // It works for all file types including symlinks since it // checks the src and dest inodes. It starts from the deepest // parent and stops once it reaches the src parent or the root path. function checkParentPaths (src, srcStat, dest, funcName, cb) { const srcParent = path.resolve(path.dirname(src)) const destParent = path.resolve(path.dirname(dest)) if (destParent === srcParent || destParent === path.parse(destParent).root) return cb() fs.stat(destParent, { bigint: true }, (err, destStat) => { if (err) { if (err.code === 'ENOENT') return cb() return cb(err) } if (areIdentical(srcStat, destStat)) { return cb(new Error(errMsg(src, dest, funcName))) } return checkParentPaths(src, srcStat, destParent, funcName, cb) }) } function checkParentPathsSync (src, srcStat, dest, funcName) { const srcParent = path.resolve(path.dirname(src)) const destParent = path.resolve(path.dirname(dest)) if (destParent === srcParent || destParent === path.parse(destParent).root) return let destStat try { destStat = fs.statSync(destParent, { bigint: true }) } catch (err) { if (err.code === 'ENOENT') return throw err } if (areIdentical(srcStat, destStat)) { throw new Error(errMsg(src, dest, funcName)) } return checkParentPathsSync(src, srcStat, destParent, funcName) } function areIdentical (srcStat, destStat) { return destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev } // return true if dest is a subdir of src, otherwise false. // It only checks the path strings. function isSrcSubdir (src, dest) { const srcArr = path.resolve(src).split(path.sep).filter(i => i) const destArr = path.resolve(dest).split(path.sep).filter(i => i) return srcArr.reduce((acc, cur, i) => acc && destArr[i] === cur, true) } function errMsg (src, dest, funcName) { return `Cannot ${funcName} '${src}' to a subdirectory of itself, '${dest}'.` } module.exports = { checkPaths, checkPathsSync, checkParentPaths, checkParentPathsSync, isSrcSubdir, areIdentical }