* 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.
This commit is contained in:
Corinna Vinschen 2006-03-09 15:31:08 +00:00
parent 82f0f1394c
commit 75fbcb4488
2 changed files with 41 additions and 7 deletions

View File

@ -1,3 +1,9 @@
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.

View File

@ -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,