diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2013-01-11 12:34:41 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2013-01-11 12:34:41 +0000 |
commit | 7142197465d10f4284519c6463b52ed3451089f1 (patch) | |
tree | 810c6ffd6ec2ac83dd7bf5ba00e7e1e531f66d68 | |
parent | 2880becf0c27375885f1b7d9fd4444065a67462e (diff) | |
download | cygnal-7142197465d10f4284519c6463b52ed3451089f1.tar.gz cygnal-7142197465d10f4284519c6463b52ed3451089f1.tar.bz2 cygnal-7142197465d10f4284519c6463b52ed3451089f1.zip |
* syscalls.cc (rename): Drop handling paths > 32757 chars, emit EINVAL
instead, thus simplifying code allocating and filling pfri. Drop size
and use constant expression in NtSetInformationFile call. Add comments.
Drop redundant test for fs_serial_number and change comment accordingly.
-rw-r--r-- | winsup/cygwin/ChangeLog | 7 | ||||
-rw-r--r-- | winsup/cygwin/syscalls.cc | 43 |
2 files changed, 28 insertions, 22 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 7f40ffe6d..32d87e080 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,10 @@ +2013-01-11 Corinna Vinschen <corinna@vinschen.de> + + * syscalls.cc (rename): Drop handling paths > 32757 chars, emit EINVAL + instead, thus simplifying code allocating and filling pfri. Drop size + and use constant expression in NtSetInformationFile call. Add comments. + Drop redundant test for fs_serial_number and change comment accordingly. + 2013-01-11 Thomas Wolff <towo@towo.net> * fhandler.h (class dev_console): Flag for expanded control sequence. diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 1aedc1f61..a23611e36 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1,7 +1,7 @@ /* syscalls.cc: syscalls Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. + 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc. This file is part of Cygwin. @@ -2035,7 +2035,6 @@ rename (const char *oldpath, const char *newpath) HANDLE old_trans = NULL, trans = NULL; OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK io; - ULONG size; FILE_STANDARD_INFORMATION ofsi; PFILE_RENAME_INFORMATION pfri; @@ -2407,14 +2406,13 @@ retry: /* SUSv3: If the old argument and the new argument resolve to the same existing file, rename() shall return successfully and perform no other action. - The test tries to be as quick as possible. First it tests for identical - volume serial numbers because that information is available anyway. - Then it tests if oldpath has more than 1 hardlink, then it opens newpath + The test tries to be as quick as possible. Due to the above cross device + check we already know both files are on the same device. So it just + tests if oldpath has more than 1 hardlink, then it opens newpath and tests for identical file ids. If so, oldpath and newpath refer to the same file. */ if ((removepc || dstpc->exists ()) && !oldpc.isdir () - && dstpc->fs_serial_number () == oldpc.fs_serial_number () && NT_SUCCESS (NtQueryInformationFile (fh, &io, &ofsi, sizeof ofsi, FileStandardInformation)) && ofsi.NumberOfLinks > 1 @@ -2440,6 +2438,18 @@ retry: } NtClose (nfh); } + /* Create FILE_RENAME_INFORMATION struct. Using a tmp_pathbuf area allows + for paths of up to 32757 chars. This test is just for paranoia's sake. */ + if (dstpc->get_nt_native_path ()->Length > NT_MAX_PATH * sizeof (WCHAR) + - sizeof (FILE_RENAME_INFORMATION)) + { + debug_printf ("target filename too long"); + set_errno (EINVAL); + goto out; + } + pfri = (PFILE_RENAME_INFORMATION) tp.w_get (); + pfri->ReplaceIfExists = TRUE; + pfri->RootDirectory = NULL; if (oldpc.fs_is_nfs ()) { /* Workaround depressing NFS bug. FILE_RENAME_INFORMATION.FileName @@ -2477,30 +2487,18 @@ retry: while ((oldp = wcschr (++oldp, L'\\')) != NULL) newp = wcpcpy (newp, L"..\\"); newp = wcpcpy (newp, dstp); - size = sizeof (FILE_RENAME_INFORMATION) - + (newp - newdst) * sizeof (WCHAR); - if (size > NT_MAX_PATH * sizeof (WCHAR)) /* Hopefully very seldom. */ - pfri = (PFILE_RENAME_INFORMATION) alloca (size); - else - pfri = (PFILE_RENAME_INFORMATION) tp.w_get (); pfri->FileNameLength = (newp - newdst) * sizeof (WCHAR); memcpy (&pfri->FileName, newdst, pfri->FileNameLength); } else { - size = sizeof (FILE_RENAME_INFORMATION) - + dstpc->get_nt_native_path ()->Length; - if (size > NT_MAX_PATH * sizeof (WCHAR)) /* Hopefully very seldom. */ - pfri = (PFILE_RENAME_INFORMATION) alloca (size); - else - pfri = (PFILE_RENAME_INFORMATION) tp.w_get (); pfri->FileNameLength = dstpc->get_nt_native_path ()->Length; memcpy (&pfri->FileName, dstpc->get_nt_native_path ()->Buffer, pfri->FileNameLength); } - pfri->ReplaceIfExists = TRUE; - pfri->RootDirectory = NULL; - status = NtSetInformationFile (fh, &io, pfri, size, FileRenameInformation); + status = NtSetInformationFile (fh, &io, pfri, + sizeof *pfri + pfri->FileNameLength, + FileRenameInformation); /* This happens if the access rights don't allow deleting the destination. Even if the handle to the original file is opened with BACKUP and/or RECOVERY, these flags don't apply to the destination of the @@ -2537,7 +2535,8 @@ retry: } } if (NT_SUCCESS (status = unlink_nt (*dstpc))) - status = NtSetInformationFile (fh, &io, pfri, size, + status = NtSetInformationFile (fh, &io, pfri, + sizeof *pfri + pfri->FileNameLength, FileRenameInformation); } if (NT_SUCCESS (status)) |