-
Notifications
You must be signed in to change notification settings - Fork 64
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
Add WindwowsString/WindowsFilePath support wrt AFPP #198
Conversation
Thanks for the PR! Can I ask you to split it into two commits? One for the refactoring for the extraction to the internal functions and one for the new functions. They can still be in the same PR, I can just more easily filter away the refactoring changes. I'm away till Friday so will do a more indepth review then, on first glance it looks great though! |
Also, |
Also for your create flags here https://github.com/hasufell/file-io/blob/master/System/File/AbstractFilePath/Windows.hs#L20 you'll want to add You can also conditionally add the flag depending on which I/O manager is in use, see https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.0#io-manager-winio-related-changes |
Also which format will |
Also there's a small bug with
So you have to reset the file size after opening it https://github.com/ghc/ghc/blob/378c0bba7d132a89dd9c35374b7b4bb5a4730bf7/libraries/base/GHC/IO/Windows/Handle.hsc#L856 otherwise the file won't be truncated on write. for |
newtype WindowsString = WS { unWFP :: BS.ShortByteString } It's a unfoldr :: (a -> Maybe (Word16, a)) -> a -> ShortByteString ...so we don't do any conversion whatsoever.
We then use the specialized functions: useAsCWString :: ShortByteString -> (Ptr Word16 -> IO a) -> IO a The endgoal then is for the user to use #if defined(mingw32_HOST_OS) || defined(__MINGW32__)
type PlatformString = WindowsString
#else
type PlatformString = PosixString
#endif
newtype AbstractFilePath = AbstractFilePath PlatformString which has this nice trick that you can't unpack |
I also want to note that another way to do this PR is heavy use of CPP and then |
The format is not specified. Does |
It does not expect it, but it accepts it. Without using a device path you'll regress the toolchain's long path support. GHC has internally mapped to device paths when the API supports it for many releases now. |
Doesn't that cause problems, because we're disabling filepath interpretation? E.g. Or put another way: is there safe way to convert arbitrary paths to Edit: |
No, because when users use
The reason we do this is so that users can give ANY path to the compiler and have it work. The user shouldn't have to do We in GHC decided to make this work out of the box because of things like cabal new-build that produce very long normal This isn't about AFPP or whatever. You're overriding openFile in an external module and not adhering to what the expectations are. If the user has to input I don't particularly care what the library does or does not do with it's PATHs. I care about the fact that you're affecting the behavior of the I/O system in an external module that presumably will be part of a boot library.
Correct. This path is almost non-existent in the real world, Very few people know what it does. Supporting this very arcane path does not warrant regressing the compiler's long path support for the vast majority of users. I'm pretty sure the conversion would fail for that path anyway so we'd use it as is. |
Can you point me to the code where the conversion is done? |
https://github.com/ghc/ghc/blob/0619fb0fb14a98f04aac5f031f6566419fd27495/utils/fs/fs.c#L48 |
I think this is not needed, because we use The documentation says:
https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea From my tests, truncation seems to work.
I tried this and it seems to lead to the file pointer moving back to the start of the file, so I don't get append behavior anymore. |
Yes but this means that errno is different in your implementation than what Base returns. It may not matter for most use cases but It's not the expected result value for GHC programs. Anything checking I also now notice an additional problem... with Since you're relying on the very latest win32 I can just add file support to
Hmmm.. are you sure you tested the right thing? access attributes don't influence the disposition. See [2]. The problem here is that the differing attributes change what happens during subsequent calls to For AppendMode you use FILE_APPEND_DATA, while GENERIC_WRITE is a combination of ALL write attributes including FILE_WRITE_ATTRIBUTES and FILE_WRITE_DATA. [1] https://docs.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants |
Sounds good.
@@ -21,5 +21,5 @@
accessMode = case iomode of
ReadMode -> Win32.gENERIC_READ
WriteMode -> Win32.gENERIC_WRITE
- AppendMode -> Win32.fILE_APPEND_DATA
+ AppendMode -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA
ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE What it now does is write to the file from the start, without truncating. If I revert the patch, appending works again.
|
So, I think The alternative is: --- a/System/File/AbstractFilePath/Windows.hs
+++ b/System/File/AbstractFilePath/Windows.hs
@@ -8,6 +8,7 @@ import System.AbstractFilePath.Windows ( WindowsFilePath )
import qualified System.Win32 as Win32
import qualified System.Win32.WindowsString.File as WS
+import Control.Monad (when)
#if defined(__IO_MANAGER_WINIO__)
import GHC.IO.SubSystem
#endif
@@ -31,12 +32,18 @@ openFile fp iomode = bracketOnError
#endif
Nothing)
Win32.closeHandle
- Win32.hANDLEToHandle
+ toHandle
where
+ toHandle h = do
+ when (iomode == AppendMode ) $ do
+ r <- Win32.setFilePointerEx h 0 Win32.fILE_END
+ err <- Win32.getLastError
+ when (r == 4294967295 && err /= 0) $ Win32.failWith "openFile" err
+ Win32.hANDLEToHandle h
accessMode = case iomode of
ReadMode -> Win32.gENERIC_READ
WriteMode -> Win32.gENERIC_WRITE
- AppendMode -> Win32.fILE_APPEND_DATA
+ AppendMode -> Win32.gENERIC_WRITE .|. Win32.fILE_APPEND_DATA
ReadWriteMode -> Win32.gENERIC_READ .|. Win32.gENERIC_WRITE
createMode = case iomode of |
ping |
Just realized that the API was already correct, you don't need this, on failure the API raises an exception. You just need a |
Cheers, did the dependent changes on this get merged get so the CI passes? If so I can merge this one. |
I'll add one more test suite to filepath that proves that old and new versions are equivalent. Maybe it's overkill, but I like to sleep well. Then this can be merged. I don't know which GHC version will be the first to depend on filepath-2.0 (maybe 9.6 or later), so you maybe want to maintain two branches for Win32? |
alright, the external CI now shows the same error. (see Appveyor) |
In preparation for AFPP.
aa97962
to
0f06662
Compare
c351218
to
995f3cc
Compare
The CI fails, because both filepath and bytestring have a lower bound on |
Well, Win32 doesn't need to run on Linux :) Please put the exports for the FPP stuff behind an
as I don't want to lose compatibility with older GHCs, we've worked very hard to maintain it. |
The CI fails here, because There are two known workarounds:
I'm not sure how to fix the private CI. |
We already had a dependency on filepath before, could we just add the constrain on the version of filepath needee under the FFp path? |
This is not about Whether you use |
Ahh ok. I Suppose we only need that because filepath hasn't been released
yet?
So should it go green once it is?
…Sent from my Mobile
On Thu, Jul 14, 2022, 10:42 Julian Ospald ***@***.***> wrote:
We already had a dependency on filepath before, could we just add the
constrain on the version of filepath needee under the FFp path?
This is not about Win32.cabal. It's about cabal.project. The cabal ticket
is here haskell/cabal#5444 <haskell/cabal#5444>
Whether you use source-repository-package or packages results in the same
issue.
—
Reply to this email directly, view it on GitHub
<#198 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAI7OKIWLMYS4IAPUQU2AI3VT7OHTANCNFSM5RR7C4KA>
.
You are receiving this because you modified the open/close state.Message
ID: ***@***.***>
|
That depends on whether this is the only issue with this PR. I can't tell, because I don't know how to install these ancient GHCs. |
Can't you add `--allow-newer` to allow cabal to ignore the upper bounds to
test on the CI?
…Sent from my Mobile
On Thu, Jul 14, 2022, 10:55 Julian Ospald ***@***.***> wrote:
So should it go green once it is?
That depends on whether this is the only issue with this PR. I can't tell,
because I don't know how to install these ancient GHCs.
—
Reply to this email directly, view it on GitHub
<#198 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAI7OKOL36YIJL37GGQ3MVDVT7PY7ANCNFSM5RR7C4KA>
.
You are receiving this because you modified the open/close state.Message
ID: ***@***.***>
|
Doubt so, because |
@Mistuke the private CI fails and I think this is not a sustainable workflow for contributors. I can't see the logs and don't wanna invest more time in blind-folded CI fixing. The public CI succeeds, feel free to adjust this PR. |
@Mistuke is this making a hackage release? |
Yes https://hackage.haskell.org/package/Win32 I'll fix the docs later when I feel a bit better. |
Thanks. Did you catch something in the amazonas? |
haha, luckily no, just exhausted. |
Depends on: haskell/filepath#103
For testing file operations, you can use https://github.com/hasufell/file-io (also please review the windows module)