* 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> 2006-12-06 Corinna Vinschen <corinna@vinschen.de>
* termios.cc: Change include order to accomodate change to sys/ioctl.h. * termios.cc: Change include order to accomodate change to sys/ioctl.h.

View File

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

View File

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

View File

@ -4150,6 +4150,8 @@ cwdstuff::get_hash ()
return hashnow; return hashnow;
} }
extern char windows_system_directory[];
/* Initialize cygcwd 'muto' for serializing access to cwd info. */ /* Initialize cygcwd 'muto' for serializing access to cwd info. */
void void
cwdstuff::init () cwdstuff::init ()
@ -4157,16 +4159,22 @@ cwdstuff::init ()
extern int dynamically_loaded; extern int dynamically_loaded;
cwd_lock.init ("cwd_lock"); cwd_lock.init ("cwd_lock");
get_initial (); 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. */ in cwdstuff::set below. */
extern char windows_system_directory[];
SetCurrentDirectory (windows_system_directory); SetCurrentDirectory (windows_system_directory);
} }
cwd_lock.release (); 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 /* Get initial cwd. Should only be called once in a
process tree. */ process tree. */
bool bool
@ -4195,40 +4203,55 @@ cwdstuff::set (const char *win32_cwd, const char *posix_cwd, bool doit)
cwd_lock.acquire (); cwd_lock.acquire ();
if (doit) if (doit)
{ {
/* Check if we *could* chdir, if we actually would. if (keep_in_sync ())
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); /* If a Cygwin application called cygwin_internal(CW_SYNC_WINENV),
goto out; then it's about to call native Windows functions. This also
} sets the keep_in_sync flag so that we actually chdir into the
if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) native directory to avoid confusion. */
{ if (!SetCurrentDirectory (win32_cwd))
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 (); __seterrno ();
goto out; 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);
}
} }
} }
} }