123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- import { basename } from 'node:path';
- import { Header } from './header.js';
- export class Pax {
- atime;
- mtime;
- ctime;
- charset;
- comment;
- gid;
- uid;
- gname;
- uname;
- linkpath;
- dev;
- ino;
- nlink;
- path;
- size;
- mode;
- global;
- constructor(obj, global = false) {
- this.atime = obj.atime;
- this.charset = obj.charset;
- this.comment = obj.comment;
- this.ctime = obj.ctime;
- this.dev = obj.dev;
- this.gid = obj.gid;
- this.global = global;
- this.gname = obj.gname;
- this.ino = obj.ino;
- this.linkpath = obj.linkpath;
- this.mtime = obj.mtime;
- this.nlink = obj.nlink;
- this.path = obj.path;
- this.size = obj.size;
- this.uid = obj.uid;
- this.uname = obj.uname;
- }
- encode() {
- const body = this.encodeBody();
- if (body === '') {
- return Buffer.allocUnsafe(0);
- }
- const bodyLen = Buffer.byteLength(body);
- // round up to 512 bytes
- // add 512 for header
- const bufLen = 512 * Math.ceil(1 + bodyLen / 512);
- const buf = Buffer.allocUnsafe(bufLen);
- // 0-fill the header section, it might not hit every field
- for (let i = 0; i < 512; i++) {
- buf[i] = 0;
- }
- new Header({
- // XXX split the path
- // then the path should be PaxHeader + basename, but less than 99,
- // prepend with the dirname
- /* c8 ignore start */
- path: ('PaxHeader/' + basename(this.path ?? '')).slice(0, 99),
- /* c8 ignore stop */
- mode: this.mode || 0o644,
- uid: this.uid,
- gid: this.gid,
- size: bodyLen,
- mtime: this.mtime,
- type: this.global ? 'GlobalExtendedHeader' : 'ExtendedHeader',
- linkpath: '',
- uname: this.uname || '',
- gname: this.gname || '',
- devmaj: 0,
- devmin: 0,
- atime: this.atime,
- ctime: this.ctime,
- }).encode(buf);
- buf.write(body, 512, bodyLen, 'utf8');
- // null pad after the body
- for (let i = bodyLen + 512; i < buf.length; i++) {
- buf[i] = 0;
- }
- return buf;
- }
- encodeBody() {
- return (this.encodeField('path') +
- this.encodeField('ctime') +
- this.encodeField('atime') +
- this.encodeField('dev') +
- this.encodeField('ino') +
- this.encodeField('nlink') +
- this.encodeField('charset') +
- this.encodeField('comment') +
- this.encodeField('gid') +
- this.encodeField('gname') +
- this.encodeField('linkpath') +
- this.encodeField('mtime') +
- this.encodeField('size') +
- this.encodeField('uid') +
- this.encodeField('uname'));
- }
- encodeField(field) {
- if (this[field] === undefined) {
- return '';
- }
- const r = this[field];
- const v = r instanceof Date ? r.getTime() / 1000 : r;
- const s = ' ' +
- (field === 'dev' || field === 'ino' || field === 'nlink' ?
- 'SCHILY.'
- : '') +
- field +
- '=' +
- v +
- '\n';
- const byteLen = Buffer.byteLength(s);
- // the digits includes the length of the digits in ascii base-10
- // so if it's 9 characters, then adding 1 for the 9 makes it 10
- // which makes it 11 chars.
- let digits = Math.floor(Math.log(byteLen) / Math.log(10)) + 1;
- if (byteLen + digits >= Math.pow(10, digits)) {
- digits += 1;
- }
- const len = digits + byteLen;
- return len + s;
- }
- static parse(str, ex, g = false) {
- return new Pax(merge(parseKV(str), ex), g);
- }
- }
- const merge = (a, b) => b ? Object.assign({}, b, a) : a;
- const parseKV = (str) => str
- .replace(/\n$/, '')
- .split('\n')
- .reduce(parseKVLine, Object.create(null));
- const parseKVLine = (set, line) => {
- const n = parseInt(line, 10);
- // XXX Values with \n in them will fail this.
- // Refactor to not be a naive line-by-line parse.
- if (n !== Buffer.byteLength(line) + 1) {
- return set;
- }
- line = line.slice((n + ' ').length);
- const kv = line.split('=');
- const r = kv.shift();
- if (!r) {
- return set;
- }
- const k = r.replace(/^SCHILY\.(dev|ino|nlink)/, '$1');
- const v = kv.join('=');
- set[k] =
- /^([A-Z]+\.)?([mac]|birth|creation)time$/.test(k) ?
- new Date(Number(v) * 1000)
- : /^[0-9]+$/.test(v) ? +v
- : v;
- return set;
- };
- //# sourceMappingURL=pax.js.map
|