Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fs.utimes does not change birthtime on Windows #2600

Closed
jorangreef opened this issue Aug 28, 2015 · 22 comments
Closed

fs.utimes does not change birthtime on Windows #2600

jorangreef opened this issue Aug 28, 2015 · 22 comments
Labels
blocked PRs that are blocked by other issues or PRs. fs Issues and PRs related to the fs subsystem / file system. windows Issues and PRs related to the Windows platform.

Comments

@jorangreef
Copy link
Contributor

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)?

@Fishrock123 Fishrock123 added the fs Issues and PRs related to the fs subsystem / file system. label Aug 28, 2015
@bnoordhuis
Copy link
Member

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.

@jorangreef
Copy link
Contributor Author

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?

@bnoordhuis
Copy link
Member

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?

@Trott
Copy link
Member

Trott commented Apr 5, 2016

Looks like this is dependent on libuv/libuv#590 which is a breaking change so will have to wait for libuv 2.0. So this might be a while, I guess...

@jasnell jasnell added the windows Issues and PRs related to the Windows platform. label Jun 7, 2016
@jorangreef
Copy link
Contributor Author

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 (joyent/libuv#1493).

It would really be better if this could be resolved in core.

@refack
Copy link
Contributor

refack commented May 27, 2017

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 libuv/libuv#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.

@jorangreef
Copy link
Contributor Author

Thanks @refack

@jorangreef
Copy link
Contributor Author

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.

@Trott
Copy link
Member

Trott commented Mar 4, 2018

Is anyone working on this? Should we add a help wanted label?

@jorangreef
Copy link
Contributor Author

There's a PR in libuv waiting on the next major version of libuv.

@joyeecheung
Copy link
Member

Blocked by libuv/libuv#590 it seems

@joyeecheung joyeecheung added the blocked PRs that are blocked by other issues or PRs. label Mar 31, 2018
@whitlockjc
Copy link
Contributor

libuv/libuv#590 is merged.

@joyeecheung joyeecheung removed the blocked PRs that are blocked by other issues or PRs. label May 17, 2018
@cjihrig cjihrig added the blocked PRs that are blocked by other issues or PRs. label May 23, 2018
@hezedu
Copy link

hezedu commented Jun 1, 2018

I think fs.utimes can change birthtime is a bug.

@whitlockjc
Copy link
Contributor

@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?

@hezedu
Copy link

hezedu commented Jun 9, 2018

@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:
fs-stat
use shell stat:
stat

@bnoordhuis
Copy link
Member

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.

@Trott
Copy link
Member

Trott commented Jul 22, 2019

@nodejs/libuv I don't imagine libuv 2 is imminent or anything like that, is it?

@bnoordhuis
Copy link
Member

bnoordhuis commented Jul 22, 2019

@Trott No, see the discussion in libuv/libuv#1597. I'd summarize it as "indefinite."

@cjihrig
Copy link
Contributor

cjihrig commented Jul 22, 2019

@bnoordhuis is it possible to backport libuv/libuv#590 to v1.x by storing the new btime value in an existing field?

@bnoordhuis
Copy link
Member

@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.)

@jasnell
Copy link
Member

jasnell commented Jun 25, 2020

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.

@jasnell jasnell closed this as completed Jun 25, 2020
@ghost

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked PRs that are blocked by other issues or PRs. fs Issues and PRs related to the fs subsystem / file system. windows Issues and PRs related to the Windows platform.
Projects
None yet
Development

No branches or pull requests

10 participants