4

One of the properties of the fs.Stats object that is returned when one calls fs.stat is birthtime and birthtimeMs, which I'm assuming is when the file was created.

Stats {
  dev: 2114,
  ino: 48064969,
  mode: 33188,
  nlink: 1,
  uid: 85,
  gid: 100,
  rdev: 0,
  size: 527,
  blksize: 4096,
  blocks: 8,
  atimeMs: 1318289051000.1,
  mtimeMs: 1318289051000.1,
  ctimeMs: 1318289051000.1,
  birthtimeMs: 1318289051000.1,              // this value
  atime: Mon, 10 Oct 2011 23:24:11 GMT,
  mtime: Mon, 10 Oct 2011 23:24:11 GMT,
  ctime: Mon, 10 Oct 2011 23:24:11 GMT,
  birthtime: Mon, 10 Oct 2011 23:24:11 GMT } // and this value all the way down here

I'm wondering whether or not birthtime and birthtimeMs is used and reliably returned in UNIX or Linux and MacOS environments?

oldboy
  • 5,729
  • 6
  • 38
  • 86
  • 1
    I can't give a concrete answer for OSX (although it certainly [looks](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/stat.2.html) like it is supported through the BSD syscall), but as for Linux/Unix, I actually just ran across this issue with NodeJS and had to do a bunch of research to dig up answers - I wrote up a post [here](https://joshuatz.com/posts/2019/unix-linux-file-creation-stamps-aka-birthtime-and-nodejs/). – Joshua T Oct 07 '19 at 04:04
  • 1
    It depends not just on the OS, but on the FS, and quite possibly on some runtimes and libraries in between, and probably on OS versions and FS driver versions. And birthtime isn't the only one that's a problem as access time is often not fully implemented for security reasons, changed time and modified time are not consistently differentiated on non-Unixish OS+FS combos where they're not native, on some combos one of the unimplemented fields contains garbage rather than zero, and some combos abuse changed time to put birth time thinking either ctime means creation time, ... – hippietrail Oct 07 '19 at 04:46
  • 1
    ... that changed time is never used on the platform, or both. Node provides a way to query the OS but not a way for us to query which FS a file is on, so we can't use heuristics to decide, and there is no API in Node to query. Birth time as of some time in 2019 should now be fully propagated through all the layers to make it visible on FS's that support it. I think MacOS supported it because HFS did. I would expect most other Unixish OSs not to support it. I was looking into this for a toy project and have moved on so I don't recall the full details anymore. If you file a node bug I'll follow. – hippietrail Oct 07 '19 at 04:50
  • 1
    @JoshuaT It's just weird because even in the document you linked it says "On filesystems where birthtime is not available, this field holds the ctime instead." So it really doesn't answer the question definitively. – oldboy Oct 07 '19 at 05:07
  • 1
    @hippietrail I'll let you know if I file bug. So is there another way to organize files and or directories by their creation date? Seems like such an essential task... – oldboy Oct 07 '19 at 05:10
  • @BugWhisperer: My toy project started with putting photos in date/time order after transferring them different ways messed with different stat fields. I decided to extract all of the date and time fields I could find from FS and file format metadata and analyse it. What a rabbit hole! I'm always finding neglected areas like this in almost every toy project I start (-: – hippietrail Oct 07 '19 at 05:17
  • @hippietrail The date/time order was messing up when you were transferring them how from where? Curious because I'm working on something that involves all of this right now. – oldboy Oct 07 '19 at 05:21
  • @BugWhisperer: From Android phone to laptop over USB cable. On PC it uses a "virtual FS" protocol called MTP or PTP rather than actually mounting the FAT FS of the phone. The way that's implemented it would give the file a new creation date on the PC. Or something like that. I know I had two ways to do it and each changed a different field, so I couldn't just tell Windows to sort my photos by either field. Sorry I forget some details. Is your project open or private? – hippietrail Oct 07 '19 at 05:27
  • @BugWhisperer: Well two people starred my question so I guess there's at least three of us to pressure Node into fixing the mess (-: – hippietrail Oct 07 '19 at 05:42
  • 1
    @hippietrail lol one of em is me :D yah somebody else had it starred before me. that number will most certainly grow as time passes if the "issue" isnt addressed – oldboy Oct 07 '19 at 05:45
  • @hippietrail [a little more confirmation](https://stackoverflow.com/q/56280115/7543162) – oldboy Oct 07 '19 at 06:17

1 Answers1

2

I'm also curios about this question, so I did a little experiment on macOS and Linux. Here are my observations.

First, create the file:

touch foo

Check the times, birth time is the same as others, which is expected.

> const fs = require("fs")
undefined
> fs.statSync("foo")
Stats {
  ...
  atimeMs: 1643199913195.383,
  mtimeMs: 1643199913195.383,
  ctimeMs: 1643199913195.383,
  birthtimeMs: 1643199913195.383,
  atime: 2022-01-26T12:25:13.195Z,
  mtime: 2022-01-26T12:25:13.195Z,
  ctime: 2022-01-26T12:25:13.195Z,
  birthtime: 2022-01-26T12:25:13.195Z
}

Update the file by echo:

echo bar > foo

Check again, mtime and ctime is updated, birth time remains the same, so far so good.

> fs.statSync("foo")
Stats {
  ...
  atimeMs: 1643199913195.383,
  mtimeMs: 1643199961947.3816,
  ctimeMs: 1643199961947.3816,
  birthtimeMs: 1643199913195.383,
  atime: 2022-01-26T12:25:13.195Z,
  mtime: 2022-01-26T12:26:01.947Z,
  ctime: 2022-01-26T12:26:01.947Z,
  birthtime: 2022-01-26T12:25:13.195Z
}

Edit the file with vi, then check again, something unexpected happens:

> fs.statSync("foo")
Stats {
  ...
  atimeMs: 1643199990663.3806,
  mtimeMs: 1643199990663.3806,
  ctimeMs: 1643199990667.3806,
  birthtimeMs: 1643199990663.3806,
  atime: 2022-01-26T12:26:30.663Z,
  mtime: 2022-01-26T12:26:30.663Z,
  ctime: 2022-01-26T12:26:30.667Z,
  birthtime: 2022-01-26T12:26:30.663Z
}

The birth time and all other times are all updated, it seems that a new file is created! After a little digging, I found out that vim is actually always copy backup files back and forth by default, so the btime is tampered. After I set set backupcopy=yse as instructed, btime is no longer updated.

> fs.statSync("foo")
Stats {
  ...
  atimeMs: 1643201126739.3442,
  mtimeMs: 1643201129323.3442,
  ctimeMs: 1643201129327.3442,
  birthtimeMs: 1643200860799.3528,
  atime: 2022-01-26T12:45:26.739Z,
  mtime: 2022-01-26T12:45:29.323Z,
  ctime: 2022-01-26T12:45:29.327Z,
  birthtime: 2022-01-26T12:41:00.799Z  // not the same as other times
}

It seems that birthtime is stable on macOS Monterey and Ubuntu with 4.15 kernel. But programs like vim which are using backup files will break the functionality, be aware of that.

According to an answer here, btime was added in Linux 4.11.

ospider
  • 9,334
  • 3
  • 46
  • 46