forked from dominictarr/fs-reverse
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
81 lines (72 loc) · 2.07 KB
/
index.js
File metadata and controls
81 lines (72 loc) · 2.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
var fs = require('fs')
var from = require('from')
module.exports = function (file, opts) {
var stream, soFar = ''
var matcher = opts && opts.matcher || '\n'
var bufferSize = opts && opts.bufferSize || 1024 * 64
var mode = opts && opts.mode || 438 // 0666
var flags = opts && opts.flags || 'r'
function onError (err) {
stream.emit('error', err)
stream.destroy()
}
var stat, fd, position
if(!/rx?/.test(flags)) throw new Error("only flags 'r' and 'rx' are allowed")
stream = from(function (i, next) {
if(stream.destroyed) return
if(i === 0) {
var c = 2
fs.stat(file, function (err, _stat) {
if(err) return onError(err)
stat = _stat
position = stat.size
if(!--c) read()
})
fs.open(file, flags, mode, function (err, _fd) {
if(err) return onError(err)
fd = _fd
stream.emit('open')
if(!--c) read()
})
} else read()
function read () {
if(stream.destroyed) return
var length = Math.min(bufferSize, position)
var b = new Buffer(length)
position = position - length
fs.read(fd, b, 0, length, position, function (err) {
if(err) return onError(err)
data(b)
if(position > 0) return next()
stream.emit('data', soFar)
stream.emit('end')
stream.destroy()
})
}
function data (buffer) {
soFar = buffer + soFar
var array = soFar.split(matcher)
soFar = array.shift()
while(array.length) {
if(stream.destroyed) return
stream.emit('data', array.pop())
}
}
})
stream.destroy = function () {
if(stream.destroyed) return
stream.readable = false
stream.destroyed = true
stream.ended = true
function close () {
fs.close(fd, function (err) {
if(err) onError(err)
stream.emit('close')
})
}
if(!stream.started) return stream.emit('close')//allow for destroy on first tick.
if(!fd) stream.once('open', close) //destroy before file opens.
else close() //any other situation.
}
return stream
}