diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..1bf4514 --- /dev/null +++ b/.npmignore @@ -0,0 +1,3 @@ +test +benchmark +.* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..20fd86b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.10 diff --git a/CHS.js b/CHS.js new file mode 100644 index 0000000..ae634e8 --- /dev/null +++ b/CHS.js @@ -0,0 +1,118 @@ +/** + * CHS constructor + * @param {Object|Buffer} data + */ +function CHS( cylinder, head, sector ) { + + if( !(this instanceof CHS) ) + return new CHS( data ) + + this.cylinder = 0 // [0,1023] + this.head = 0 // [0,255] + this.sector = 0 // [1,63] + + this._buffer = new Buffer([ 0xFE, 0xFF, 0xFF ]) + + if( cylinder instanceof Buffer ) { + this.buffer = data + } else { + this.cylinder = cylinder || 0 + this.head = head || 0 + this.sector = sector || 0 + } + + // Update internal buffer + void this.buffer + +} + +// Exports +module.exports = CHS + +/** + * Set to the CHS of a Logical Block Address + * @param {Number} lba + * @param {Number} hpt Heads per Track + * @param {Number} spt Sectors per Track + */ +CHS.fromLBA = function( lba, hpt, spt ) { + return new CHS().setLBA( lba, hpt, spt ) +} + +/** + * CHS prototype + * @type {Object} + */ +CHS.prototype = { + + constructor: CHS, + + get buffer() { + + var cylinder = this.cylinder & 0xFF + var head = this.head + var sector = ( this.cylinder >> 2 ) & 0xC0 + sector = sector ^ this.sector + + this._buffer[0] = head + this._buffer[1] = sector + this._buffer[2] = cylinder + + return this._buffer.slice() + + }, + + set buffer( value ) { + + if( !(value instanceof Buffer) ) { + throw new TypeError( 'Value must be a buffer' ) + } + + value.copy( this._buffer ) + + this.head = this._buffer[0] + + // Sector in bits 5–0; + // bits 7–6 are high bits of cylinder + this.sector = this._buffer[1] & 0x3F // 00111111b + + // Bits 7-6 from sector & bits 7–0 of cylinder + this.cylinder = ( this._buffer[1] & 0xC0 ) << 2 // 11000000b + this.cylinder = this.cylinder | this._buffer[2] + + }, + + /** + * Set to the CHS of a Logical Block Address + * @param {Number} lba + * @param {Number} hpt Heads per Track + * @param {Number} spt Sectors per Track + */ + setLBA: function( lba, hpt, spt ) { + this.cylinder = ( lba / ( spt * hpt )) | 0 + this.head = ( lba / spt ) % hpt + this.sector = ( lba % spt ) + 1 + return this + }, + + /** + * Get the Logical Block Address corresponding + * to the given disk geometry + * @param {Number} hpt Heads per Track + * @param {Number} spt Sectors per Track + */ + getLBA: function( hpt, spt ) { + return ( this.cylinder * hpt + this.head ) * + spt + ( this.sector - 1 ) + }, + + /** + * @see #getLBA() + * @param {Number} hpt Heads per Track + * @param {Number} spt Sectors per Track + */ + toLBA: function( hpt, spt ) { + return this.getLBA( hpt, spt ) + } + +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..8496762 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,22 @@ + +## License (MIT) + +Copyright (c) 2014 [Jonas Hermsmeier](http://jhermsmeier.de) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..405191c --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# CHS - Cylinder Head Sector Address +[![build status](https://secure.travis-ci.org/jhermsmeier/node-chs.png)](http://travis-ci.org/jhermsmeier/node-chs) +[![NPM version](https://badge.fury.io/js/chs.png)](https://npmjs.org/chs) + + +## Install via [npm](https://npmjs.org) + +```sh +$ npm install chs +``` + + +## Usage + +```js +// Load module +var CHS = require( 'chs' ) +// Create a CHS address +var addr = new CHS( 5, 20, 8 ) +// Properties: +var c = addr.cylinder +var h = addr.head +var s = addr.sector +// Convert to an LBA (Logical Block Address) +var lba = addr.toLBA( headsPerTrack, sectorsPerTrack ) +var lba = addr.toLBA( 12, 32 ) +// Set it to an LBA +addr.setLBA( lba, headsPerTrack, sectorsPerTrack ) +addr.setLBA( 3150, 16, 63 ) +// Get it as a buffer +var buf = addr.buffer +// Set from buffer +addr.buffer = new Buffer([ 0xFE, 0xFF, 0xFF ]) +``` diff --git a/package.json b/package.json new file mode 100644 index 0000000..b771325 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "chs", + "version": "0.1.0", + "license": "MIT", + "description": "Cylinder-Head-Sector Address (CHS)", + "kewords": [], + "author": { + "name": "Jonas Hermsmeier", + "email": "jhermsmeier@gmail.com", + "url": "https://github.com/jhermsmeier" + }, + "main": "CHS", + "scripts": { + "test": "node node_modules/mocha/bin/mocha" + }, + "dependencies": { + + }, + "devDependencies": { + "mocha": "" + }, + "repository": { + "type": "git", + "url": "https://github.com/jhermsmeier/node-chs.git" + }, + "bugs": { + "url": "https://github.com/jhermsmeier/node-chs/issues" + } +} diff --git a/test/chs.js b/test/chs.js new file mode 100644 index 0000000..d281117 --- /dev/null +++ b/test/chs.js @@ -0,0 +1,62 @@ +var assert = require( 'assert' ) +var CHS = require( '../' ) + +describe( 'CHS', function() { + + it( 'should map the right LBAs corresponding to geometry', function() { + + var chs = new CHS( 3, 2, 1 ) + + // For geometry 1020 16 63 of a disk with + // 1028160 sectors CHS 3 2 1 is LBA 3150=(3*16+2)* 63 + assert.equal( chs.toLBA( 16, 63 ), 3150 ) + + // For geometry 1008 4 255 of a disk with + // 1028160 sectors CHS 3 2 1 is LBA 3570=(3*4+2)*255 + assert.equal( chs.toLBA( 4, 255 ), 3570 ) + + // For geometry 64 255 63 of a disk with + // 1028160 sectors CHS 3 2 1 is LBA 48321=(3*255+2)* 63 + assert.equal( chs.toLBA( 255, 63 ), 48321 ) + + // For geometry 2142 15 32 of a disk with + // 1028160 sectors CHS 3 2 1 is LBA 1504=(3*15+2)* 32 + assert.equal( chs.toLBA( 15, 32 ), 1504 ) + + }) + + it( 'should map the right CHS to a given LBA with geometry', function() { + + var chs = new CHS() + + // For geometry 1020 16 63 of a disk with + // 1028160 sectors CHS 3 2 1 is LBA 3150=(3*16+2)* 63 + chs.setLBA( 3150, 16, 63 ) + assert.equal( chs.cylinder, 3 ) + assert.equal( chs.head, 2 ) + assert.equal( chs.sector, 1 ) + + // For geometry 1008 4 255 of a disk with + // 1028160 sectors CHS 3 2 1 is LBA 3570=(3*4+2)*255 + chs.setLBA( 3570, 4, 255 ) + assert.equal( chs.cylinder, 3 ) + assert.equal( chs.head, 2 ) + assert.equal( chs.sector, 1 ) + + // For geometry 64 255 63 of a disk with + // 1028160 sectors CHS 3 2 1 is LBA 48321=(3*255+2)* 63 + chs.setLBA( 48321, 255, 63 ) + assert.equal( chs.cylinder, 3 ) + assert.equal( chs.head, 2 ) + assert.equal( chs.sector, 1 ) + + // For geometry 2142 15 32 of a disk with + // 1028160 sectors CHS 3 2 1 is LBA 1504=(3*15+2)* 32 + chs.setLBA( 1504, 15, 32 ) + assert.equal( chs.cylinder, 3 ) + assert.equal( chs.head, 2 ) + assert.equal( chs.sector, 1 ) + + }) + +}) \ No newline at end of file diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..9e58416 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1 @@ +--reporter=spec