git ssb

0+

cel / pull-tar-extract



Tree: e6f6f8953f02f539bb377ecd4fc0a5eb4db2f900

Files: e6f6f8953f02f539bb377ecd4fc0a5eb4db2f900 / index.js

4115 bytesRaw
1var pull = require('pull-stream')
2var Buffered = require('pull-buffered')
3var xtend = require('xtend')
4var headers = require('./headers')
5
6var mixinPax = function (header, pax) {
7 if (pax.path) header.name = pax.path
8 if (pax.linkpath) header.linkname = pax.linkpath
9 if (pax.size) header.size = parseInt(pax.size, 10)
10 header.pax = pax
11 return header
12}
13
14module.exports = function (opts) {
15 var b = Buffered()
16 var gnuLongPath, gnuLongLinkPath, pax, paxGlobal
17 opts = opts || {}
18 var _cb
19 var ended
20 var locked = false
21
22 function drainOverflow(size, cb) {
23 var len = 512 - (size % 512)
24 if (!len) return cb()
25 b.chunks(len)(null, function (end, data) {
26 if (end && end !== true) return cb(end)
27 cb()
28 })
29 }
30
31 var readNextHeader = b.chunks(512)
32 function readEntry(cb) {
33 if (locked) return _cb = cb
34 if (ended) return cb(ended)
35 readNextHeader(null, function (end, data) {
36 if (end) return cb(ended = end)
37 var header
38 try { header = headers.decode(data, opts.filenameEncoding) }
39 catch (err) { return cb(err) }
40 if (!header) return readEntry(cb)
41
42 if (header.type === 'gnu-long-path') {
43 return b.chunks(header.size)(null, function (end, data) {
44 if (end) return cb(end)
45 gnuLongPath = headers.decodeLongPath(data, opts.filenameEncoding)
46 drainOverflow(header.size, function (err) {
47 if (err) return cb(err)
48 readEntry(cb)
49 })
50 })
51 }
52
53 if (header.type === 'gnu-long-link-path') {
54 return b.chunks(header.size)(null, function (end, data) {
55 if (end) return cb(end)
56 gnuLongLinkPath = headers.decodeLongPath(data, opts.filenameEncoding)
57 drainOverflow(header.size, function (err) {
58 if (err) return cb(err)
59 readEntry(cb)
60 })
61 })
62 }
63
64 if (header.type === 'pax-global-header') {
65 return b.chunks(header.size)(null, function (end, data) {
66 if (end) return cb(end)
67 paxGlobal = headers.decodePax(data)
68 drainOverflow(header.size, function (err) {
69 if (err) return cb(err)
70 readEntry(cb)
71 })
72 })
73 }
74
75 if (header.type === 'pax-header') {
76 return b.chunks(header.size)(null, function (end, data) {
77 if (end) return cb(end)
78 pax = headers.decodePax(data)
79 if (paxGlobal) pax = xtend(paxGlobal, pax)
80 drainOverflow(header.size, function (err) {
81 if (err) return cb(err)
82 readEntry(cb)
83 })
84 })
85 }
86
87 if (gnuLongPath) {
88 header.name = gnuLongPath
89 gnuLongPath = null
90 }
91
92 if (gnuLongLinkPath) {
93 header.linkname = gnuLongLinkPath
94 gnuLongLinkPath = null
95 }
96
97 if (pax) {
98 header = mixinPax(header, pax)
99 pax = null
100 }
101
102 if (!header.size || header.type === 'directory') {
103 return cb(null, {
104 header: header,
105 read: pull.empty()
106 })
107 }
108
109 locked = true
110 var overflow = 512 - header.size % 512
111 var readBody = b.take(header.size)
112 var readOverflow = function () {
113 pull(
114 b.take(overflow),
115 pull.drain(null, function (err) {
116 if (err) ended = err
117 locked = false
118 var cb1
119 if (_cb) {
120 var cb1 = _cb
121 _cb = null
122 readEntry(cb1)
123 }
124 })
125 )
126 }
127 var readBodyWrapped = function (abort, cb) {
128 if (abort) return pull(
129 readBody,
130 pull.drain(null, function (err) {
131 if (err) return cb(err)
132 cb()
133 readOverflow()
134 })
135 )
136 readBody(null, function (end, data) {
137 if (end) readOverflow()
138 cb(end, data)
139 })
140 }
141 cb(null, {
142 header: header,
143 read: readBodyWrapped
144 })
145 })
146 }
147
148 return function (read) {
149 b(read)
150 return function (abort, cb) {
151 if (abort) return read(abort, cb)
152 readEntry(cb)
153 }
154 }
155}
156

Built with git-ssb-web