summaryrefslogtreecommitdiff
path: root/desktop/node_modules/fs-extra/lib/util/stat.js
diff options
context:
space:
mode:
authorRaindropsSys <raindrops@equestria.dev>2023-10-24 17:43:37 +0200
committerRaindropsSys <raindrops@equestria.dev>2023-10-24 17:43:37 +0200
commitae187b6d75c8079da0be1dc288613bad8466fe61 (patch)
tree5ea0d34185a2270f29ffaa65e1f5258028d7d5d0 /desktop/node_modules/fs-extra/lib/util/stat.js
downloadmist-ae187b6d75c8079da0be1dc288613bad8466fe61.tar.gz
mist-ae187b6d75c8079da0be1dc288613bad8466fe61.tar.bz2
mist-ae187b6d75c8079da0be1dc288613bad8466fe61.zip
Initial commit
Diffstat (limited to 'desktop/node_modules/fs-extra/lib/util/stat.js')
-rw-r--r--desktop/node_modules/fs-extra/lib/util/stat.js172
1 files changed, 172 insertions, 0 deletions
diff --git a/desktop/node_modules/fs-extra/lib/util/stat.js b/desktop/node_modules/fs-extra/lib/util/stat.js
new file mode 100644
index 0000000..350cb9f
--- /dev/null
+++ b/desktop/node_modules/fs-extra/lib/util/stat.js
@@ -0,0 +1,172 @@
+'use strict'
+
+const fs = require('graceful-fs')
+const path = require('path')
+
+const NODE_VERSION_MAJOR_WITH_BIGINT = 10
+const NODE_VERSION_MINOR_WITH_BIGINT = 5
+const NODE_VERSION_PATCH_WITH_BIGINT = 0
+const nodeVersion = process.versions.node.split('.')
+const nodeVersionMajor = Number.parseInt(nodeVersion[0], 10)
+const nodeVersionMinor = Number.parseInt(nodeVersion[1], 10)
+const nodeVersionPatch = Number.parseInt(nodeVersion[2], 10)
+
+function nodeSupportsBigInt () {
+ if (nodeVersionMajor > NODE_VERSION_MAJOR_WITH_BIGINT) {
+ return true
+ } else if (nodeVersionMajor === NODE_VERSION_MAJOR_WITH_BIGINT) {
+ if (nodeVersionMinor > NODE_VERSION_MINOR_WITH_BIGINT) {
+ return true
+ } else if (nodeVersionMinor === NODE_VERSION_MINOR_WITH_BIGINT) {
+ if (nodeVersionPatch >= NODE_VERSION_PATCH_WITH_BIGINT) {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+function getStats (src, dest, cb) {
+ if (nodeSupportsBigInt()) {
+ fs.stat(src, { bigint: true }, (err, srcStat) => {
+ if (err) return cb(err)
+ fs.stat(dest, { bigint: true }, (err, destStat) => {
+ if (err) {
+ if (err.code === 'ENOENT') return cb(null, { srcStat, destStat: null })
+ return cb(err)
+ }
+ return cb(null, { srcStat, destStat })
+ })
+ })
+ } else {
+ fs.stat(src, (err, srcStat) => {
+ if (err) return cb(err)
+ fs.stat(dest, (err, destStat) => {
+ if (err) {
+ if (err.code === 'ENOENT') return cb(null, { srcStat, destStat: null })
+ return cb(err)
+ }
+ return cb(null, { srcStat, destStat })
+ })
+ })
+ }
+}
+
+function getStatsSync (src, dest) {
+ let srcStat, destStat
+ if (nodeSupportsBigInt()) {
+ srcStat = fs.statSync(src, { bigint: true })
+ } else {
+ srcStat = fs.statSync(src)
+ }
+ try {
+ if (nodeSupportsBigInt()) {
+ destStat = fs.statSync(dest, { bigint: true })
+ } else {
+ destStat = fs.statSync(dest)
+ }
+ } catch (err) {
+ if (err.code === 'ENOENT') return { srcStat, destStat: null }
+ throw err
+ }
+ return { srcStat, destStat }
+}
+
+function checkPaths (src, dest, funcName, cb) {
+ getStats(src, dest, (err, stats) => {
+ if (err) return cb(err)
+ const { srcStat, destStat } = stats
+ if (destStat && destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
+ return cb(new Error('Source and destination must not be the same.'))
+ }
+ if (srcStat.isDirectory() && isSrcSubdir(src, dest)) {
+ return cb(new Error(errMsg(src, dest, funcName)))
+ }
+ return cb(null, { srcStat, destStat })
+ })
+}
+
+function checkPathsSync (src, dest, funcName) {
+ const { srcStat, destStat } = getStatsSync(src, dest)
+ if (destStat && destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
+ throw new Error('Source and destination must not be the same.')
+ }
+ 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()
+ if (nodeSupportsBigInt()) {
+ fs.stat(destParent, { bigint: true }, (err, destStat) => {
+ if (err) {
+ if (err.code === 'ENOENT') return cb()
+ return cb(err)
+ }
+ if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
+ return cb(new Error(errMsg(src, dest, funcName)))
+ }
+ return checkParentPaths(src, srcStat, destParent, funcName, cb)
+ })
+ } else {
+ fs.stat(destParent, (err, destStat) => {
+ if (err) {
+ if (err.code === 'ENOENT') return cb()
+ return cb(err)
+ }
+ if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
+ 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 {
+ if (nodeSupportsBigInt()) {
+ destStat = fs.statSync(destParent, { bigint: true })
+ } else {
+ destStat = fs.statSync(destParent)
+ }
+ } catch (err) {
+ if (err.code === 'ENOENT') return
+ throw err
+ }
+ if (destStat.ino && destStat.dev && destStat.ino === srcStat.ino && destStat.dev === srcStat.dev) {
+ throw new Error(errMsg(src, dest, funcName))
+ }
+ return checkParentPathsSync(src, srcStat, destParent, funcName)
+}
+
+// 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
+}