* dir.cc (mkdir): Check last path component for "..".

(rmdir): Don't check last path component for "..".
	* fhandler_disk_file.cc (fhandler_disk_file::rmdir): Drop kludge
	which tries to allow deleting the current working directory.
	* path.cc (has_dot_last_component): Add parameter to indicate testing
	for "..".  Take trailing slash into account.
	(symlink_info::posixify): Rely on cygheap->cwd.win32 having a
	useful value.
	(cwdstuff::init): Initialize cygheap->cwd with current working
	directory.  Change to windows_system_directory afterwards.
	(cwdstuff::set): Never call SetCurrentDirectory here.  Just check
	if changing into target directory would be allowed.  Add comment to
	explain why.
	* path.h (has_dot_last_component): Declare with second parameter.
	* pinfo.cc (pinfo::zap_cwd): Remove.
	(pinfo::exit): Drop call to zap_cwd.
	* pinfo.h (class pinfo): Remove declaration of zap_cwd.
	* spawn.cc (spawn_guts): Set current working directory for non-Cygwin
	child applications.  Drop call to zap_cwd.
This commit is contained in:
Corinna Vinschen
2006-11-30 10:17:24 +00:00
parent 7d79436443
commit 8eca536272
8 changed files with 118 additions and 97 deletions

View File

@ -215,16 +215,28 @@ pathmatch (const char *path1, const char *path2)
Right now, normalize_posix_path will just normalize
those components away, which changes the semantics. */
bool
has_dot_last_component (const char *dir)
has_dot_last_component (const char *dir, bool test_dot_dot)
{
/* SUSv3: . and .. are not allowed as last components in various system
calls. Don't test for backslash path separator since that's a Win32
path following Win32 rules. */
const char *last_comp = strrchr (dir, '/');
return last_comp
&& last_comp[1] == '.'
&& (last_comp[2] == '\0'
|| (last_comp[2] == '.' && last_comp[3] == '\0'));
if (!last_comp)
last_comp = dir;
else {
/* Check for trailing slash. If so, hop back to the previous slash. */
if (!last_comp[1])
while (last_comp > dir)
if (*--last_comp == '/')
break;
if (*last_comp == '/')
++last_comp;
}
return last_comp[0] == '.'
&& ((last_comp[1] == '\0' || last_comp[1] == '/')
|| (test_dot_dot
&& last_comp[1] == '.'
&& (last_comp[2] == '\0' || last_comp[2] == '/')));
}
#define isslash(c) ((c) == '/')
@ -3199,10 +3211,7 @@ symlink_info::posixify (char *srcbuf)
{
char cvtbuf[CYG_MAX_PATH + 6];
if (cygheap->cwd.win32)
strncpy (cvtbuf, cygheap->cwd.win32, 2);
else
GetCurrentDirectory (CYG_MAX_PATH, cvtbuf);
strncpy (cvtbuf, cygheap->cwd.win32, 2);
strcpy (cvtbuf + 2, srcbuf);
mount_table->conv_to_posix_path (cvtbuf, contents, 0);
}
@ -4146,6 +4155,12 @@ void
cwdstuff::init ()
{
cwd_lock.init ("cwd_lock");
get_initial ();
/* Actually chdir into the syste dir to avoid cwd problems. See comment
in cwdstuff::set below. */
extern char windows_system_directory[];
SetCurrentDirectory (windows_system_directory);
cwd_lock.release ();
}
/* Get initial cwd. Should only be called once in a
@ -4173,17 +4188,42 @@ cwdstuff::set (const char *win32_cwd, const char *posix_cwd, bool doit)
if (win32_cwd)
{
cwd_lock.acquire ();
if (doit && !SetCurrentDirectory (win32_cwd))
{
/* When calling SetCurrentDirectory for a non-existant dir on a
Win9x share, it returns ERROR_INVALID_FUNCTION. */
if (GetLastError () == ERROR_INVALID_FUNCTION)
cwd_lock.acquire ();
if (doit)
{
/* Check if we *could* chdir, if we actually would.
Why don't we actually chdir? For two reasons:
- A process has always an open handle to the current working
directory which disallows manipulating this directory.
POSIX allows to remove a directory if the permissions are
ok. The fact that its the cwd of some process doesn't matter.
- SetCurrentDirectory fails for directories with strict
permissions even for processes with the SE_BACKUP_NAME
privilege enabled. The reason is apparently that
SetCurrentDirectory calls NtOpenFile without the
FILE_OPEN_FOR_BACKUP_INTENT flag set. */
DWORD attr = GetFileAttributes (win32_cwd);
if (attr == INVALID_FILE_ATTRIBUTES)
{
set_errno (ENOENT);
else
goto out;
}
if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
{
set_errno (ENOTDIR);
goto out;
}
HANDLE h = CreateFile (win32_cwd, GENERIC_READ, wincap.shared (),
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE)
{
__seterrno ();
goto out;
}
goto out;
}
CloseHandle (h);
}
}
/* If there is no win32 path or it has the form c:xxx, get the value */
if (!win32_cwd || (isdrive (win32_cwd) && win32_cwd[2] != '\\'))