Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / node-pre-gyp / node_modules / tar / lib / pax.js
1 'use strict'
2 const Buffer = require('./buffer.js')
3 const Header = require('./header.js')
4 const path = require('path')
5
6 class Pax {
7   constructor (obj, global) {
8     this.atime = obj.atime || null
9     this.charset = obj.charset || null
10     this.comment = obj.comment || null
11     this.ctime = obj.ctime || null
12     this.gid = obj.gid || null
13     this.gname = obj.gname || null
14     this.linkpath = obj.linkpath || null
15     this.mtime = obj.mtime || null
16     this.path = obj.path || null
17     this.size = obj.size || null
18     this.uid = obj.uid || null
19     this.uname = obj.uname || null
20     this.dev = obj.dev || null
21     this.ino = obj.ino || null
22     this.nlink = obj.nlink || null
23     this.global = global || false
24   }
25
26   encode () {
27     const body = this.encodeBody()
28     if (body === '')
29       return null
30
31     const bodyLen = Buffer.byteLength(body)
32     // round up to 512 bytes
33     // add 512 for header
34     const bufLen = 512 * Math.ceil(1 + bodyLen / 512)
35     const buf = Buffer.allocUnsafe(bufLen)
36
37     // 0-fill the header section, it might not hit every field
38     for (let i = 0; i < 512; i++) {
39       buf[i] = 0
40     }
41
42     new Header({
43       // XXX split the path
44       // then the path should be PaxHeader + basename, but less than 99,
45       // prepend with the dirname
46       path: ('PaxHeader/' + path.basename(this.path)).slice(0, 99),
47       mode: this.mode || 0o644,
48       uid: this.uid || null,
49       gid: this.gid || null,
50       size: bodyLen,
51       mtime: this.mtime || null,
52       type: this.global ? 'GlobalExtendedHeader' : 'ExtendedHeader',
53       linkpath: '',
54       uname: this.uname || '',
55       gname: this.gname || '',
56       devmaj: 0,
57       devmin: 0,
58       atime: this.atime || null,
59       ctime: this.ctime || null
60     }).encode(buf)
61
62     buf.write(body, 512, bodyLen, 'utf8')
63
64     // null pad after the body
65     for (let i = bodyLen + 512; i < buf.length; i++) {
66       buf[i] = 0
67     }
68
69     return buf
70   }
71
72   encodeBody () {
73     return (
74       this.encodeField('path') +
75       this.encodeField('ctime') +
76       this.encodeField('atime') +
77       this.encodeField('dev') +
78       this.encodeField('ino') +
79       this.encodeField('nlink') +
80       this.encodeField('charset') +
81       this.encodeField('comment') +
82       this.encodeField('gid') +
83       this.encodeField('gname') +
84       this.encodeField('linkpath') +
85       this.encodeField('mtime') +
86       this.encodeField('size') +
87       this.encodeField('uid') +
88       this.encodeField('uname')
89     )
90   }
91
92   encodeField (field) {
93     if (this[field] === null || this[field] === undefined)
94       return ''
95     const v = this[field] instanceof Date ? this[field].getTime() / 1000
96       : this[field]
97     const s = ' ' +
98       (field === 'dev' || field === 'ino' || field === 'nlink'
99        ? 'SCHILY.' : '') +
100       field + '=' + v + '\n'
101     const byteLen = Buffer.byteLength(s)
102     // the digits includes the length of the digits in ascii base-10
103     // so if it's 9 characters, then adding 1 for the 9 makes it 10
104     // which makes it 11 chars.
105     let digits = Math.floor(Math.log(byteLen) / Math.log(10)) + 1
106     if (byteLen + digits >= Math.pow(10, digits))
107       digits += 1
108     const len = digits + byteLen
109     return len + s
110   }
111 }
112
113 Pax.parse = (string, ex, g) => new Pax(merge(parseKV(string), ex), g)
114
115 const merge = (a, b) =>
116   b ? Object.keys(a).reduce((s, k) => (s[k] = a[k], s), b) : a
117
118 const parseKV = string =>
119   string
120     .replace(/\n$/, '')
121     .split('\n')
122     .reduce(parseKVLine, Object.create(null))
123
124 const parseKVLine = (set, line) => {
125   const n = parseInt(line, 10)
126
127   // XXX Values with \n in them will fail this.
128   // Refactor to not be a naive line-by-line parse.
129   if (n !== Buffer.byteLength(line) + 1)
130     return set
131
132   line = line.substr((n + ' ').length)
133   const kv = line.split('=')
134   const k = kv.shift().replace(/^SCHILY\.(dev|ino|nlink)/, '$1')
135   if (!k)
136     return set
137
138   const v = kv.join('=')
139   set[k] = /^([A-Z]+\.)?([mac]|birth|creation)time$/.test(k)
140     ?  new Date(v * 1000)
141     : /^[0-9]+$/.test(v) ? +v
142     : v
143   return set
144 }
145
146 module.exports = Pax