glib: map ERROR_LOCK_VIOLATION and ERROR_SHARING_VIOLATION to EBUSY.
On Windows, these errors happen when a file is temporarily unavailable because another process has a lock on it. This is not necessarily a fatal error for g_rename(), as it means it may work after a retry. Yet we need to properly tell the proper error condition for calling developer to handle the situation.
Linux' rename() already use EBUSY errno for similar issue, though mostly
when called on directories only, and warning such case is actually quite
uncommon: "The rename fails because oldpath or newpath is a directory
that is in use by some process" (cf.
man 2 rename).
So I figure this is the right counterpart for the sharing violation on
Additional context: this change was triggered by gimp#1370. Basically some people under Windows experience intermittent issues when saving on directories synced in their cloud system (reported for Dropbox and Google drive) on Windows.
Current code simply returns "Error renaming temporary file: Permission denied", because current implementation of
SHARING_VIOLATION all to
EACCESS, as though they were the same issue.
Actually they aren't. Whereas
ACCESS_DENIED can probably be considered as fatale (permissions or whatnot), the other could be just temporary stepbacks. Now this is up to the calling software probably to decide what to do when this happens (cancel, retry, and if so, for how long until abandoning, etc.) but for this, we need the information.
I chose to map these to
EBUSY instead as it looks quite similar and is used in similar way by
man 2 rename. POSIX defines this error as: "Resource busy. An attempt was made to make use of a system resource that is not currently available, as it is being used by another process in a manner that would have conflicted with the request being made by this process."
That sounds quite fitting! (note I hesitated with EAGAIN too, which is defined by: "Resource temporarily unavailable. This is a temporary condition and later calls to the same routine may complete normally." Yet I went with EBUSY as it was also a possible errno value in the
rename() Linux call (unlike EAGAIN), so it seems like it could allow easier cross-platform handling.
Note: at first I actually added some handling code within
g_rename(), to retry before abandoning. But afterwards I thought this may not be the wisest, especially since the caller cannot control any max retry delay (unless we create a new function with a delay parameter). Maybe it's better to just let the calling application decide what to do.
Now if you would prefer to have handling code within glib, just tell me, and I'll push the alternative with a new function.