diff options
author | Bram Moolenaar <Bram@vim.org> | 2008-12-30 15:15:57 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2008-12-30 15:15:57 +0000 |
commit | 3576da72b4b5099ef8949c01ae8a7a5d8fb02913 (patch) | |
tree | dd70f1d98d55f6087d9676a8e726f159edd80355 /src/fileio.c | |
parent | cbb8eb34805c66a2ffbac0afd1bf3de1d9d93948 (diff) |
updated for version 7.2-076v7.2.076
Diffstat (limited to 'src/fileio.c')
-rw-r--r-- | src/fileio.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/fileio.c b/src/fileio.c index c0dd78d47d..39b92a6c90 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -6119,6 +6119,47 @@ vim_rename(from, to) if (mch_stat((char *)from, &st) < 0) return -1; +#ifdef UNIX + { + struct stat st_to; + char tempname[MAXPATHL + 1]; + + /* It's possible for the source and destination to be the same file. + * This happens when "from" and "to" differ in case and are on a FAT32 + * filesystem. In that case go through a temp file name. */ + if (mch_stat((char *)to, &st_to) >= 0 + && st.st_dev == st_to.st_dev + && st.st_ino == st_to.st_ino) + { + /* Find a name that doesn't exist and is in the same directory. + * Move "from" to "tempname" and then to "to". */ + if (STRLEN(from) >= MAXPATHL - 5) + return -1; + STRCPY(tempname, from); + for (n = 123; n < 99999; ++n) + { + sprintf(gettail(tempname), "%d", n); + if (mch_stat(tempname, &st_to) < 0) + { + if (mch_rename((char *)from, tempname) == 0) + { + if (mch_rename(tempname, (char *)to) == 0) + return 0; + /* Strange, the second step failed. Try moving the + * file back and return failure. */ + mch_rename(tempname, (char *)from); + return -1; + } + /* If it fails for one temp name it will most likely fail + * for any temp name, give up. */ + return -1; + } + } + return -1; + } + } +#endif + /* * Delete the "to" file, this is required on some systems to make the * mch_rename() work, on other systems it makes sure that we don't have |