On OS X, utimes can be used to set birthtime but this is a no-op on Windows, since libuv's fs code for Windows just sets NULL for Creation Time in the SetFileTime call.
The real issue is that there is no proper way to set the birthtime on Windows or OS X or on Linux systems which support it.
Would it be okay to add something like fs.utimes2(path, btime, atime, mtime, callback)?
Perhaps I'm misunderstanding something but the utimes and futimes system calls don't let you alter the birth and change times, only the access and modification times.
I believe OS X will let you change the creation time (but not birth time) through the OS X-specific setattrlist system call. I'm not sure if it's implemented for anything besides HFS.
On Linux, you would have to resort to file system-specific ioctls. I don't think many file systems actually support that, though.
I believe OS X will let you change the creation time (but not birth time) through the OS X-specific setattrlist system call. I'm not sure if it's implemented for anything besides HFS.
Thanks Ben, I didn't know OS X had a separate concept of creation time and birthtime. What is the difference between them?
I think on OS X (and possibly on Linux file systems which already support birthtime), utimes can change the btime if the provided mtime argument is less than the current btime. But one can't use that to set btime properly if the btime is greater than the mtime (which may be the case for a backup program syncing files between different machines with different clocks). So using setattrlist would be much better there. Is that what the SetFile command line tool uses to set the btime on OS X?
Supporting btime on Windows is probably the easiest, as one could pass in a creation time instead of NULL in the current libuv call:
if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m))
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724933(v=vs.85).aspx
It would be really helpful if Node could set btime at least on Windows and OS X which support it, possibly as an extra argument to fs.utimes just before the callback, which would be a no-op on Linux:
fs.utimes(path, atime, mtime, btime, callback)
Then when Linux support comes along (if it does) for setting btime, this could be added, but without blocking the others. The creation time is quite important for Windows users. What do you think?
I didn't know OS X had a separate concept of creation time and birthtime. What is the difference between them?
Argh, can't believe I made that typo. I meant to write change time, not creation time. I retract that comment though; I just checked the XNU sources and it lets you change both birth time and change time.
(To confuse things more, XNU internally calls it create time, not birth time.)
So using setattrlist would be much better there. Is that what the SetFile command line tool uses to set the btime on OS X?
The tool itself calls FSSetCatalogInfo() (which is deprecated as of 10.8) from CoreServices but I think that ends up calling setattrlist() or setxattr().
What do you think?
No strong opinion. I can see how it could be useful but it's arguably outside the scope of libuv because it's not very portable. Can I suggest you open a libuv issue and link to this one?
Looks like this is dependent on https://github.com/libuv/libuv/pull/590 which is a breaking change so will have to wait for libuv 2.0. So this might be a while, I guess...
The PR in libuv has been ready since December 2015.
Is there any way to get this into Node directly without requiring anything from libuv, thereby not having to wait for the next libuv major version? Then, when that comes we can remove the shim from Node?
I am doing this in a native binding at present but it's not possible to have a native binding work with an fd opened by libuv on Windows because of the way _get_osfhandle() is linked (https://github.com/joyent/libuv/issues/1493).
It would really be better if this could be resolved in core.
Is there any way to get this into Node directly without requiring anything from libuv, thereby not having to wait for the next libuv major version? Then, when that comes we can remove the shim from Node?
@jorangreef IMHO It's not impossible. You could open a PR applying https://github.com/libuv/libuv/pull/590 over the libuv version in the node tree (https://github.com/nodejs/node/tree/master/deps/uv) and get a discussion going. If you decide to do so mention me and platform-windows (/cc @refack @nodejs/platform-windows).
Just some background info: AFAICT if it's ABI breaking for libuv, it's ABI breaking for node so it would probably be semver-major. The deadline for integrating majors into node8 has passed (we are in the RC phase, expecting RTM on May 31st), so if it decided to "float a patch" (a.k.a. shim) over libuv, it will only be released in node9, and by that time we might already have libuv2.0.
Thanks @refack
For anyone else interested in this, I have released https://github.com/ronomon/utimes which can set the btime (as well as mtime and/or atime) of a file or directory on Windows and macOS.
Is anyone working on this? Should we add a help wanted label?
There's a PR in libuv waiting on the next major version of libuv.
Blocked by https://github.com/libuv/libuv/pull/590 it seems
https://github.com/libuv/libuv/pull/590 is merged.
I think fs.utimes can change birthtime is a bug.
@hezedu I don't disagree, I found this by accident with failing tests on FreeBSD. But it looks like this is an implementation detail for utime on FreeBSD and working around it could be a problem. Thoughts?
@whitlockjc My linux fs type is ext4. ext4 is not have birthtime. Why nodejs fs.stat is have birthtime? It's not same as shell stat command.
use nodejs fs.stat:

use shell stat:

On operating systems / file systems without birth time support, libuv sets it to the ctime (because something needs to be filled in in the field.)
I suppose libuv could fill in a sentinel value that says "no birth time" (e.g. all bits one) but I don't know if that's a marked improvement. If you (generic you) want to discuss that, please open a libuv issue.
@nodejs/libuv I don't imagine libuv 2 is imminent or anything like that, is it?
@Trott No, see the discussion in libuv/libuv#1597. I'd summarize it as "indefinite."
@bnoordhuis is it possible to backport https://github.com/libuv/libuv/pull/590 to v1.x by storing the new btime value in an existing field?
@cjihrig That could work, uv_req_t.reserved[6] still has space. libuv/libuv#2322 is about to take a nibble out of it though. (Well... 8 to 16 nibbles if we're being pedantically correct.)
There's been no activity on this and it's been blocked indefinitely. Keeping the issue open does not benefit anyone but we also don't want to forget about it. I've added it to a Futures project board so it doesn't get lost.
utimes had failed me while moving to new NodeJS v15 (https://nodejs.org/download/nightly/).
I wrote this exe https://github.com/eladkarako/set_time which accepts unix time and changes all datatimes.
```js
..... require("child_process").execFile;
parse a data from old file's data, into a new Date() call for .getTime();
then (result / 1000).toFixed(0);
pass this to require("child_process").execFile(
,["--target" , file_path_full
,"--set-time-creation" , btime
,....
````
I'm heading into Rust/C++/C alternative for speed. will avoid native compilation on NodeJS from now on. Even java is better.