Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-03-09 18:31:08 +0300
committerCorinna Vinschen <corinna@vinschen.de>2006-03-09 18:31:08 +0300
commit75fbcb44888333e7f6b7aa7ca1d3e47a7088162a (patch)
treeb27f44157ed7eeab21c9ffba4f20695992b409fa
parent82f0f1394c1ad85759eaa3749fca0f8331f608ef (diff)
* syscalls.cc (rename): Move existance check for oldpath further up
to the start of the function. Avoid another case of a name collision if oldpath is a shortcut and a file or directory newpath already exists.
-rw-r--r--winsup/cygwin/ChangeLog6
-rw-r--r--winsup/cygwin/syscalls.cc42
2 files changed, 41 insertions, 7 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ed94c4534..3ead72e5d 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,11 @@
2006-03-09 Corinna Vinschen <corinna@vinschen.de>
+ * syscalls.cc (rename): Move existance check for oldpath further up
+ to the start of the function. Avoid another case of a name collision
+ if oldpath is a shortcut and a file or directory newpath already exists.
+
+2006-03-09 Corinna Vinschen <corinna@vinschen.de>
+
* autoload.cc (NtClose): Define.
(NtOpenDirectoryObject): Define.
(NtQueryDirectoryObject): Define.
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 5cb5fe79a..758949398 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1176,6 +1176,7 @@ rename (const char *oldpath, const char *newpath)
{
int res = 0;
char *lnk_suffix = NULL;
+ bool no_lnk_file_exists = false;
path_conv real_old (oldpath, PC_SYM_NOFOLLOW,
transparent_exe ? stat_suffixes : NULL);
@@ -1187,6 +1188,13 @@ rename (const char *oldpath, const char *newpath)
return -1;
}
+ if (!real_old.exists ()) /* file to move doesn't exist */
+ {
+ syscall_printf ("file to move doesn't exist");
+ set_errno (ENOENT);
+ return -1;
+ }
+
path_conv real_new (newpath, PC_SYM_NOFOLLOW,
transparent_exe ? stat_suffixes : NULL);
@@ -1198,6 +1206,21 @@ rename (const char *oldpath, const char *newpath)
if (real_old.is_lnk_special ())
{
+ if (real_new.exists ())
+ {
+ /* This early directory test is necessary because the below test
+ tests against the name with attached .lnk suffix. To avoid
+ name collisions, we shouldn't rename a file to "foo.lnk"
+ if a "foo" directory exists. */
+ if (real_new.isdir ())
+ {
+ syscall_printf ("newpath is directory, but oldpath is not");
+ set_errno (EISDIR);
+ return -1;
+ }
+ /* Shortcut hack, No. 3, part 1 */
+ no_lnk_file_exists = true;
+ }
/* Shortcut hack. */
strcpy (new_buf, newpath);
strcat (new_buf, ".lnk");
@@ -1225,13 +1248,6 @@ rename (const char *oldpath, const char *newpath)
return -1;
}
- if (!real_old.exists ()) /* file to move doesn't exist */
- {
- syscall_printf ("file to move doesn't exist");
- set_errno (ENOENT);
- return -1;
- }
-
if (real_new.isdir () && !real_old.isdir ())
{
syscall_printf ("newpath is directory, but oldpath is not");
@@ -1355,6 +1371,18 @@ done:
*lnk_suffix = '.';
DeleteFile (real_new);
}
+ /* Shortcut hack, No. 3, part 2 */
+ /* If a file with the given name exists, it must be deleted after the
+ symlink has been renamed. Otherwise we end up with two files of
+ the same name in the directory, one file "newpath", which already
+ exited before rename has been called, and one file "newpath.lnk",
+ which is the result of the rename operation. */
+ else if (no_lnk_file_exists)
+ {
+ lnk_suffix = strrchr (real_new.get_win32 (), '.');
+ *lnk_suffix = '\0';
+ DeleteFile (real_new);
+ }
}
syscall_printf ("%d = rename (%s, %s)", res, (char *) real_old,