-
Notifications
You must be signed in to change notification settings - Fork 86
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
Mixup of O_EXCL and O_TRUNC constant values CGO vs non CGO #66
Comments
I can confirm that this is a problem. I am investigating why this is happening. |
The relevant source in WinFsp is from file if ('C' == f->env->environment) /* Cygwin */
fi.flags = 0x0200 | 0x0800 | 2 /*O_CREAT|O_EXCL|O_RDWR*/;
else
fi.flags = 0x0100 | 0x0400 | 2 /*O_CREAT|O_EXCL|O_RDWR*/; This agrees with the contents of file #define _O_CREAT 0x0100 // create and open file
#define _O_TRUNC 0x0200 // open and truncate
#define _O_EXCL 0x0400 // open only if file doesn't already exist It also agrees with file #define _O_CREAT 0x0100
#define _O_TRUNC 0x0200
#define _O_EXCL 0x0400 It looks to me that the no-cgo version is incorrect. It should read: O_TRUNC = 0x0200
O_EXCL = 0x0400 FYI, WinFsp will not send the O_TRUNC flag. |
From one of the posts on the rclone forum, this is what rclone received from WinFSP/cgofuse which agrees with the code above.
And this is how rclone interprets it using the cgo flags
So I think you are saying that is correct and I guess that brings me on to the question of why is WinFSP sending This was the issue I was chasing down when I discovered the mismatch between the constants! |
The WinFsp native API has an operation The FUSE layer is implemented on top of the native WinFsp API. The FUSE implementation of |
That makes perfect sense... Except for the issue reported in the forum thread... Here is the rclone log What appears to happen is that
Then immediately called again which fails because the file already exists.
I haven't been able to replicate this but I suspect it might be Windows 11 / WIndows 2022 datacenter behaviour. So I don't know exactly what is going on here - probably a misunderstanding by me, but I'd appreciate your thoughts! |
I notice that the first log ends with:
The status code Possible scenario:
|
Possibilities for things which WinFsp calls into rclone during the I don't think this is being called as there is no trace from rclone I don't think this is being called as there is no trace from rclone either This part of the log
Implies that release was called, so create was taking the error path here as you suggested. Given that So either CreateEx caused Result to be set to failure (unlikely since we see it returned OK in the rclone log) Or this went wrong Or this went wrong What about the last two options - can they fail with |
I agree that This could be the problem. The Windows file creation API is the kitchen sink and then some: the file creation "system call" allows a file to be created together with extended attributes. So this checks if there are extended attributes passed during file creation and calls The problem is that in practice this Windows file system capability is almost never used, because it is not exposed by the regular Windows API ( In any case, it might be prudent to add a check for Re: This issues an |
Re-reading the code of This suggests that if the failure to set extended attributes is indeed the problem, we may not be able to ignore a |
Rclone does indeed return ENOSYS for any of the // Setxattr sets extended attributes.
func (fsys *FS) Setxattr(path string, name string, value []byte, flags int) (errc int) {
return -fuse.ENOSYS
}
// Getxattr gets extended attributes.
func (fsys *FS) Getxattr(path string, name string) (errc int, value []byte) {
return -fuse.ENOSYS, nil
}
// Removexattr removes extended attributes.
func (fsys *FS) Removexattr(path string, name string) (errc int) {
return -fuse.ENOSYS
}
// Listxattr lists extended attributes.
func (fsys *FS) Listxattr(path string, fill func(name string) bool) (errc int) {
return -fuse.ENOSYS
} I'll add Trace statements and get the user to test again and we can see if your theory is correct. |
Please let me know. In the meantime I will fix the mixed up values for the |
I got a log back from the user. It shows quite clearly that So it looks like your theory is correct.
Here are some ideas...
What do you think? Any of those sound like a good idea? |
Thanks for confirming. I find it rather unusual that anyone would try to set Extended Attributes (EAs in Windows parlance) during the The sensible fix here is to assume success when An additional fix would be to avoid enabling EA support during initialization of the file system. Currently this is done with the following code: if (0 != f->ops.listxattr && 0 != f->ops.getxattr &&
0 != f->ops.setxattr && 0 != f->ops.removexattr)
f->VolumeParams.ExtendedAttributes = 1; Obviously this does not work if the file system has empty definitions of these operations that return I will look look into implementing either the first one or both of these fixes in WinFsp-FUSE, which should resolve this issue.
FUSE file systems already "approximate" the Windows file system. For example, FUSE file systems do not support full ACLs, file attributes or reparse points. I think there are fewer Windows applications that care about EAs rather than other features that FUSE does not support.
That is an interesting idea and worth keeping in mind if we fail to provide a simpler fix. |
If you compile and run this program
It prints this
However if you disable CGO and compile it you get a different answer with O_EXCL and O_TRUNC swapped over.
I believe the non CGO version is correct, at least that agrees with what I receive from WinFSP. It is defined here
cgofuse/fuse/fsop_nocgo_windows.go
Lines 107 to 108 in f0ad031
whereas the CGO version is defined here - this also looks correct
cgofuse/fuse/fsop_cgo.go
Lines 249 to 250 in f0ad031
So something a little wacky is going on!
This is compiling on Windows 10 with go1.18.1 and gcc 8.1.0 provided by MinGW using latest released cgofuse v1.5.0 and latest stable WinFSP (2022 installed from
1.10.220006.msi
).This was originally reported in the rclone forum here: https://forum.rclone.org/t/cannot-copy-files-to-mounted-azure-storage-windows/30092 if you want some background.
I suspect that the problem might be with the WinFSP include files, but I couldn't figure out where the constants were defined.
You said before in #19 (comment) where we discussed a very similar issue
So I wonder if I'm including the Cygwin version of the fuse header files or something like that? This is the include I use
Any help gratefully received!
The text was updated successfully, but these errors were encountered: