Fossil Forum

coz.eduardo.hernandez 1 month ago

Post: What does the executable status for files mean?

When I run fossil status or fossil changes I get the status executable for most files. I expected something like edited, unknown, etc.. I'm using Fossil 2.28 [52445a27f1] 2026-03-11 11:31:46 UTC, under MSYS2 on Windows. This is what I see:

Executable status

I have noticed that when I create a stash all modifications seem to be stored, but when I use apply or pop only the files that did not have the executable status get restored. Therefore for an unsuspecting user fossil stash followed by fossil pop would mean losing all changes if undo didn't exist, but a new user might not know about undo. This behavior partially explains some of the weirdness I've seen with stashes.

And it's not that the files have execute permission, because they don't.

So what does a executable status mean?

mgagnon 1 month ago

By any chance, are you using a Cygwin executable on a non-Cygwin environment?

coz.eduardo.hernandez 1 month ago

MSYS2 is based on Cygwin, but I'm using their provided Fossil executables under the MSYS2's UCRT64 environment.

coz.eduardo.hernandez 1 month ago

MSYS2 is based on Cygwin, but I'm using their provided Fossil executables under the MSYS2's UCRT64 environment. I get the same result when using the official standa-alone executable through PowerShell.

mgagnon 1 month ago

Perhaps this forum thread could be related...

coz.eduardo.hernandez 1 month ago

It might be. I guess I'll have to dig into Fossil's code to figure this one out. Thanks for sending me in that direction.

mgagnon 1 month ago

Also, other questions about your setup: - Do you have the same problem when using the fossil executable provided from the fossil download page ? - Is your checkout on a local regular ntfs volume ?

In the past, I also had those false EXECUTABLE/UNEXEC state changes in windows when using wsl fossil on a ntfs drive (using /mnt/c/.../ path).

wsl fossil which is linux, is compiled to support executable mode bits, but when working on NTFS volume, something doesn't play well.

Related forum thread about WSL and EXECUTABLE status change issue.

coz.eduardo.hernandez 1 month ago

I do have the same problems with the executable on the fossil download page.

Indeed my checkout is on a local regular ntfs volume.

I did read about the WSL fossil issues, but I assumed it didn't have anything to do with my case, I only skimmed that page until I started this thread.

I think that Linux doesn't really handles NTFS permissions (access contro lists) but emulates it to a degree on mount, but they are not saved, but yeah the point is that it's not a seamless transition.

mgagnon 1 month ago

Can you reproduce the same issue from a standard powershell or cmd shell with downloaded fossil exec (on a newly created repo in this environment)

Perhaps you could give step-by-step instruction, starting with creation of a new repo to reproduce the issue so I or someone else reading this could try to reproduce the issue.

coz.eduardo.hernandez 1 month ago

So I actually went into Linux to check. If I run fossil with the files on the NTFS volume, I get the same output. If I copy the files to a Linux filesystem, I still get the same output, but then I can modify the execute bit with chmod -x and the execute output disappears.

I'm not sure why the files are marked as executable, but according to the security tab on the file properties on Windows, even if I disable the read & execute (there is a separate read permission) it is still marked as executable with Fossil.

coz.eduardo.hernandez 1 month ago

I haven't been able to reproduce it yet.

For now I know the reason it shows as executable it's because it takes it from the FOSSIL vFile table, I'm trying to find something that can cause such a change.

wyoung 1 month ago

The cause is neither Fossil nor MSYS. It’s NTFS vs POSIX, which is why it also affects Cygwin and WSL. Fossil’s sole involvement here is exposing an underlying truth.

That is also why our WSL doc is relevant. Z 2

coz.eduardo.hernandez 1 month ago

On the bright side, I found this issue is less serious than I thought, there's no loss of data. The files marked as executable are only non-edited files that are tracked, and stashing and popping actually fixes the issue. I checked the files one by one and reverted the files marked that didn't show anything, which left me with the same files I got after stashing and popping, with the exception of a file I had slotted for deletion, which was reported as missing afterwards.

doug9forester 1 month ago

See this thread to get rid of the problem: https://fossil-scm.org/forum/forumpost/160515715a7acd76

coz.eduardo.hernandez 1 month ago

So!

