Skip to content

readFile changes ctime #1177

@maritz

Description

@maritz

Calling readFile on a file in memfs changes its ctime attribute when read out again via stat.

Here's an example test (in vitest, but changing it to whatever memfs uses should not be too difficult, right?) I wrote:

import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { vol } from "memfs";
import { setTimeout } from "node:timers/promises";

describe("memfs ctime bug", () => {
  beforeEach(() => {
    vol.fromJSON({
      "/tmp/": null,
    });
  });
  afterEach(() => {
    vol.reset();
  });

  test.fails(
    "memfs fails to have the same ctime after a read-only operation",
    async () => {
      const _fs_ = vol.promises;

      const file = "/tmp/test-memfs-ctime-after-readFile.txt";

      // Create the file if it doesn't exist.
      await _fs_.writeFile(file, "foo");

      // Get the ctime before any changes.
      const initial = (await _fs_.stat(file)).ctimeMs;

      await setTimeout(50); // make sure we're not on the same tick
      // read the file
      await _fs_.readFile(file); // removing this line makes the test pass in both real node fs and memfs

      // Get the ctime again, should be the same then
      const afterWrite = (await _fs_.stat(file)).ctimeMs;

      // but it's not the same, so the test fails
      expect(afterWrite).equal(initial);
    },
  );

  test("real node fs has same ctime after a read-only operation", async () => {
    const _fs_ =
      await vi.importActual<typeof import("node:fs/promises")>(
        "node:fs/promises",
      );

    const file = "/tmp/test-memfs-ctime-after-readFile.txt";

    // Create the file if it doesn't exist.
    await _fs_.writeFile(file, "foo");

    // Get the ctime before any changes.
    const initial = (await _fs_.stat(file)).ctimeMs;

    await setTimeout(50); // make sure we're not on the same tick
    // read the file
    await _fs_.readFile(file); // removing this line makes the test pass in both real node fs and memfs

    // Get the ctime again, should be the same then
    const afterWrite = (await _fs_.stat(file)).ctimeMs;

    // and it is
    expect(afterWrite).equal(initial);
  });
});

The same might be true for mtime, but I didn't test that.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions