c7c7da904288be26d969017cf3c0fd233c8a653f079e6f2067fa264fba2049e0d7642891654280a602ef372c1c0a819998b9a9d7d27788bf8ed02dc7027e9f 4.8 KB

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