tar
Advanced tools
Comparing version 3.1.15 to 3.2.0
@@ -6,2 +6,3 @@ 'use strict' | ||
const path = require('path') | ||
const chownr = require('chownr') | ||
@@ -27,2 +28,8 @@ class SymlinkError extends Error { | ||
const uid = opt.uid | ||
const gid = opt.gid | ||
const doChown = typeof uid === 'number' && | ||
typeof gid === 'number' && | ||
( uid !== opt.processUid || gid !== opt.processGid ) | ||
const preserve = opt.preserve | ||
@@ -33,3 +40,3 @@ const unlink = opt.unlink | ||
const done = er => { | ||
const done = (er, created) => { | ||
if (er) | ||
@@ -39,3 +46,5 @@ cb(er) | ||
cache.set(dir, true) | ||
if (needChmod) | ||
if (created && doChown) | ||
chownr(created, uid, gid, er => done(er)) | ||
else if (needChmod) | ||
fs.chmod(dir, mode, cb) | ||
@@ -55,16 +64,16 @@ else | ||
const parts = sub.split(/\/|\\/) | ||
mkdir_(cwd, parts, mode, cache, unlink, done) | ||
mkdir_(cwd, parts, mode, cache, unlink, null, done) | ||
} | ||
const mkdir_ = (base, parts, mode, cache, unlink, cb) => { | ||
const mkdir_ = (base, parts, mode, cache, unlink, created, cb) => { | ||
if (!parts.length) | ||
return cb() | ||
return cb(null, created) | ||
const p = parts.shift() | ||
const part = base + '/' + p | ||
if (cache.get(part)) | ||
return mkdir_(part, parts, mode, cache, unlink, cb) | ||
fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cb)) | ||
return mkdir_(part, parts, mode, cache, unlink, created, cb) | ||
fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, created, cb)) | ||
} | ||
const onmkdir = (part, parts, mode, cache, unlink, cb) => er => { | ||
const onmkdir = (part, parts, mode, cache, unlink, created, cb) => er => { | ||
if (er) { | ||
@@ -75,3 +84,3 @@ fs.lstat(part, (statEr, st) => { | ||
else if (st.isDirectory()) | ||
mkdir_(part, parts, mode, cache, unlink, cb) | ||
mkdir_(part, parts, mode, cache, unlink, created, cb) | ||
else if (unlink) | ||
@@ -81,3 +90,3 @@ fs.unlink(part, er => { | ||
return cb(er) | ||
fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cb)) | ||
fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, created, cb)) | ||
}) | ||
@@ -89,4 +98,6 @@ else if (st.isSymbolicLink()) | ||
}) | ||
} else | ||
mkdir_(part, parts, mode, cache, unlink, cb) | ||
} else { | ||
created = created || part | ||
mkdir_(part, parts, mode, cache, unlink, created, cb) | ||
} | ||
} | ||
@@ -101,2 +112,8 @@ | ||
const uid = opt.uid | ||
const gid = opt.gid | ||
const doChown = typeof uid === 'number' && | ||
typeof gid === 'number' && | ||
( uid !== opt.processUid || gid !== opt.processGid ) | ||
const preserve = opt.preserve | ||
@@ -107,4 +124,6 @@ const unlink = opt.unlink | ||
const done = er => { | ||
const done = (created) => { | ||
cache.set(dir, true) | ||
if (created && doChown) | ||
chownr.sync(created, uid, gid) | ||
if (needChmod) | ||
@@ -118,10 +137,8 @@ fs.chmodSync(dir, mode) | ||
if (preserve) { | ||
mkdirp.sync(dir, mode) | ||
cache.set(dir, true) | ||
return | ||
} | ||
if (preserve) | ||
return done(mkdirp.sync(dir, mode)) | ||
const sub = path.relative(cwd, dir) | ||
const parts = sub.split(/\/|\\/) | ||
let created = null | ||
for (let p = parts.shift(), part = cwd; | ||
@@ -136,2 +153,3 @@ p && (part += '/' + p); | ||
fs.mkdirSync(part, mode) | ||
created = created || part | ||
cache.set(part, true) | ||
@@ -146,2 +164,3 @@ } catch (er) { | ||
fs.mkdirSync(part, mode) | ||
created = created || part | ||
cache.set(part, true) | ||
@@ -154,3 +173,3 @@ continue | ||
return done() | ||
return done(created) | ||
} |
@@ -32,2 +32,4 @@ 'use strict' | ||
const DOCHOWN = Symbol('doChown') | ||
const UID = Symbol('uid') | ||
const GID = Symbol('gid') | ||
@@ -54,3 +56,20 @@ class Unpack extends Parser { | ||
if (opt.preserveOwner === undefined) | ||
if (typeof opt.uid === 'number' || typeof opt.gid === 'number') { | ||
// need both or neither | ||
if (typeof opt.uid !== 'number' || typeof opt.gid !== 'number') | ||
throw new TypeError('cannot set owner without number uid and gid') | ||
if (opt.preserveOwner) | ||
throw new TypeError( | ||
'cannot preserve owner in archive and also set owner explicitly') | ||
this.uid = opt.uid | ||
this.gid = opt.gid | ||
this.setOwner = true | ||
} else { | ||
this.uid = null | ||
this.gid = null | ||
this.setOwner = false | ||
} | ||
// default true for root | ||
if (opt.preserveOwner === undefined && typeof opt.uid !== 'number') | ||
this.preserveOwner = process.getuid && process.getuid() === 0 | ||
@@ -60,5 +79,5 @@ else | ||
this.processUid = this.preserveOwner && process.getuid ? | ||
this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ? | ||
process.getuid() : null | ||
this.processGid = this.preserveOwner && process.getgid ? | ||
this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ? | ||
process.getgid() : null | ||
@@ -179,2 +198,6 @@ | ||
mkdir(dir, { | ||
uid: this.uid, | ||
gid: this.gid, | ||
processUid: this.processUid, | ||
processGid: this.processGid, | ||
umask: this.processUmask, | ||
@@ -190,7 +213,24 @@ preserve: this.preservePaths, | ||
[DOCHOWN] (entry) { | ||
// in preserve owner mode, chown if the entry doesn't match process | ||
// in set owner mode, chown if setting doesn't match process | ||
return this.preserveOwner && | ||
( typeof entry.uid === 'number' && entry.uid !== this.processUid || | ||
typeof entry.gid === 'number' && entry.gid !== this.processGid ) | ||
|| | ||
( typeof this.uid === 'number' && this.uid !== this.processUid || | ||
typeof this.gid === 'number' && this.gid !== this.processGid ) | ||
} | ||
[UID] (entry) { | ||
return typeof this.uid === 'number' ? this.uid | ||
: typeof entry.uid === 'number' ? entry.uid | ||
: this.processUid | ||
} | ||
[GID] (entry) { | ||
return typeof this.gid === 'number' ? this.gid | ||
: typeof entry.gid === 'number' ? entry.gid | ||
: this.processGid | ||
} | ||
[FILE] (entry) { | ||
@@ -216,3 +256,3 @@ const mode = entry.mode & 0o7777 || this.fmode | ||
queue.push(cb => | ||
fs.chown(entry.absolute, entry.uid, entry.gid || this.processGid, cb)) | ||
fs.chown(entry.absolute, this[UID](entry), this[GID](entry), cb)) | ||
processQueue() | ||
@@ -245,3 +285,3 @@ }) | ||
queue.push(cb => | ||
fs.chown(entry.absolute, entry.uid, entry.gid || this.processGid, cb)) | ||
fs.chown(entry.absolute, this[UID](entry), this[GID](entry), cb)) | ||
@@ -385,3 +425,3 @@ processQueue() | ||
try { | ||
fs.fchownSync(fd, entry.uid, entry.gid || this.processGid) | ||
fs.fchownSync(fd, this[UID](entry), this[GID](entry)) | ||
} catch (er) {} | ||
@@ -406,3 +446,3 @@ } | ||
try { | ||
fs.chownSync(entry.absolute, entry.uid, entry.gid || this.processGid) | ||
fs.chownSync(entry.absolute, this[UID](entry), this[GID](entry)) | ||
} catch (er) {} | ||
@@ -416,2 +456,6 @@ } | ||
return mkdir.sync(dir, { | ||
uid: this.uid, | ||
gid: this.gid, | ||
processUid: this.processUid, | ||
processGid: this.processGid, | ||
umask: this.processUmask, | ||
@@ -418,0 +462,0 @@ preserve: this.preservePaths, |
@@ -5,3 +5,3 @@ { | ||
"description": "tar for node", | ||
"version": "3.1.15", | ||
"version": "3.2.0", | ||
"repository": { | ||
@@ -20,2 +20,3 @@ "type": "git", | ||
"dependencies": { | ||
"chownr": "^1.0.1", | ||
"minipass": "^2.0.2", | ||
@@ -22,0 +23,0 @@ "minizlib": "^1.0.3", |
@@ -298,2 +298,12 @@ # node-tar | ||
[Alias: `p`] | ||
- `uid` Set to a number to force ownership of all extracted files and | ||
folders, and all implicitly created directories, to be owned by the | ||
specified user id, regardless of the `uid` field in the archive. | ||
Cannot be used along with `preserveOwner`. Requires also setting a | ||
`gid` option. | ||
- `gid` Set to a number to force ownership of all extracted files and | ||
folders, and all implicitly created directories, to be owned by the | ||
specified group id, regardless of the `gid` field in the archive. | ||
Cannot be used along with `preserveOwner`. Requires also setting a | ||
`uid` option. | ||
@@ -558,2 +568,12 @@ The following options are mostly internal, but can be modified in some | ||
windows-compatible values while being unpacked. | ||
- `uid` Set to a number to force ownership of all extracted files and | ||
folders, and all implicitly created directories, to be owned by the | ||
specified user id, regardless of the `uid` field in the archive. | ||
Cannot be used along with `preserveOwner`. Requires also setting a | ||
`gid` option. | ||
- `gid` Set to a number to force ownership of all extracted files and | ||
folders, and all implicitly created directories, to be owned by the | ||
specified group id, regardless of the `gid` field in the archive. | ||
Cannot be used along with `preserveOwner`. Requires also setting a | ||
`uid` option. | ||
@@ -560,0 +580,0 @@ ### class tar.Unpack.Sync |
121908
2758
875
5
+ Addedchownr@^1.0.1
+ Addedchownr@1.1.4(transitive)