Jinoh Kang (@iamahuman) commented about server/fd.c:
{ if (!fstat( fd->unix_fd, &st2 ) && st.st_ino == st2.st_ino && st.st_dev == st2.st_dev) { - if (create_link && !replace) set_error( STATUS_OBJECT_NAME_COLLISION ); + if (!create_link) + { + /* if it's not the "same" file (by path), it means it's a hardlink, so we need to remove the source */ + if (!is_same_file_by_path( fd->unix_name, name ) && unlink( fd->unix_name )) + file_set_error(); + } + else if (!replace) set_error( STATUS_OBJECT_NAME_COLLISION ); free( name ); return; }
I suspect this (both old and new code) is broken since it doesn't go through the rest of checks below. This is merely a hack to work around rename(2) being a no-op if src and dest are hard-links to the same file, so the special casing should be done at the rename(2) call below, instead of returning early IMHO. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/6855#note_88729