Team Ai
Datasetpublic

codekingpro/portable-devtools

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