diff options
author | Gar <gar+gh@danger.computer> | 2021-08-26 21:20:59 +0300 |
---|---|---|
committer | Gar <gar+gh@danger.computer> | 2021-08-26 21:20:59 +0300 |
commit | e63a942c685233fa546788981ed9c144220d50e1 (patch) | |
tree | 4115e9ae913ad1b688c35711418a528184c9b337 /node_modules/@npmcli/fs/lib/common/owner.js | |
parent | 7af36bb9f8e5c9facaa8deb114b76368841fbc66 (diff) |
cacache@15.3.0
* feat: introduce @npmcli/fs for tmp dir methods
Diffstat (limited to 'node_modules/@npmcli/fs/lib/common/owner.js')
-rw-r--r-- | node_modules/@npmcli/fs/lib/common/owner.js | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/node_modules/@npmcli/fs/lib/common/owner.js b/node_modules/@npmcli/fs/lib/common/owner.js new file mode 100644 index 000000000..e3468b077 --- /dev/null +++ b/node_modules/@npmcli/fs/lib/common/owner.js @@ -0,0 +1,92 @@ +const { dirname, resolve } = require('path') + +const fileURLToPath = require('./file-url-to-path/index.js') +const fs = require('../fs.js') + +// given a path, find the owner of the nearest parent +const find = async (path) => { + // if we have no getuid, permissions are irrelevant on this platform + if (!process.getuid) { + return {} + } + + // fs methods accept URL objects with a scheme of file: so we need to unwrap + // those into an actual path string before we can resolve it + const resolved = path != null && path.href && path.origin + ? resolve(fileURLToPath(path)) + : resolve(path) + + let stat + + try { + stat = await fs.lstat(resolved) + } finally { + // if we got a stat, return its contents + if (stat) { + return { uid: stat.uid, gid: stat.gid } + } + + // try the parent directory + if (resolved !== dirname(resolved)) { + return find(dirname(resolved)) + } + + // no more parents, never got a stat, just return an empty object + return {} + } +} + +// given a path, uid, and gid update the ownership of the path if necessary +const update = async (path, uid, gid) => { + // nothing to update, just exit + if (uid === undefined && gid === undefined) { + return + } + + try { + // see if the permissions are already the same, if they are we don't + // need to do anything, so return early + const stat = await fs.stat(path) + if (uid === stat.uid && gid === stat.gid) { + return + } + } catch (err) {} + + try { + await fs.chown(path, uid, gid) + } catch (err) {} +} + +// accepts a `path` and the `owner` property of an options object and normalizes +// it into an object with numerical `uid` and `gid` +const validate = async (path, input) => { + let uid + let gid + + if (typeof input === 'string' || typeof input === 'number') { + uid = input + gid = input + } else if (input && typeof input === 'object') { + uid = input.uid + gid = input.gid + } + + if (uid === 'inherit' || gid === 'inherit') { + const owner = await find(path) + if (uid === 'inherit') { + uid = owner.uid + } + + if (gid === 'inherit') { + gid = owner.gid + } + } + + return { uid, gid } +} + +module.exports = { + find, + update, + validate, +} |