| var alloc = Buffer.alloc | |
| var ZEROS = '0000000000000000000' | |
| var SEVENS = '7777777777777777777' | |
| var ZERO_OFFSET = '0'.charCodeAt(0) | |
| var USTAR_MAGIC = Buffer.from('ustar\x00', 'binary') | |
| var USTAR_VER = Buffer.from('00', 'binary') | |
| var GNU_MAGIC = Buffer.from('ustar\x20', 'binary') | |
| var GNU_VER = Buffer.from('\x20\x00', 'binary') | |
| var MASK = parseInt('7777', 8) | |
| var MAGIC_OFFSET = 257 | |
| var VERSION_OFFSET = 263 | |
| var clamp = function (index, len, defaultValue) { | |
| if (typeof index !== 'number') return defaultValue | |
| index = ~~index // Coerce to integer. | |
| if (index >= len) return len | |
| if (index >= 0) return index | |
| index += len | |
| if (index >= 0) return index | |
| return 0 | |
| } | |
| var toType = function (flag) { | |
| switch (flag) { | |
| case 0: | |
| return 'file' | |
| case 1: | |
| return 'link' | |
| case 2: | |
| return 'symlink' | |
| case 3: | |
| return 'character-device' | |
| case 4: | |
| return 'block-device' | |
| case 5: | |
| return 'directory' | |
| case 6: | |
| return 'fifo' | |
| case 7: | |
| return 'contiguous-file' | |
| case 72: | |
| return 'pax-header' | |
| case 55: | |
| return 'pax-global-header' | |
| case 27: | |
| return 'gnu-long-link-path' | |
| case 28: | |
| case 30: | |
| return 'gnu-long-path' | |
| } | |
| return null | |
| } | |
| var toTypeflag = function (flag) { | |
| switch (flag) { | |
| case 'file': | |
| return 0 | |
| case 'link': | |
| return 1 | |
| case 'symlink': | |
| return 2 | |
| case 'character-device': | |
| return 3 | |
| case 'block-device': | |
| return 4 | |
| case 'directory': | |
| return 5 | |
| case 'fifo': | |
| return 6 | |
| case 'contiguous-file': | |
| return 7 | |
| case 'pax-header': | |
| return 72 | |
| } | |
| return 0 | |
| } | |
| var indexOf = function (block, num, offset, end) { | |
| for (; offset < end; offset++) { | |
| if (block[offset] === num) return offset | |
| } | |
| return end | |
| } | |
| var cksum = function (block) { | |
| var sum = 8 * 32 | |
| for (var i = 0; i < 148; i++) sum += block[i] | |
| for (var j = 156; j < 512; j++) sum += block[j] | |
| return sum | |
| } | |
| var encodeOct = function (val, n) { | |
| val = val.toString(8) | |
| if (val.length > n) return SEVENS.slice(0, n) + ' ' | |
| else return ZEROS.slice(0, n - val.length) + val + ' ' | |
| } | |
| /* Copied from the node-tar repo and modified to meet | |
| * tar-stream coding standard. | |
| * | |
| * Source: https://github.com/npm/node-tar/blob/51b6627a1f357d2eb433e7378e5f05e83b7aa6cd/lib/header.js#L349 | |
| */ | |
| function parse256 (buf) { | |
| // first byte MUST be either 80 or FF | |
| // 80 for positive, FF for 2's comp | |
| var positive | |
| if (buf[0] === 0x80) positive = true | |
| else if (buf[0] === 0xFF) positive = false | |
| else return null | |
| // build up a base-256 tuple from the least sig to the highest | |
| var tuple = [] | |
| for (var i = buf.length - 1; i > 0; i--) { | |
| var byte = buf[i] | |
| if (positive) tuple.push(byte) | |
| else tuple.push(0xFF - byte) | |
| } | |
| var sum = 0 | |
| var l = tuple.length | |
| for (i = 0; i < l; i++) { | |
| sum += tuple[i] * Math.pow(256, i) | |
| } | |
| return positive ? sum : -1 * sum | |
| } | |
| var decodeOct = function (val, offset, length) { | |
| val = val.slice(offset, offset + length) | |
| offset = 0 | |
| // If prefixed with 0x80 then parse as a base-256 integer | |
| if (val[offset] & 0x80) { | |
| return parse256(val) | |
| } else { | |
| // Older versions of tar can prefix with spaces | |
| while (offset < val.length && val[offset] === 32) offset++ | |
| var end = clamp(indexOf(val, 32, offset, val.length), val.length, val.length) | |
| while (offset < end && val[offset] === 0) offset++ | |
| if (end === offset) return 0 | |
| return parseInt(val.slice(offset, end).toString(), 8) | |
| } | |
| } | |
| var decodeStr = function (val, offset, length, encoding) { | |
| return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString(encoding) | |
| } | |
| var addLength = function (str) { | |
| var len = Buffer.byteLength(str) | |
| var digits = Math.floor(Math.log(len) / Math.log(10)) + 1 | |
| if (len + digits >= Math.pow(10, digits)) digits++ | |
| return (len + digits) + str | |
| } | |
| exports.decodeLongPath = function (buf, encoding) { | |
| return decodeStr(buf, 0, buf.length, encoding) | |
| } | |
| exports.encodePax = function (opts) { // TODO: encode more stuff in pax | |
| var result = '' | |
| if (opts.name) result += addLength(' path=' + opts.name + '\n') | |
| if (opts.linkname) result += addLength(' linkpath=' + opts.linkname + '\n') | |
| var pax = opts.pax | |
| if (pax) { | |
| for (var key in pax) { | |
| result += addLength(' ' + key + '=' + pax[key] + '\n') | |
| } | |
| } | |
| return Buffer.from(result) | |
| } | |
| exports.decodePax = function (buf) { | |
| var result = {} | |
| while (buf.length) { | |
| var i = 0 | |
| while (i < buf.length && buf[i] !== 32) i++ | |
| var len = parseInt(buf.slice(0, i).toString(), 10) | |
| if (!len) return result | |
| var b = buf.slice(i + 1, len - 1).toString() | |
| var keyIndex = b.indexOf('=') | |
| if (keyIndex === -1) return result | |
| result[b.slice(0, keyIndex)] = b.slice(keyIndex + 1) | |
| buf = buf.slice(len) | |
| } | |
| return result | |
| } | |
| exports.encode = function (opts) { | |
| var buf = alloc(512) | |
| var name = opts.name | |
| var prefix = '' | |
| if (opts.typeflag === 5 && name[name.length - 1] !== '/') name += '/' | |
| if (Buffer.byteLength(name) !== name.length) return null // utf-8 | |
| while (Buffer.byteLength(name) > 100) { | |
| var i = name.indexOf('/') | |
| if (i === -1) return null | |
| prefix += prefix ? '/' + name.slice(0, i) : name.slice(0, i) | |
| name = name.slice(i + 1) | |
| } | |
| if (Buffer.byteLength(name) > 100 || Buffer.byteLength(prefix) > 155) return null | |
| if (opts.linkname && Buffer.byteLength(opts.linkname) > 100) return null | |
| buf.write(name) | |
| buf.write(encodeOct(opts.mode & MASK, 6), 100) | |
| buf.write(encodeOct(opts.uid, 6), 108) | |
| buf.write(encodeOct(opts.gid, 6), 116) | |
| buf.write(encodeOct(opts.size, 11), 124) | |
| buf.write(encodeOct((opts.mtime.getTime() / 1000) | 0, 11), 136) | |
| buf[156] = ZERO_OFFSET + toTypeflag(opts.type) | |
| if (opts.linkname) buf.write(opts.linkname, 157) | |
| USTAR_MAGIC.copy(buf, MAGIC_OFFSET) | |
| USTAR_VER.copy(buf, VERSION_OFFSET) | |
| if (opts.uname) buf.write(opts.uname, 265) | |
| if (opts.gname) buf.write(opts.gname, 297) | |
| buf.write(encodeOct(opts.devmajor || 0, 6), 329) | |
| buf.write(encodeOct(opts.devminor || 0, 6), 337) | |
| if (prefix) buf.write(prefix, 345) | |
| buf.write(encodeOct(cksum(buf), 6), 148) | |
| return buf | |
| } | |
| exports.decode = function (buf, filenameEncoding, allowUnknownFormat) { | |
| var typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET | |
| var name = decodeStr(buf, 0, 100, filenameEncoding) | |
| var mode = decodeOct(buf, 100, 8) | |
| var uid = decodeOct(buf, 108, 8) | |
| var gid = decodeOct(buf, 116, 8) | |
| var size = decodeOct(buf, 124, 12) | |
| var mtime = decodeOct(buf, 136, 12) | |
| var type = toType(typeflag) | |
| var linkname = buf[157] === 0 ? null : decodeStr(buf, 157, 100, filenameEncoding) | |
| var uname = decodeStr(buf, 265, 32) | |
| var gname = decodeStr(buf, 297, 32) | |
| var devmajor = decodeOct(buf, 329, 8) | |
| var devminor = decodeOct(buf, 337, 8) | |
| var c = cksum(buf) | |
| // checksum is still initial value if header was null. | |
| if (c === 8 * 32) return null | |
| // valid checksum | |
| if (c !== decodeOct(buf, 148, 8)) throw new Error('Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?') | |
| if (USTAR_MAGIC.compare(buf, MAGIC_OFFSET, MAGIC_OFFSET + 6) === 0) { | |
| // ustar (posix) format. | |
| // prepend prefix, if present. | |
| if (buf[345]) name = decodeStr(buf, 345, 155, filenameEncoding) + '/' + name | |
| } else if (GNU_MAGIC.compare(buf, MAGIC_OFFSET, MAGIC_OFFSET + 6) === 0 && | |
| GNU_VER.compare(buf, VERSION_OFFSET, VERSION_OFFSET + 2) === 0) { | |
| // 'gnu'/'oldgnu' format. Similar to ustar, but has support for incremental and | |
| // multi-volume tarballs. | |
| } else { | |
| if (!allowUnknownFormat) { | |
| throw new Error('Invalid tar header: unknown format.') | |
| } | |
| } | |
| // to support old tar versions that use trailing / to indicate dirs | |
| if (typeflag === 0 && name && name[name.length - 1] === '/') typeflag = 5 | |
| return { | |
| name, | |
| mode, | |
| uid, | |
| gid, | |
| size, | |
| mtime: new Date(1000 * mtime), | |
| type, | |
| linkname, | |
| uname, | |
| gname, | |
| devmajor, | |
| devminor | |
| } | |
| } | |
Xet Storage Details
- Size:
- 7.97 kB
- Xet hash:
- f03794e23c32d7fca7ea4268f1e241ce8a8934c4186ebcf8dfac3ad54b4cba4d
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.