modern-tar 0.7.3 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/fs/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as normalizeBody, c as LINK, l as SYMLINK, n as createTarPacker, o as DIRECTORY, r as transformHeader, s as FILE, t as createUnpacker } from "../unpacker-BpPBxY8N.js";
1
+ import { a as normalizeBody, c as LINK, l as SYMLINK, n as createTarPacker, o as DIRECTORY, r as transformHeader, s as FILE, t as createUnpacker } from "../unpacker-Dcww6JeE.js";
2
2
  import * as fs from "node:fs/promises";
3
3
  import { cpus } from "node:os";
4
4
  import * as path from "node:path";
@@ -575,11 +575,13 @@ const createPathCache = (destDirPath, options) => {
575
575
  }
576
576
  const parentDir = path.dirname(outPath);
577
577
  switch (type) {
578
- case DIRECTORY:
578
+ case DIRECTORY: {
579
579
  pathConflicts.set(normalizedName, DIRECTORY);
580
- await prepareDirectory(outPath, dmode ?? mode);
580
+ const safeMode = mode ? mode & 511 : void 0;
581
+ await prepareDirectory(outPath, dmode ?? safeMode);
581
582
  if (mtime) await fs.lutimes(outPath, mtime, mtime).catch(() => {});
582
583
  return;
584
+ }
583
585
  case FILE:
584
586
  pathConflicts.set(normalizedName, FILE);
585
587
  await prepareDirectory(parentDir);
@@ -678,8 +680,9 @@ function unpackTar(directoryPath, options = {}) {
678
680
  }
679
681
  const outPath = await opQueue.add(() => pathCache.preparePath(transformedHeader));
680
682
  if (outPath) {
683
+ const safeMode = transformedHeader.mode ? transformedHeader.mode & 511 : void 0;
681
684
  const fileStream = createFileSink(outPath, {
682
- mode: options.fmode ?? transformedHeader.mode ?? void 0,
685
+ mode: options.fmode ?? safeMode,
683
686
  mtime: transformedHeader.mtime ?? void 0
684
687
  });
685
688
  let needsDrain = false;
@@ -108,7 +108,7 @@ function readNumeric(view, offset, size) {
108
108
 
109
109
  //#endregion
110
110
  //#region src/tar/body.ts
111
- const isBodyless = (header) => header.type === DIRECTORY || header.type === SYMLINK || header.type === LINK;
111
+ const isBodyless = (header) => header.type === DIRECTORY || header.type === SYMLINK || header.type === LINK || header.type === "character-device" || header.type === "block-device" || header.type === "fifo";
112
112
  async function normalizeBody(body) {
113
113
  if (body === null || body === void 0) return EMPTY;
114
114
  if (body instanceof Uint8Array) return body;
@@ -120,18 +120,24 @@ async function normalizeBody(body) {
120
120
 
121
121
  //#endregion
122
122
  //#region src/tar/options.ts
123
+ const stripPath = (p, n) => {
124
+ const parts = p.split("/").filter(Boolean);
125
+ return n >= parts.length ? "" : parts.slice(n).join("/");
126
+ };
123
127
  function transformHeader(header, options) {
124
128
  const { strip, filter, map } = options;
125
129
  if (!strip && !filter && !map) return header;
126
130
  const h = { ...header };
127
131
  if (strip && strip > 0) {
128
- const components = h.name.split("/").filter(Boolean);
129
- if (strip >= components.length) return null;
130
- const newName = components.slice(strip).join("/");
132
+ const newName = stripPath(h.name, strip);
133
+ if (!newName) return null;
131
134
  h.name = h.type === DIRECTORY && !newName.endsWith("/") ? `${newName}/` : newName;
132
- if (h.linkname?.startsWith("/")) {
133
- const linkComponents = h.linkname.split("/").filter(Boolean);
134
- h.linkname = strip >= linkComponents.length ? "/" : `/${linkComponents.slice(strip).join("/")}`;
135
+ if (h.linkname) {
136
+ const isAbsolute = h.linkname.startsWith("/");
137
+ if (isAbsolute || h.type === LINK) {
138
+ const stripped = stripPath(h.linkname, strip);
139
+ h.linkname = isAbsolute ? `/${stripped}` || "/" : stripped;
140
+ }
135
141
  }
136
142
  }
137
143
  if (filter?.(h) === false) return null;
@@ -256,6 +262,7 @@ function parseUstarHeader(block, strict) {
256
262
  linkname: readString(block, USTAR_LINKNAME_OFFSET, USTAR_LINKNAME_SIZE)
257
263
  };
258
264
  const magic = readString(block, USTAR_MAGIC_OFFSET, USTAR_MAGIC_SIZE);
265
+ if (isBodyless(header)) header.size = 0;
259
266
  if (magic.trim() === "ustar") {
260
267
  header.uname = readString(block, USTAR_UNAME_OFFSET, USTAR_UNAME_SIZE);
261
268
  header.gname = readString(block, USTAR_GNAME_OFFSET, USTAR_GNAME_SIZE);
@@ -275,8 +282,8 @@ const PAX_MAPPING = {
275
282
  };
276
283
  function parsePax(buffer) {
277
284
  const decoder$1 = new TextDecoder("utf-8");
278
- const overrides = {};
279
- const pax = {};
285
+ const overrides = Object.create(null);
286
+ const pax = Object.create(null);
280
287
  let offset = 0;
281
288
  while (offset < buffer.length) {
282
289
  const spaceIndex = buffer.indexOf(32, offset);
@@ -287,9 +294,8 @@ function parsePax(buffer) {
287
294
  const [key, value] = decoder$1.decode(buffer.subarray(spaceIndex + 1, recordEnd - 1)).split("=", 2);
288
295
  if (key && value !== void 0) {
289
296
  pax[key] = value;
290
- const mapping = PAX_MAPPING[key];
291
- if (mapping) {
292
- const [targetKey, parser] = mapping;
297
+ if (Object.hasOwn(PAX_MAPPING, key)) {
298
+ const [targetKey, parser] = PAX_MAPPING[key];
293
299
  const parsedValue = parser(value);
294
300
  if (typeof parsedValue === "string" || !Number.isNaN(parsedValue)) overrides[targetKey] = parsedValue;
295
301
  }
@@ -641,6 +647,7 @@ function createUnpacker(options = {}) {
641
647
  if (internalHeader.prefix) header.name = `${internalHeader.prefix}/${header.name}`;
642
648
  applyOverrides(header, paxGlobals);
643
649
  applyOverrides(header, nextEntryOverrides);
650
+ if (header.name.endsWith("/") && header.type === FILE) header.type = DIRECTORY;
644
651
  nextEntryOverrides = {};
645
652
  currentEntry = {
646
653
  header,
package/dist/web/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as normalizeBody, i as isBodyless, n as createTarPacker$1, r as transformHeader, t as createUnpacker } from "../unpacker-BpPBxY8N.js";
1
+ import { a as normalizeBody, i as isBodyless, n as createTarPacker$1, r as transformHeader, t as createUnpacker } from "../unpacker-Dcww6JeE.js";
2
2
 
3
3
  //#region src/web/compression.ts
4
4
  function createGzipEncoder() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modern-tar",
3
- "version": "0.7.3",
3
+ "version": "0.7.5",
4
4
  "description": "Zero dependency streaming tar parser and writer for JavaScript.",
5
5
  "author": "Ayuhito <hello@ayuhito.com>",
6
6
  "license": "MIT",