disk 0.8.0 → 0.8.9

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,381 +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
- // TODO: Read GUID Partition Table Backup
78
- // TODO: Verify GUID Partition Table against backup
79
- ( next ) => {
80
- debug( 'open:read_gpt' )
81
- this.readGPT(( error, gpt ) => {
82
- this.gpt = gpt
83
- next( error )
84
- })
85
- },
86
- // Step 5: Partitions
87
- ( next ) => {
88
-
89
- debug( 'open:init_partitions' )
90
-
91
- var addPartition = ( partition ) => {
92
- if( partition.firstLBA === 0 && partition.lastLBA === 0 )
93
- return void 0
94
- var part = this.partition( partition.firstLBA, partition.lastLBA )
95
- this.partitions.push( part )
96
- }
97
-
98
- if( this.gpt ) {
99
- this.gpt.partitions.forEach( addPartition )
100
- } else if( this.mbr ) {
101
- this.mbr.partitions.forEach( addPartition )
102
- }
103
-
104
- next()
105
-
106
- }
107
- ]
108
-
109
- var run = ( error ) => {
110
- if( error ) return callback.call( this, error )
111
- var task = tasks.shift()
112
- task ? task( run ) : callback.call( this )
113
- }
114
-
115
- run()
116
-
117
- return this
118
-
119
- },
120
-
121
- /**
122
- * Closes the device handle
123
- * @param {Function} callback
124
- */
125
- close: function( callback ) {
126
- var done = callback.bind( this )
127
- debug( 'close' )
128
- this.device.close( done )
129
- return this
130
- },
131
-
132
- /**
133
- * Create a bound-checked slice of the disk
134
- * @param {Number} fromLBA
135
- * @param {Number} toLBA
136
- * @return {Disk.Partition}
137
- */
138
- partition: function( fromLBA, toLBA ) {
139
- return new Disk.Partition( this.device, {
140
- firstLBA: fromLBA,
141
- lastLBA: toLBA,
142
- })
143
- },
144
-
145
- /**
146
- * Returns the EFI System Partition entry, if available
147
- * @return {MBR.Partition}
148
- */
149
- getEFIPart: function() {
150
- return this.mbr && this.mbr.getEFIPart()
151
- },
152
-
153
- /**
154
- * Reads the Master Boot Record from disk
155
- * @param {Function} callback
156
- */
157
- readMBR: function( callback ) {
158
-
159
- var self = this
160
- var done = callback.bind( this )
161
-
162
- this.device.readBlocks( 0, 1, function( error, buffer ) {
163
-
164
- if( error != null ) {
165
- return done( error, null )
166
- }
167
-
168
- try {
169
- self.mbr = Disk.MBR.parse( buffer )
170
- } catch( e ) {
171
- // TODO: Use flags to communicate
172
- // what should be notices / warnings
173
- return done( null, null )
174
- }
175
-
176
- done( null, self.mbr )
177
-
178
- })
179
-
180
- return this
181
-
182
- },
183
-
184
- /**
185
- * Writes the Master Boot Record to disk
186
- * @param {Function} callback
187
- */
188
- writeMBR: function( callback ) {
189
-
190
- var done = callback.bind( this )
191
- var buffer = this.mbr.buffer
192
-
193
- this.device.writeBlocks( 0, buffer, done )
194
-
195
- return this
196
-
197
- },
198
-
199
- /**
200
- * Reads the GUID Partition Table from disk
201
- * @param {Function} callback
202
- */
203
- readGPT: function( lba, callback ) {
204
-
205
- var argv = Array.prototype.slice.call( arguments )
206
-
207
- callback = argv.pop()
208
- lba = argv.pop()
209
-
210
- var self = this
211
- var done = callback.bind( this )
212
- var gpt = null
213
-
214
- if( this.mbr == null ) {
215
- // TODO: Use flags to communicate what should be notices / warnings
216
- // new Error( 'Missing Master Boot Record' )
217
- return done( null, null )
218
- }
219
-
220
- if( lba == null ) {
221
- var efiPart = this.getEFIPart()
222
- if( efiPart ) {
223
- lba = efiPart.firstLBA || 1
224
- } else {
225
- return done( null, null )
226
- }
227
- }
228
-
229
- debug( 'read_gpt', lba )
230
-
231
- // Step 1: Read GUID Partition Table Header
232
- this.device.readBlocks( lba, lba + 1, function( error, buffer ) {
233
-
234
- if( error != null ) {
235
- debug( 'read_gpt:error', e.message )
236
- return done( error, null )
237
- }
238
-
239
- // TODO: Use flags to communicate
240
- // what should be notices / warnings
241
- try {
242
- gpt = new Disk.GPT()
243
- gpt.parseHeader( buffer )
244
- } catch( e ) {
245
- debug( 'read_gpt:header:error', e.message )
246
- return done( null, null )
247
- }
248
-
249
- debug( 'read_gpt:header', gpt )
250
-
251
- // Step 2: Read GUID Partition Table
252
- self.device.readBlocks(
253
- gpt.tableOffset,
254
- gpt.tableOffset + ( gpt.tableSize / self.device.blockSize ),
255
- function( error, buffer ) {
256
-
257
- if( error != null ) {
258
- return done( error, null )
259
- }
260
-
261
- try {
262
- gpt.parseTable( buffer )
263
- } catch( e ) {
264
- // TODO: Use flags to communicate
265
- // what should be notices / warnings
266
- debug( 'read_gpt:table:error', e.message )
267
- return done( e, null )
268
- }
269
-
270
- debug( 'read_gpt:table', gpt.partitions )
271
-
272
- return done( null, gpt )
273
-
274
- }
275
- )
276
-
277
- })
278
-
279
- return this
280
-
281
- },
282
-
283
- /**
284
- * Writes the GUID Partition Table to disk
285
- * @param {Function} callback
286
- */
287
- writeGPT: function( callback ) {
288
-
289
- var done = callback.bind( this )
290
-
291
- if( this.gpt == null || !(this.gpt instanceof Disk.GPT) ) {
292
- return done( new Error( 'Invalid or missing GPT' ) )
293
- }
294
-
295
- var headerBuffer = this.gpt.toBuffer( true, false )
296
- var tableBuffer = this.gpt.toBuffer( false, true )
297
-
298
- var header = Buffer.alloc( this.device.blockSize, 0 )
299
- var tableHeader = Buffer.alloc( this.device.blockSize, 0 )
300
- var table = Buffer.alloc( this.device.blockSize * 31, 0 )
301
-
302
- headerBuffer.copy( header )
303
- tableBuffer.slice( 0, this.gpt.entrySize * 4 ).copy( tableHeader )
304
- tableBuffer.slice( this.gpt.entrySize * 4 ).copy( table )
305
-
306
- // Last LBA of device (not user-space!)
307
- var lastLBA = ( this.device.size / this.device.blockSize ) - 1
308
-
309
- var tasks = [
310
- // Write the GPT header
311
- ( next ) => {
312
- var address = 1
313
- this.device.writeBlocks( address, header, next )
314
- },
315
- // Write the first 4 partition table entries
316
- ( next ) => {
317
- var address = 2
318
- this.device.writeBlocks( address, tableHeader, next )
319
- },
320
- // Write partition table entries 5-128
321
- ( next ) => {
322
- var address = 3
323
- this.device.writeBlocks( address, table, next )
324
- },
325
- // Write the backup GPT header
326
- ( next ) => {
327
- var address = this.gpt.backupLBA || lastLBA - 1
328
- this.device.writeBlocks( address, header, next )
329
- },
330
- // Write the first 4 backup partition table entries
331
- ( next ) => {
332
- var address = this.gpt.backupLBA ?
333
- this.gpt.backupLBA - 34 : lastLBA - 34
334
- this.device.writeBlocks( address, tableHeader, next )
335
- },
336
- // Write backup partition table entries 5-128
337
- ( next ) => {
338
- var address = this.gpt.backupLBA ?
339
- this.gpt.backupLBA - 33 : lastLBA - 33
340
- this.device.writeBlocks( address, table, next )
341
- },
342
- ]
343
-
344
- var run = ( error ) => {
345
- if( error ) return callback.call( this, error )
346
- var task = tasks.shift()
347
- task ? task( run ) : callback.call( this )
348
- }
349
-
350
- run()
351
-
352
- return this
353
- },
354
-
355
- verifyGPT: function( callback ) {
356
-
357
- var self = this
358
- var done = callback.bind( this )
359
-
360
- if( this.gpt == null ) {
361
- debug( 'verify_gpt:missing' )
362
- done( new Error( 'Missing GPT' ) )
363
- return this
364
- }
365
-
366
- debug( 'verify_gpt', this.gpt.backupLBA )
367
-
368
- this.readGPT( this.gpt.backupLBA, function( error, backupGPT ) {
369
- error = error || self.gpt.verify( backupGPT )
370
- debug( 'verify_gpt:error', error.message )
371
- done( error, backupGPT )
372
- })
373
-
374
- return this
375
-
376
- },
377
-
378
- }
379
-
380
- // Exports
381
- 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