* cygheap.h (struct cwdstuff): Add "sync" member and accompanying

"keep_in_sync" methods.
	* external.cc (cygwin_internal): Call above keep_in_sync method when
	CW_SYNC_WINENV is requested.
	* path.cc (cwdstuff::init): Don't change to windows_system_directory
	if keep_in_sync is requested.
	(cwdstuff::keep_in_sync): New method.
	(cwdstuff::set): Take sync flag into account.
This commit is contained in:
Corinna Vinschen 2006-12-07 10:04:52 +00:00
parent 63f33caadc
commit 2ffc166d07
4 changed files with 71 additions and 33 deletions

View File

@ -1,3 +1,14 @@
2006-12-07 Corinna Vinschen <corinna@vinschen.de>
* cygheap.h (struct cwdstuff): Add "sync" member and accompanying
"keep_in_sync" methods.
* external.cc (cygwin_internal): Call above keep_in_sync method when
CW_SYNC_WINENV is requested.
* path.cc (cwdstuff::init): Don't change to windows_system_directory
if keep_in_sync is requested.
(cwdstuff::keep_in_sync): New method.
(cwdstuff::set): Take sync flag into account.
2006-12-06 Corinna Vinschen <corinna@vinschen.de>
* termios.cc: Change include order to accomodate change to sys/ioctl.h.

View File

@ -230,6 +230,7 @@ struct cwdstuff
char *win32;
DWORD hash;
DWORD drive_length;
bool sync;
static muto cwd_lock;
char *get (char *, int = 1, int = 0, unsigned = CYG_MAX_PATH);
DWORD get_hash ();
@ -244,6 +245,8 @@ struct cwdstuff
void fixup_after_exec (char *, char *, DWORD);
bool get_initial ();
int set (const char *, const char *, bool);
bool keep_in_sync () const { return sync; }
void keep_in_sync (bool val);
};
#ifdef DEBUGGING

View File

@ -346,6 +346,7 @@ cygwin_internal (cygwin_getinfo_types t, ...)
try_to_debug ();
break;
case CW_SYNC_WINENV:
cygheap->cwd.keep_in_sync (true);
sync_winenv ();
return 0;
case CW_CYGTLS_PADSIZE:

View File

@ -4150,6 +4150,8 @@ cwdstuff::get_hash ()
return hashnow;
}
extern char windows_system_directory[];
/* Initialize cygcwd 'muto' for serializing access to cwd info. */
void
cwdstuff::init ()
@ -4157,16 +4159,22 @@ cwdstuff::init ()
extern int dynamically_loaded;
cwd_lock.init ("cwd_lock");
get_initial ();
if (!dynamically_loaded)
if (!dynamically_loaded && !keep_in_sync ())
{
/* Actually chdir into the syste dir to avoid cwd problems. See comment
/* Actually chdir into the system dir to avoid cwd problems. See comment
in cwdstuff::set below. */
extern char windows_system_directory[];
SetCurrentDirectory (windows_system_directory);
}
cwd_lock.release ();
}
void
cwdstuff::keep_in_sync (bool val)
{
sync = val;
SetCurrentDirectory (val ? win32 : windows_system_directory);
}
/* Get initial cwd. Should only be called once in a
process tree. */
bool
@ -4195,40 +4203,55 @@ cwdstuff::set (const char *win32_cwd, const char *posix_cwd, bool doit)
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)
if (keep_in_sync ())
{
set_errno (ENOENT);
goto out;
}
if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
{
set_errno (ENOTDIR);
goto out;
}
if (wincap.can_open_directories ())
{
HANDLE h = CreateFile (win32_cwd, GENERIC_READ, wincap.shared (),
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE)
{
/* If a Cygwin application called cygwin_internal(CW_SYNC_WINENV),
then it's about to call native Windows functions. This also
sets the keep_in_sync flag so that we actually chdir into the
native directory to avoid confusion. */
if (!SetCurrentDirectory (win32_cwd))
{
__seterrno ();
goto out;
}
CloseHandle (h);
}
else
{
/* 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);
goto out;
}
if (!(attr & FILE_ATTRIBUTE_DIRECTORY))
{
set_errno (ENOTDIR);
goto out;
}
if (wincap.can_open_directories ())
{
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;
}
CloseHandle (h);
}
}
}
}