On Sat Mar 15 12:38:32 2025 +0000, Jinoh Kang wrote:
If multiple wineservers (and thus wineprefixes) were to attempt to rename the same hardlink, they may end up allocating the *same*[^1] tempname and race against each other. This fixes the race without increasing the number of syscalls (untested):
if (!is_dir) { /* to avoid TOCTTOU, probe existence of tmpname and link at the same time */ if (linkat( dirfd, srcname, dirfd, tmpname )) continue; if (unlinkat( dirfd, srcname )) { file_set_error(); unlinkat( dirfd, tmpname ); goto ret; } break; } /* directories can't have hardlinks, so just rename it to tmpname */ else if (fstatat( dirfd, tmpname, &st, 0 ) && /* tmpname doesn't exist */ !renameat( dirfd, srcname, dirfd, tmpname )) break;
(And remove the renameat srcname,tmpname below) [^1]: Each wineserver starts with `tmp_value = 0`. Each wineserver has the same `current_time` at the same time if clock sampling aligns.
Good point. I've added it along with checking for error codes properly (we only want to keep going if it actually exists; if it fails for other reasons, there's no point retrying since it will likely keep failing).