You probably stumbled upon this issue on Windows platforms: files created by
fopen() are by default locked for deletion or renaming.
Ie. if you do this:
foo.bar file will be locked until the process closes the file (or dies). No renaming. No deleting.
This default feature is rather different from what we have on POSIX-like systems, and on Linux especially, where any file can basically be renamed or deleted while being opened. Once a file is being opened, its directory reference has basically no influence, except the implicit reference count (ie. deleting the file will only decrement the refcount, and closing the last handle will remove the underlying inodes)
This is actually a cool feature: you can have a file opened, and immediately unlinked, to have an anonymous file where you may execute read/write operations without bothering handling the cleanup if the process is killed, for example. You can also create a log file, redirect stdout/stderr, and later want to rotate the file, without being hit by
permission denied errors. This is especially true when all references to the file haven’t been closed yet – say, if you have stdio redirected to a log file, and if you have a child process spawned and logging in the same log file.
On, Windows, the infamous
ERROR_ACCESS_DENIED will kick you in the face as soon as you try to do the same.
The documentation says:
- FILE_SHARE_DELETE Enables subsequent open operations on a file or device to request delete access. Otherwise, other processes cannot open the file or device if they request delete access. If this flag is not specified, but the file or device has been opened for delete access, the function fails. Note Delete access allows both delete and rename operations.
Hey, that’s exactly what we are looking for! But we want a nice
FILE pointer, not an horrible
HANDLE object. Is it possible ?
HANDLEobject can be attached to a low-level C library handle through
the low-level C library handle can be attached to a
You just have to take some care about the passed
fopen() flags to open the file with proper flags, and your “compatible” function should be something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
You can test this function using the example below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
The “log.txt” file will be deletable and movable without troubles, and you may even successfully write to the deleted file.
TL;DR: I wish I had known sooner. Darn.