Jinoh Kang (@iamahuman) commented about server/fd.c:
+ if (!is_dir) + { + /* we can't just do rename(2) here; renaming a file to its hardlink is no-op */ + if (linkat( dirfd, tmpname, dirfd, dstname, 0 ) && errno != EEXIST) + { + if (errno == EPERM || errno == EOPNOTSUPP) + { + /* FIXME: filesystem doesn't support hardlinks, entire operation might be a no-op on casefold dirs */ + if (renameat( dirfd, tmpname, dirfd, dstname )) + file_set_error(); + goto ret; + } + + file_set_error(); + /* revert the temporary rename */ + renameat( dirfd, tmpname, dirfd, srcname ); Let's make this a common logic for all cases (hardlink, no hardlink, & dir).
Something like this (untested): ```c int undo_tmp_rename = 0; (...) undo_tmp_rename = 1; /* directories can't have hardlinks */ if (!is_dir) { /* we can't just do rename(2) here; renaming a file to its hardlink is no-op */ if (linkat( dirfd, tmpname, dirfd, dstname, 0 ) && errno != EEXIST) { if (errno != EPERM && errno != EOPNOTSUPP) { file_set_error(); goto ret; } /* Filesystem doesn't support hardlinks, fall back to renaming */ } else { undo_tmp_rename = 0; if (unlinkat( dirfd, tmpname, 0 )) file_set_error(); goto ret; /* We're done */ } } /* Renaming a directory, or filesystem doesn't support hardlinks */ if (renameat( dirfd, tmpname, dirfd, dstname )) file_set_error(); else undo_tmp_rename = 0; ret: if (undo_tmp_rename) { /* revert the temporary rename */ renameat( dirfd, tmpname, dirfd, srcname ); } ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6855#note_98191