From 65a040dadd68ca5cb6697c8fd15922f505833a19 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 4 Jun 2020 11:43:50 +0100 Subject: [PATCH] fix: ignore high mode bits passed to constructor The UnixFS Spec says high mode bits not defined in the version of the spec supported by a given implementation should be ignored but also persisted to ensure forwards compatibility. The change here: 1. Ignores high bits passed to the constructor 1. Respects high bits read out of a protobuf though does not expose them 1. Writes high bits back to a protobuf but only if they were read from a protobuf to begin with --- packages/ipfs-unixfs-exporter/package.json | 2 +- packages/ipfs-unixfs-importer/package.json | 2 +- packages/ipfs-unixfs/package.json | 2 +- packages/ipfs-unixfs/src/index.js | 8 ++- .../ipfs-unixfs/test/unixfs-format.spec.js | 61 +++++++++++++++++++ 5 files changed, 70 insertions(+), 5 deletions(-) diff --git a/packages/ipfs-unixfs-exporter/package.json b/packages/ipfs-unixfs-exporter/package.json index 7b79785b..e9ef3b1c 100644 --- a/packages/ipfs-unixfs-exporter/package.json +++ b/packages/ipfs-unixfs-exporter/package.json @@ -36,7 +36,7 @@ "homepage": "https://github.com/ipfs/js-ipfs-unixfs#readme", "devDependencies": { "abort-controller": "^3.0.0", - "aegir": "^21.9.0", + "aegir": "^22.0.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "detect-node": "^2.0.4", diff --git a/packages/ipfs-unixfs-importer/package.json b/packages/ipfs-unixfs-importer/package.json index bbf56d6d..c320eaeb 100644 --- a/packages/ipfs-unixfs-importer/package.json +++ b/packages/ipfs-unixfs-importer/package.json @@ -35,7 +35,7 @@ }, "homepage": "https://github.com/ipfs/js-ipfs-unixfs#readme", "devDependencies": { - "aegir": "^21.9.0", + "aegir": "^22.0.0", "chai": "^4.2.0", "cids": "^0.8.0", "detect-node": "^2.0.4", diff --git a/packages/ipfs-unixfs/package.json b/packages/ipfs-unixfs/package.json index 2e04dac3..e8cd2f1a 100644 --- a/packages/ipfs-unixfs/package.json +++ b/packages/ipfs-unixfs/package.json @@ -35,7 +35,7 @@ }, "homepage": "https://github.com/ipfs/js-ipfs-unixfs#readme", "devDependencies": { - "aegir": "^21.9.0", + "aegir": "^22.0.0", "chai": "^4.2.0", "dirty-chai": "^2.0.1", "nyc": "^15.0.0" diff --git a/packages/ipfs-unixfs/src/index.js b/packages/ipfs-unixfs/src/index.js index 5f77a9c1..ae22d0b8 100644 --- a/packages/ipfs-unixfs/src/index.js +++ b/packages/ipfs-unixfs/src/index.js @@ -129,13 +129,18 @@ class Data { static unmarshal (marshaled) { const decoded = unixfsData.decode(marshaled) - return new Data({ + const data = new Data({ type: types[decoded.Type], data: decoded.hasData() ? decoded.Data : undefined, blockSizes: decoded.blocksizes, mode: decoded.hasMode() ? decoded.mode : undefined, mtime: decoded.hasMtime() ? decoded.mtime : undefined }) + + // make sure we honor the original mode + data._originalMode = decoded.hasMode() ? decoded.mode : undefined + + return data } constructor (...args) { @@ -158,7 +163,6 @@ class Data { this.hashType = hashType this.fanout = fanout this.blockSizes = blockSizes || [] - this._originalMode = mode const parsedMode = parseMode(mode) diff --git a/packages/ipfs-unixfs/test/unixfs-format.spec.js b/packages/ipfs-unixfs/test/unixfs-format.spec.js index e8bf137d..76cbe50f 100644 --- a/packages/ipfs-unixfs/test/unixfs-format.spec.js +++ b/packages/ipfs-unixfs/test/unixfs-format.spec.js @@ -331,6 +331,67 @@ describe('unixfs-format', () => { expect(entry).to.have.property('mode', mode) }) + it('omits default file mode from protobuf', () => { + const entry = new UnixFS({ + type: 'file', + mode: 0o644 + }) + + const marshaled = entry.marshal() + + const protobuf = unixfsData.decode(marshaled) + expect(protobuf.hasMode()).to.be.false() + }) + + it('omits default directory mode from protobuf', () => { + const entry = new UnixFS({ + type: 'directory', + mode: 0o755 + }) + + const marshaled = entry.marshal() + + const protobuf = unixfsData.decode(marshaled) + expect(protobuf.hasMode()).to.be.false() + }) + + it('respects high bits in mode read from buffer', () => { + const mode = 0o0100644 // similar to output from fs.stat + const buf = unixfsData.encode({ + Type: unixfsData.DataType.File, + mode + }) + + const entry = UnixFS.unmarshal(buf) + + // should have truncated mode to bits in the version of the spec this module supports + expect(entry).to.have.property('mode', 0o644) + + const marshaled = entry.marshal() + + const protobuf = unixfsData.decode(marshaled) + expect(protobuf).to.have.property('mode', mode) + }) + + it('ignores high bits in mode passed to constructor', () => { + const mode = 0o0100644 // similar to output from fs.stat + const entry = new UnixFS({ + type: 'file', + mode + }) + + // should have truncated mode to bits in the version of the spec this module supports + expect(entry).to.have.property('mode', 0o644) + + const marshaled = entry.marshal() + const unmarshaled = UnixFS.unmarshal(marshaled) + + expect(unmarshaled).to.have.property('mode', 0o644) + + const protobuf = unixfsData.decode(marshaled) + expect(protobuf.hasMode()).to.be.false() + }) + // figuring out what is this metadata for https://github.com/ipfs/js-ipfs-data-importing/issues/3#issuecomment-182336526 it('metadata', () => { const entry = new UnixFS({