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 ); } ```