-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
SetCreationTime, SetLastAccessTime, SetLastWriteTime Should not open a new stream to obtain a SafeFileHandle #20234
Comments
Is there a plan this problem to be fixed soon? |
@TrabacchinLuigi @kostadinmarinov next step would be for someone to format this as an API proposal as per the example linked in https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md @JeremyKuhne do you have any feedback up front about this? |
I'm ok with us having this functionality, but I'd rather see this as extension methods on SafeFileHandle. This will allow hitting the functionality anytime you have a handle, not just with FileStream. Something like: namespace System.IO
{
public static class FileHandleExtensions
{
public static DateTime GetLastWriteTimeUtc(this SafeFileHandle fileHandle);
public static void SetLastWriteTimeUtc(this SafeFileHandle fileHandle, DateTime time);
// etc...
}
} |
Won't it be better and more consistent with the existing interface, if the methods are part of File class. This class already contains that functionality hidden as internal. We can move the body of the using into that public method and make the current one call it. However, based on my copy-paste experience, I see one problem - __Error.WinIOError(errorCode, path) needs path and we don't have it. I am not so familiar with SafeFileHandle, but I don't see from where we can get it. I also see that it's not good to skip it as it will affect the exception messages. Instead we can change the SafeFileHandle parameter to be FileStream which contains the file path into Name property. It's just a suggestion on that problem. |
@kostadinmarinov I've tried to copy paste the actual implementation and i've end in the same situation where I also like your solution where our extension methods target |
I'm Already using |
This is the full initial API shape we want to review. namespace System.IO
{
public static class FileHandleExtensions
{
public static DateTime GetLastWriteTimeUtc(this SafeFileHandle fileHandle);
public static void SetLastWriteTimeUtc(this SafeFileHandle fileHandle, DateTime time);
public static DateTime GetLastAccessTimeUtc(this SafeFileHandle fileHandle);
public static void SetLastAccessTimeUtc(this SafeFileHandle fileHandle, DateTime time);
public static DateTime GetCreationTimeUtc(this SafeFileHandle fileHandle);
public static void SetCreationTimeUtc(this SafeFileHandle fileHandle, DateTime time);
}
} |
namespace System.IO
{
public static partial class File
{
public static DateTime GetCreationTime(SafeFileHandle fileHandle);
public static DateTime GetCreationTimeUtc(SafeFileHandle fileHandle);
public static DateTime GetLastAccessTime(SafeFileHandle fileHandle);
public static DateTime GetLastAccessTimeUtc(SafeFileHandle fileHandle);
public static DateTime GetLastWriteTime(SafeFileHandle fileHandle);
public static DateTime GetLastWriteTimeUtc(SafeFileHandle fileHandle);
public static void SetCreationTime(SafeFileHandle fileHandle, DateTime creationTime);
public static void SetCreationTimeUtc(SafeFileHandle fileHandle, DateTime creatinTimeUtc);
public static void SetLastAccessTime(SafeFileHandle fileHandle, DateTime lastAccessTime);
public static void SetLastAccessTimeUtc(SafeFileHandle fileHandle, DateTime lastAccessTimeUtc);
public static void SetLastWriteTime(SafeFileHandle fileHandle, DateTime lastWriteTime);
public static void SetLastWriteTimeUtc(SafeFileHandle fileHandle, DateTime lastWriteTimeUtc);
// Seems we should be adding support for these too.
// If we can't make it work, dropping is fine.
public static FileAttributes GetAttributes(SafeFileHandle fileHandle);
public static void SetAttributes(SafeFileHandle fileHandle, FileAttributes fileAttributes);
}
} |
Any volunteers interested in adding these? |
They could be extension methods on |
There is an advantage to putting these on
|
We don't define any extension methods in the
Is there a key scenario where avoiding flushing is necessary? Given that |
I avoided replying till now because i have absolutely zero experience on maintaining a framework. I see no weirdness in using SafeFileHandle extensions, what really matter to me is not getting an exception doing it, i don't want to give up the handle to that file and be able to set those values. Just to give some context i had to do that because i'm writing an usermode filesystem, so my code get's called by a driver and it expect to be able to do that. |
Given this is primarily a performance optimisation - a 66% syscall reduction going from Resetting the stream position to 0 is what I'm be more worried about - that's surprising and could potentially cause data loss if mixing Read/Write and SetXx() calls. Unlikely, I guess?
I think that would be a separate issue about getting Try*/result-code-returning versions of most of System.IO? I'm surprised I can't find an issue for that already actually. |
Sorry i think i mis-phrased that. The exception was not the issue (but i agree, exception workflow isn't so great, and alternative methods would be nice), the issue was that wasn't possible without closing the filestream first . |
|
Accessing the |
Do you have a repro for .NET Core? Looking at the code, that doesn't seem intentional. Rather, it should merely validate that you haven't advanced the underlying file pointer that is backed by the file handle by calling OS APIs yourself. |
Indeed, it seems the docs are wrong. |
Cool, sanity restored 😀 I’ll file a doc bug. |
Ok so reading a bit more, it also sets |
Yes, but it uses |
Ahh, right I have no idea what the docs mean then. It's still an extra syscall though. |
I would like to implement this :). If you want you can assign me the issue 😄 |
Hi @deeprobin , it would be awesome! Please open a pull request when you are ready and ping me directly:) I would be glad to review your code ! |
API Proposal
Original post
I know that in many cases it is ok to do so, but we found ourself in the case where we need to set file times without closing the actual
FileStream
, and this is possible via Windows API.To do so we had to write unsafe code which mimic the functionality of the existing functions.
(which include rewriting
System.IO.__Error.WinIOError()
, this is obviusly a bad thing, because we have to maintain code wich already exist)This could be extremely more usable and maintainable if the framework exposed those methods as
SafeFileHandle
Method/ExtensionMethod.My proposal is to leave those functions unaltered but move the actual implementation in an ipotetic function:
SafeFileHandle.SetFileTimesUtc(DateTime? creationTimeUtc, DateTime? lastAccessTimeUtc, DateTime? lastWriteTimeUtc)
which should be public.The text was updated successfully, but these errors were encountered: