We have to be careful about doing too much (adding edge cases and complexity), though in this case how about:
canon_src = canonicalize(src);
canon_dst = canonicalize(dst);
int ret = rename(src, dst);
if (ret == EXDEV) {
/* Note if there are symlinks being recreated
between the canonicalize() and rename() above,
then it's better to not fall back to a
cross device copy anyway. */
if (common_prefix(canon_src, canon_dst))
ret = EINVAL; /* Treat like "copy into self" */
}
We have to be careful about doing too much (adding edge cases and complexity), though in this case how about: