disk 0.7.1 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/disk.js DELETED
@@ -1,379 +0,0 @@
1
- var debug = require( 'debug' )( 'disk' )
2
-
3
- /**
4
- * Disk
5
- * @class
6
- * @param {BlockDevice} device
7
- * @return {Disk}
8
- */
9
- function Disk( device ) {
10
-
11
- if( !(this instanceof Disk) )
12
- return new Disk( device )
13
-
14
- /** @type {BlockDevice} Device */
15
- this.device = device
16
- /** @type {MBR} Master Boot Record */
17
- this.mbr = null
18
- /** @type {GPT} GUID Partition Table */
19
- this.gpt = null
20
- /** @type {BlockDevice.Partition[]} Partitions */
21
- this.partitions = []
22
-
23
- }
24
-
25
- /**
26
- * Master Boot Record
27
- * @see https://github.com/jhermsmeier/node-mbr
28
- * @constructor
29
- */
30
- Disk.MBR = require( 'mbr' )
31
-
32
- /**
33
- * GUID Partition Table
34
- * @see https://github.com/jhermsmeier/node-gpt
35
- * @constructor
36
- */
37
- Disk.GPT = require( 'gpt' )
38
-
39
- Disk.Partition = require( './partition' )
40
-
41
- /**
42
- * Disk prototype
43
- * @type {Object}
44
- */
45
- Disk.prototype = {
46
-
47
- constructor: Disk,
48
-
49
- /**
50
- * Opens a device handle and attempts
51
- * to read structures from disk
52
- * @param {Function} callback
53
- */
54
- open: function( callback ) {
55
-
56
- var done = callback.bind( this )
57
-
58
- this.mbr = null
59
- this.gpt = null
60
- this.partitions.length = 0
61
-
62
- debug( 'open' )
63
-
64
- var tasks = [
65
- // Step 1: Open handle
66
- ( next ) => {
67
- debug( 'open:device' )
68
- this.device.open( next )
69
- },
70
- // Step 2: Read Master Boot Record
71
- ( next ) => {
72
- debug( 'open:read_mbr' )
73
- this.readMBR( next )
74
- },
75
- // Step 3: Read GUID Partition Table Header
76
- // Step 4: Read GUID Partition Table
77
- ( next ) => {
78
- debug( 'open:read_gpt' )
79
- this.readGPT(( error, gpt ) => {
80
- this.gpt = gpt
81
- next( error )
82
- })
83
- },
84
- // Step 5: Partitions
85
- ( next ) => {
86
-
87
- debug( 'open:init_partitions' )
88
-
89
- var addPartition = ( partition ) => {
90
- if( partition.firstLBA === 0 && partition.lastLBA === 0 )
91
- return void 0
92
- var part = this.partition( partition.firstLBA, partition.lastLBA )
93
- this.partitions.push( part )
94
- }
95
-
96
- if( this.gpt ) {
97
- this.gpt.partitions.forEach( addPartition )
98
- } else if( this.mbr ) {
99
- this.mbr.partitions.forEach( addPartition )
100
- }
101
-
102
- next()
103
-
104
- }
105
- ]
106
-
107
- var run = ( error ) => {
108
- if( error ) return callback.call( this, error )
109
- var task = tasks.shift()
110
- task ? task( run ) : callback.call( this )
111
- }
112
-
113
- run()
114
-
115
- return this
116
-
117
- },
118
-
119
- /**
120
- * Closes the device handle
121
- * @param {Function} callback
122
- */
123
- close: function( callback ) {
124
- var done = callback.bind( this )
125
- debug( 'close' )
126
- this.device.close( done )
127
- return this
128
- },
129
-
130
- /**
131
- * Create a bound-checked slice of the disk
132
- * @param {Number} fromLBA
133
- * @param {Number} toLBA
134
- * @return {Disk.Partition}
135
- */
136
- partition: function( fromLBA, toLBA ) {
137
- return new Disk.Partition( this.device, {
138
- firstLBA: fromLBA,
139
- lastLBA: toLBA,
140
- })
141
- },
142
-
143
- /**
144
- * Returns the EFI System Partition entry, if available
145
- * @return {MBR.Partition}
146
- */
147
- getEFIPart: function() {
148
- return this.mbr && this.mbr.getEFIPart()
149
- },
150
-
151
- /**
152
- * Reads the Master Boot Record from disk
153
- * @param {Function} callback
154
- */
155
- readMBR: function( callback ) {
156
-
157
- var self = this
158
- var done = callback.bind( this )
159
-
160
- this.device.readBlocks( 0, 1, function( error, buffer ) {
161
-
162
- if( error != null ) {
163
- return done( error, null )
164
- }
165
-
166
- try {
167
- self.mbr = Disk.MBR.parse( buffer )
168
- } catch( e ) {
169
- // TODO: Use flags to communicate
170
- // what should be notices / warnings
171
- return done( null, null )
172
- }
173
-
174
- done( null, self.mbr )
175
-
176
- })
177
-
178
- return this
179
-
180
- },
181
-
182
- /**
183
- * Writes the Master Boot Record to disk
184
- * @param {Function} callback
185
- */
186
- writeMBR: function( callback ) {
187
-
188
- var done = callback.bind( this )
189
- var buffer = this.mbr.buffer
190
-
191
- this.device.writeBlocks( 0, buffer, done )
192
-
193
- return this
194
-
195
- },
196
-
197
- /**
198
- * Reads the GUID Partition Table from disk
199
- * @param {Function} callback
200
- */
201
- readGPT: function( lba, callback ) {
202
-
203
- var argv = Array.prototype.slice.call( arguments )
204
-
205
- callback = argv.pop()
206
- lba = argv.pop()
207
-
208
- var self = this
209
- var done = callback.bind( this )
210
- var gpt = null
211
-
212
- if( this.mbr == null ) {
213
- // TODO: Use flags to communicate what should be notices / warnings
214
- // new Error( 'Missing Master Boot Record' )
215
- return done( null, null )
216
- }
217
-
218
- if( lba == null ) {
219
- var efiPart = this.getEFIPart()
220
- if( efiPart ) {
221
- lba = efiPart.firstLBA
222
- } else {
223
- return done( null, null )
224
- }
225
- }
226
-
227
- debug( 'read_gpt', lba )
228
-
229
- // Step 1: Read GUID Partition Table Header
230
- this.device.readBlocks( lba, lba + 1, function( error, buffer ) {
231
-
232
- if( error != null ) {
233
- debug( 'read_gpt:error', e.message )
234
- return done( error, null )
235
- }
236
-
237
- // TODO: Use flags to communicate
238
- // what should be notices / warnings
239
- try {
240
- gpt = new Disk.GPT()
241
- gpt.parseHeader( buffer )
242
- } catch( e ) {
243
- debug( 'read_gpt:header:error', e.message )
244
- return done( null, null )
245
- }
246
-
247
- debug( 'read_gpt:header', gpt )
248
-
249
- // Step 2: Read GUID Partition Table
250
- self.device.readBlocks(
251
- gpt.tableOffset,
252
- gpt.tableOffset + ( gpt.tableSize / self.device.blockSize ),
253
- function( error, buffer ) {
254
-
255
- if( error != null ) {
256
- return done( error, null )
257
- }
258
-
259
- try {
260
- gpt.parseTable( buffer )
261
- } catch( e ) {
262
- // TODO: Use flags to communicate
263
- // what should be notices / warnings
264
- debug( 'read_gpt:table:error', e.message )
265
- return done( e, null )
266
- }
267
-
268
- debug( 'read_gpt:table', gpt.partitions )
269
-
270
- return done( null, gpt )
271
-
272
- }
273
- )
274
-
275
- })
276
-
277
- return this
278
-
279
- },
280
-
281
- /**
282
- * Writes the GUID Partition Table to disk
283
- * @param {Function} callback
284
- */
285
- writeGPT: function( callback ) {
286
-
287
- var done = callback.bind( this )
288
-
289
- if( this.gpt == null || !(this.gpt instanceof Disk.GPT) ) {
290
- return done( new Error( 'Invalid or missing GPT' ) )
291
- }
292
-
293
- var headerBuffer = this.gpt.toBuffer( true, false )
294
- var tableBuffer = this.gpt.toBuffer( false, true )
295
-
296
- var header = Buffer.alloc( this.device.blockSize, 0 )
297
- var tableHeader = Buffer.alloc( this.device.blockSize, 0 )
298
- var table = Buffer.alloc( this.device.blockSize * 31, 0 )
299
-
300
- headerBuffer.copy( header )
301
- tableBuffer.slice( 0, this.gpt.entrySize * 4 ).copy( tableHeader )
302
- tableBuffer.slice( this.gpt.entrySize * 4 ).copy( table )
303
-
304
- // Last LBA of device (not user-space!)
305
- var lastLBA = ( this.device.size / this.device.blockSize ) - 1
306
-
307
- var tasks = [
308
- // Write the GPT header
309
- ( next ) => {
310
- var address = 1
311
- this.device.writeBlocks( address, header, next )
312
- },
313
- // Write the first 4 partition table entries
314
- ( next ) => {
315
- var address = 2
316
- this.device.writeBlocks( address, tableHeader, next )
317
- },
318
- // Write partition table entries 5-128
319
- ( next ) => {
320
- var address = 3
321
- this.device.writeBlocks( address, table, next )
322
- },
323
- // Write the backup GPT header
324
- ( next ) => {
325
- var address = this.gpt.backupLBA || lastLBA - 1
326
- this.device.writeBlocks( address, header, next )
327
- },
328
- // Write the first 4 backup partition table entries
329
- ( next ) => {
330
- var address = this.gpt.backupLBA ?
331
- this.gpt.backupLBA - 34 : lastLBA - 34
332
- this.device.writeBlocks( address, tableHeader, next )
333
- },
334
- // Write backup partition table entries 5-128
335
- ( next ) => {
336
- var address = this.gpt.backupLBA ?
337
- this.gpt.backupLBA - 33 : lastLBA - 33
338
- this.device.writeBlocks( address, table, next )
339
- },
340
- ]
341
-
342
- var run = ( error ) => {
343
- if( error ) return callback.call( this, error )
344
- var task = tasks.shift()
345
- task ? task( run ) : callback.call( this )
346
- }
347
-
348
- run()
349
-
350
- return this
351
- },
352
-
353
- verifyGPT: function( callback ) {
354
-
355
- var self = this
356
- var done = callback.bind( this )
357
-
358
- if( this.gpt == null ) {
359
- debug( 'verify_gpt:missing' )
360
- done( new Error( 'Missing GPT' ) )
361
- return this
362
- }
363
-
364
- debug( 'verify_gpt', this.gpt.backupLBA )
365
-
366
- this.readGPT( this.gpt.backupLBA, function( error, backupGPT ) {
367
- error = error || self.gpt.verify( backupGPT )
368
- debug( 'verify_gpt:error', error.message )
369
- done( error, backupGPT )
370
- })
371
-
372
- return this
373
-
374
- },
375
-
376
- }
377
-
378
- // Exports
379
- module.exports = Disk
package/lib/partition.js DELETED
@@ -1,117 +0,0 @@
1
- var debug = require( 'debug' )( 'disk:partition' )
2
-
3
- /**
4
- * Disk Partition
5
- * @constructor
6
- * @memberOf Disk
7
- * @return {Partition}
8
- */
9
- function Partition( device, options ) {
10
-
11
- if( !(this instanceof Partition) )
12
- return new Partition( device, options )
13
-
14
- this.device = device
15
-
16
- this.firstLBA = options.firstLBA || 0
17
- this.lastLBA = options.lastLBA || -1
18
-
19
- debug( 'new', this.firstLBA, this.lastLBA )
20
-
21
- }
22
-
23
- /**
24
- * Partition Prototype
25
- * @type {Object}
26
- * @ignore
27
- */
28
- Partition.prototype = {
29
-
30
- constructor: Partition,
31
-
32
- /**
33
- * Determine whether a LBA is within the partition's bounds
34
- * @internal
35
- * @param {Number} lba
36
- * @return {Boolean}
37
- */
38
- __OOB: function( lba ) {
39
- return lba < this.firstLBA ||
40
- lba > this.lastLBA
41
- },
42
-
43
- get blockSize() {
44
- return this.device.blockSize
45
- },
46
-
47
- get sectors() {
48
- return this.lastLBA - this.firstLBA
49
- },
50
-
51
- get size() {
52
- return this.sectors * this.blockSize
53
- },
54
-
55
- /**
56
- * Read from a LBA to another LBA
57
- * @param {Number} from
58
- * @param {Number} to
59
- * @param {Buffer} [buffer]
60
- * @param {Function} callback
61
- * @return {Partition}
62
- */
63
- readBlocks: function( from, to, buffer, callback ) {
64
-
65
- if( typeof buffer === 'function' ) {
66
- callback = buffer
67
- buffer = null
68
- }
69
-
70
- callback = callback.bind( this )
71
-
72
- from = from + this.firstLBA
73
- to = to + this.firstLBA
74
-
75
- if( this.__OOB( from ) || this.__OOB( to ) ) {
76
- var msg = 'Block address out of bounds: ' +
77
- '[' + from + ',' + to + '] not in range ' +
78
- '[' + this.firstLBA + ',' + this.lastLBA + ']'
79
- return callback( new Error( msg ) )
80
- }
81
-
82
- this.device.readBlocks( from, to, buffer, callback )
83
-
84
- return this
85
-
86
- },
87
-
88
- /**
89
- * Write a buffer to a given LBA
90
- * @param {Number} from
91
- * @param {Buffer} [buffer]
92
- * @param {Function} callback
93
- * @return {Partition}
94
- */
95
- writeBlocks: function( from, buffer, callback ) {
96
-
97
- callback = callback.bind( this )
98
-
99
- from = from + this.firstLBA
100
-
101
- if( this.__OOB( from ) ) {
102
- var msg = 'Block address out of bounds: ' +
103
- '[' + from + ',' + to + '] not in range ' +
104
- '[' + this.firstLBA + ',' + this.lastLBA + ']'
105
- return callback( new Error( msg ) )
106
- }
107
-
108
- this.device.writeBlocks( from, buffer, callback )
109
-
110
- return this
111
-
112
- },
113
-
114
- }
115
-
116
- // Exports
117
- module.exports = Partition