isaacs / isaacs/node-tar

Link cache collision in write-entry due to erroneous 'ino'

Open
#431 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
922
Forks
281
PR merge metrics
No merged PRs in 30d

Description

I am trying to create an archive with two different files, but one file ends up being (incorrectly) hard linked to the other. I believe this is because node erroneously reports the same 'ino' number for these files. Potentially related to https://github.com/nodejs/node/issues/12115

Here is the code I'm using

            const mfiles = [
                './dist/components/FeatureFilterViewWindow.scss',
                './dist/components/FieldTagsInput.scss'
            ]
            const stream = tar.create(
                {
                    gzip: false,
                    onwarn: (code, message, date) => {
                        console.warn(code, message, date);
                    },
                    filter: (path, stat) => {
                        console.log(path, stat);
                        return true;
                    }
                },
                mfiles
            );

            const writeStream = fs.createWriteStream(packageTarball);
            stream.pipe(writeStream).on('error', (e) => {
                console.error('error', e);
            }).on('finish', () => {
                console.log('finished');
            })

which prints

./dist/components/FeatureFilterViewWindow.scss Stats {
  dev: 204880295,
  mode: 33206,
  nlink: 2,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: 4096,
  ino: 9570149211882252,
  size: 667,
  blocks: 8,
  atimeMs: 1737048571848.961,
  mtimeMs: 1724710432427.687,
  ctimeMs: 1736989116749.4336,
  birthtimeMs: 1734560418984.347,
  atime: 2025-01-16T17:29:31.849Z,
  mtime: 2024-08-26T22:13:52.428Z,
  ctime: 2025-01-16T00:58:36.749Z,
  birthtime: 2024-12-18T22:20:18.984Z
}
./dist/components/FieldTagsInput.scss Stats {
  dev: 204880295,
  mode: 33206,
  nlink: 2,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: 4096,
  ino: 9570149211882252,
  size: 233,
  blocks: 0,
  atimeMs: 1737047555156.3042,
  mtimeMs: 1736987398798.4736,
  ctimeMs: 1736989157564.605,
  birthtimeMs: 1736987481606.987,
  atime: 2025-01-16T17:12:35.156Z,
  mtime: 2025-01-16T00:29:58.798Z,
  ctime: 2025-01-16T00:59:17.565Z,
  birthtime: 2025-01-16T00:31:21.607Z
}
finished

Note that the 'ino' numbers are identical.

which ends up creating an archive that looks like this in 7-zip
Image

I believe using the bigint option for fs.stat can fix the issue.

            mfiles.forEach(file => {
                console.log(file);
                console.log(fs.statSync(file, { bigint: true }));
            });

prints

./dist/components/FeatureFilterViewWindow.scss
BigIntStats {
  dev: 204880295n,
  mode: 33206n,
  nlink: 2n,
  uid: 0n,
  gid: 0n,
  rdev: 0n,
  blksize: 4096n,
  ino: 9570149211882252n,
  size: 667n,
  blocks: 8n,
  atimeMs: 1737048612767n,
  mtimeMs: 1724710432427n,
  ctimeMs: 1736989116749n,
  birthtimeMs: 1734560418984n,
  atimeNs: 1737048612767570500n,
  mtimeNs: 1724710432427686900n,
  ctimeNs: 1736989116749433700n,
  birthtimeNs: 1734560418984347000n,
  atime: 2025-01-16T17:30:12.767Z,
  mtime: 2024-08-26T22:13:52.427Z,
  ctime: 2025-01-16T00:58:36.749Z,
  birthtime: 2024-12-18T22:20:18.984Z
}
./dist/components/FieldTagsInput.scss
BigIntStats {
  dev: 204880295n,
  mode: 33206n,
  nlink: 2n,
  uid: 0n,
  gid: 0n,
  rdev: 0n,
  blksize: 4096n,
  ino: 9570149211882253n,
  size: 233n,
  blocks: 0n,
  atimeMs: 1737047555156n,
  mtimeMs: 1736987398798n,
  ctimeMs: 1736989157564n,
  birthtimeMs: 1736987481606n,
  atimeNs: 1737047555156304200n,
  mtimeNs: 1736987398798473700n,
  ctimeNs: 1736989157564605000n,
  birthtimeNs: 1736987481606987000n,
  atime: 2025-01-16T17:12:35.156Z,
  mtime: 2025-01-16T00:29:58.798Z,
  ctime: 2025-01-16T00:59:17.564Z,
  birthtime: 2025-01-16T00:31:21.606Z
}

where the 'ino' numbers are no longer identical.

node-tar version 7.4.3
Node v18.20.5
Windows 11 Enterprise 23H2

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the write-entry path responsible for caching inode values, then reproduce the issue with the two SCSS paths and compare regular and bigint fs.stat results. Add a regression test covering distinct files whose non-bigint inode values collide, and verify the archive does not represent them as hard links.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.