diff --git a/lib/image-stream/gzip.js b/lib/image-stream/gzip.js new file mode 100644 index 00000000..287a3bf9 --- /dev/null +++ b/lib/image-stream/gzip.js @@ -0,0 +1,74 @@ +/* + * Copyright 2016 resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const Bluebird = require('bluebird'); +const fs = Bluebird.promisifyAll(require('fs')); + +/** + * @summary The byte length of ISIZE + * @type {Number} + * @constant + * @description + * See https://tools.ietf.org/html/rfc1952 + */ +const ISIZE_LENGTH = 4; + +/** + * @summary Get a gzip file uncompressed size + * @function + * @public + * + * @description + * This function determines the uncompressed size of the gzip file + * by reading its `ISIZE`. The specification clarifies that this + * value is just an estimation. + * + * @param {String} file - path to gzip file + * @fulfil {Number} - uncompressed size + * @returns {Promise} + * + * @example + * gzip.getUncompressedSize('path/to/file.gz').then((uncompressedSize) => { + * console.log(`The uncompressed size is: ${uncompressedSize}`); + * }); + */ +exports.getUncompressedSize = (file) => { + return Bluebird.using(fs.openAsync(file, 'r').disposer((fileDescriptor) => { + return fs.closeAsync(fileDescriptor); + }), (fileDescriptor) => { + return fs.fstatAsync(fileDescriptor).then((stats) => { + const ISIZE_BUFFER_FILL_VALUE = 0; + const ISIZE_BUFFER_START = 0; + const isizeBuffer = Buffer.alloc(ISIZE_LENGTH, ISIZE_BUFFER_FILL_VALUE); + + return fs.readAsync( + fileDescriptor, + isizeBuffer, + ISIZE_BUFFER_START, + ISIZE_LENGTH, + stats.size - ISIZE_LENGTH + ).then((bytesRead) => { + if (bytesRead !== ISIZE_LENGTH) { + throw new Error(`Bytes read mismatch: ${bytesRead} != ${ISIZE_LENGTH}`); + } + + return isizeBuffer.readUInt32LE(ISIZE_BUFFER_START); + }); + }); + }); +}; diff --git a/lib/image-stream/handlers.js b/lib/image-stream/handlers.js index 3ee3e7bd..5e3ee73a 100644 --- a/lib/image-stream/handlers.js +++ b/lib/image-stream/handlers.js @@ -22,7 +22,7 @@ const PassThroughStream = require('stream').PassThrough; const lzma = Bluebird.promisifyAll(require('lzma-native')); const zlib = require('zlib'); const unbzip2Stream = require('unbzip2-stream'); -const gzipUncompressedSize = Bluebird.promisifyAll(require('gzip-uncompressed-size')); +const gzip = require('./gzip'); const archive = require('./archive'); const zipArchiveHooks = require('./archive-hooks/zip'); @@ -74,7 +74,7 @@ module.exports = { * @returns {Promise} */ 'application/gzip': (file, options) => { - return gzipUncompressedSize.fromFileAsync(file).then((uncompressedSize) => { + return gzip.getUncompressedSize(file).then((uncompressedSize) => { return Bluebird.props({ stream: fs.createReadStream(file), size: { diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index bf9e7c56..8e5c81d9 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -374,7 +374,8 @@ "async": { "version": "2.0.0", "from": "async@>=2.0.0-rc.2 <3.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.0.0.tgz" + "resolved": "https://registry.npmjs.org/async/-/async-2.0.0.tgz", + "dev": true }, "async-foreach": { "version": "0.1.3", @@ -684,11 +685,6 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "dev": true }, - "bufferpack": { - "version": "0.0.6", - "from": "bufferpack@0.0.6", - "resolved": "https://registry.npmjs.org/bufferpack/-/bufferpack-0.0.6.tgz" - }, "buffers": { "version": "0.1.1", "from": "buffers@>=0.1.1 <0.2.0", @@ -2895,11 +2891,6 @@ "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", "dev": true }, - "gzip-uncompressed-size": { - "version": "1.0.0", - "from": "gzip-uncompressed-size@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.com/gzip-uncompressed-size/-/gzip-uncompressed-size-1.0.0.tgz" - }, "handlebars": { "version": "4.0.6", "from": "handlebars@>=4.0.5 <5.0.0", diff --git a/package.json b/package.json index 89679b5f..c840c310 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,6 @@ "etcher-latest-version": "^1.0.0", "flat": "^2.0.1", "flexboxgrid": "^6.3.0", - "gzip-uncompressed-size": "^1.0.0", "immutable": "^3.8.1", "is-elevated": "^2.0.1", "lodash": "^4.5.1",