That small post by @wyoung led me to try a few things to reliably reproduce the bug, and what I found was: 1. The fossil version in MSYS2 in the UCRT64 (uses windows library called Universal C Runtime, the one I'm typically supposed to use) does not cause the bug 2. If I create a new repo with the UCRT64 fossil, then copy a file, add it, and commit it, calling fossil changes does not cause the bug 3. But if I immediately run fossil changes with the fossil version in Cygwin's repositories, or compiled by myself under Cygwin the bug will happen 4. After calling fossil revert it won't show as executable anymore, but sometimes if I repeat steps 2-3 some of the files that were previously committed will show the bug in addition to the new file. I don't know what determines when this happens.

Regardless, on src/vfile.c in the function vfile_check_signature at line 173, if I add a #define _WIN32 just before the first #ifndef _WIN32 in the function, then #undef _WIN32 after the last related #endif in the function, the bug goes away.

Cygwin doesn't define _WIN32 by default. You'd need to add a flag specific to Cygwin's gcc, -mwin32 for that, but compiling with that flag won't allow fossil to compile under Cygwin. To compile fossil under Cygwin you need to run ./configure; make like a *NIX build, not make -f win/Makefile.mingw.

What it does define is __CYGWIN__ .

At least the Cygwin project should patch their version of fossil. I'm not sure what approach Fossil's devs would like to take regarding this bug.

wyoung 1 month ago

Cygwin doesn't define _WIN32 by default.

On purpose. It is possible sentiment has evolved since I ceased involvement with the Cygwin project — which included maintaining a few packages — but my stale sense is that your solution is facile, even hacky.

the Cygwin project should patch their version of fossil

Cygwin packages are not maintained by “the project” but by individuals who choose to get involved. By the evidence, they need a new maintainer for this package. If you choose to take this on, you will be in a position to force this issue by worker fiat. However, I caution you to seek advice on the cygwin-apps list first.

You might get them to accept your justification in this specific, narrow instance; there’s precedent. Still, it cannot be a general rule, because to do so is to violate Cygwin’s basic contract. The sole question is whether you’ll be allowed a waiver.

Yet, because he who does the work makes the rules, you might get your way on that basis alone. Z 751c89b78ea

coz.eduardo.hernandez 1 month ago

Got it.

Defining _WIN32 then undefining it is definitely hacky, however changing it to #if defined(_WIN32) || defined(__CYGWIN__) makes sense to me. What do you think that would be a better solution?

I mean, the reason to skip the code is not just the POSIX functions, but like you said, that the NTFS and POSIX security model is different. POSIX uses the system's umask, while NTFS by default inherits from the parent directory. POSIX uses the exec bit to determine what is allowed to run, Windows looks at the file extension and magic numbers inside the file to know what it will attempt to run.

So on Windows having the 'read and execute' permission does not mean the same as what fossil means when it calls a file EXECUTABLE, even while running inside Cygwin. BUILD.txt considers Cygwin a kind of Windows environment, though admitedly I couldn't compile fossil on Cygwin using the MinGW Makefile.

The only other thing that makes sense to me is adding the CYGWIN guard to the func file_isexe at src/file.c instead, because it affects the program at more points, and in the description it mentions that on Windows it should only return a non-exec non-symlink result.

wyoung 1 month ago

What do you think that would be a better solution?

The linked article above gives some.

The essence of the alternative viewpoint is a philosophical stance: if you want Win32 semantics, use a Win32 program, not a Cygwin one trying to emulate Linux incompletely atop an NT kernel. Thus WSL2 vs WSL1: a real Linux kernel with a real Linux filesystem vs an NT kernel "personality" atop NTFS. If WSL1 solved all the problems, they would not have had to bother with the wholesale reimplementation that is WSL2.

Where you run into trouble is when trying to mix them, as with the WSL2 /mnt/c escape hatch. Now it's a real Linux kernel running a real Linux ELF binary but atop NTFS, and what else did you expect but trouble? 🤓 Z

coz.eduardo.hernandez 1 month ago

Got it.

Defining _WIN32 then undefining it is definitely hacky, however changing it to #if defined(_WIN32) || defined(__CYGWIN__) makes sense to me. What do you think that would be a better solution?

I mean, the reason to skip the code is not just the POSIX functions, but like you said, that the NTFS and POSIX security model is different. POSIX uses the system's umask, while NTFS by default inherits from the parent directory. POSIX uses the exec bit to determine what is allowed to run, Windows looks at the file extension and magic numbers inside the file to know what it will attempt to run.

So on Windows having the 'read and execute' permission does not mean the same as what fossil means when it calls a file EXECUTABLE, even while running inside Cygwin. BUILD.txt considers Cygwin a kind of Windows environment, though admitedly I couldn't compile fossil on Cygwin using the MinGW Makefile.

The only other thing that makes sense to me is adding the __CYGWIN__ guard to the func file_isexe at src/file.c instead, because it affects the program at more points, and in the description it mentions that on Windows it should only return a non-exec non-symlink result.

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button