From 20a2c4436224db8bf0b9dd47c58749a36a1dfc17 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 18 Jun 2001 21:18:59 +0000 Subject: [PATCH] * fhandler_tty.cc (fhandler_tty_slave::init): Revert 2001-06-16 change. * fork.cc (fork_copy): Print more debugging info. (fork_parent): Change order of arguments to accomdate buggy gcc. (fork): Ditto. * syscalls.cc (_unlink): Reorganize to try harder to delete file with DeleteFile and to recover more gracefully if FILE_FLAG_DELETE_ON_CLOSE doesn't work properly. --- winsup/cygwin/ChangeLog | 20 +++++- winsup/cygwin/fhandler_tty.cc | 2 +- winsup/cygwin/fork.cc | 12 ++-- winsup/cygwin/syscalls.cc | 129 ++++++++++++++++++++-------------- 4 files changed, 99 insertions(+), 64 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 218b0c73d..03b3b2640 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +Mon Jun 18 17:09:25 2001 Christopher Faylor + + * fhandler_tty.cc (fhandler_tty_slave::init): Revert 2001-06-16 change. + + * fork.cc (fork_copy): Print more debugging info. + (fork_parent): Change order of arguments to accomdate buggy gcc. + (fork): Ditto. + +Sun Jun 17 18:54:46 2001 Christopher Faylor + + * syscalls.cc (_unlink): Reorganize to try harder to delete file with + DeleteFile and to recover more gracefully if FILE_FLAG_DELETE_ON_CLOSE + doesn't work properly. + Sat Jun 16 13:06:49 2001 Christopher Faylor * exceptions.cc (sig_handle_tty_stop): Reset PID_STOPPED if not @@ -25,14 +39,14 @@ Thu Jun 14 20:19:46 2001 Christopher Faylor call to get_attributes. Fri June 15 09:25:00 Robert Collins - + * thread.cc (pthread_cond::Signal): Release the condition access variable correctly. 2001-06-14 Egor Duda - * fhandler.cc (fhandler_base::open): Set win32 access flags - to 0, when requested. + * fhandler.cc (fhandler_base::open): Set win32 access flags to 0, when + requested. * fhandler.h: New status flag FH_QUERYOPEN. (fhandler::get_query_open): New function. (fhandler::set_query_open): Ditto. diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index f0076cabf..293f4e636 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -574,7 +574,7 @@ fhandler_tty_slave::init (HANDLE, DWORD a, mode_t) if (a == (GENERIC_READ | GENERIC_WRITE)) mode = O_RDWR; - open (0, mode | O_NOCTTY); + open (0, mode); } int diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 651d935a3..b44855497 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -104,8 +104,8 @@ fork_copy (PROCESS_INFORMATION &pi, const char *what, ...) __seterrno (); /* If this happens then there is a bug in our fork implementation somewhere. */ - system_printf ("%s pass %d failed, %p..%p, done %d, %E", - what, pass, low, high, done); + system_printf ("%s pass %d failed, %p..%p, done %d, windows pid %u, %E", + what, pass, low, high, done, pi.dwProcessId); goto err; } } @@ -340,8 +340,8 @@ slow_pid_reuse (HANDLE h) } static int __stdcall -fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, - bool& load_dlls, child_info_fork &ch) +fork_parent (HANDLE& hParent, dll *&first_dll, + bool& load_dlls, void *stack_here, child_info_fork &ch) { HANDLE subproc_ready, forker_finished; DWORD rc; @@ -646,7 +646,7 @@ fork () } void *esp; - __asm ("movl %%esp,%0": "=r" (esp)); + __asm__ volatile ("movl %%esp,%0": "=r" (esp)); myself->set_has_pgid_children (); @@ -657,7 +657,7 @@ fork () if (res) res = fork_child (grouped.hParent, grouped.first_dll, grouped.load_dlls); else - res = fork_parent (esp, grouped.hParent, grouped.first_dll, grouped.load_dlls, ch); + res = fork_parent (grouped.hParent, grouped.first_dll, grouped.load_dlls, esp, ch); MALLOC_CHECK; syscall_printf ("%d = fork()", res); diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 4e96ccc1e..23b6540e3 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -100,78 +100,99 @@ _unlink (const char *ourname) /* Check for shortcut as symlink condition. */ if (atts != 0xffffffff && atts & FILE_ATTRIBUTE_READONLY) { - int len = strlen (win32_name.get_win32 ()); - if (len > 4 && strcasematch (win32_name.get_win32 () + len - 4, ".lnk")) - SetFileAttributes (win32_name.get_win32 (), - win32_name.file_attributes () & ~FILE_ATTRIBUTE_READONLY); + int len = strlen (win32_name); + if (len > 4 && strcasematch (win32_name + len - 4, ".lnk")) + SetFileAttributes (win32_name, atts & ~FILE_ATTRIBUTE_READONLY); } + DWORD lasterr; + lasterr = 0; for (int i = 0; i < 2; i++) { if (DeleteFile (win32_name)) { syscall_printf ("DeleteFile succeeded"); - res = 0; - break; + goto ok; } - DWORD lasterr; lasterr = GetLastError (); + if (i || lasterr != ERROR_ACCESS_DENIED || win32_name.issymlink ()) + break; /* Couldn't delete it. */ - /* FIXME: There's a race here. */ - HANDLE h = CreateFile (win32_name, GENERIC_READ, - FILE_SHARE_READ, - &sec_none_nih, OPEN_EXISTING, - FILE_FLAG_DELETE_ON_CLOSE, 0); - if (h != INVALID_HANDLE_VALUE) - { - CloseHandle (h); - syscall_printf ("CreateFile/CloseHandle succeeded"); - if (os_being_run == winNT || GetFileAttributes (win32_name) == (DWORD) -1) - { - res = 0; - break; - } - } + /* if access denied, chmod to be writable, in case it is not, + and try again */ + (void) chmod (win32_name, 0777); + } - if (i > 0) - { - if (os_being_run == winNT || lasterr != ERROR_ACCESS_DENIED) - goto err; + /* Tried to delete file by normal DeleteFile and by resetting protection + and then deleting. That didn't work. - if (win32_name.isremote ()) - { - syscall_printf ("access denied on remote drive"); - goto err; /* Can't detect this, unfortunately */ - } - lasterr = ERROR_SHARING_VIOLATION; - } + There are two possible reasons for this: 1) The file may be opened and + Windows is not allowing it to be deleted, or 2) We may not have permissions + to delete the file. - syscall_printf ("i %d, couldn't delete file, %E", i); + So, first assume that it may be 1) and try to remove the file using the + Windows FILE_FLAG_DELETE_ON_CLOSE semantics. This seems to work only + spottily on Windows 9x/Me but it does seem to work reliably on NT as + long as the file doesn't exist on a remote drive. */ - /* If we get ERROR_SHARING_VIOLATION, the file may still be open - - Windows NT doesn't support deleting a file while it's open. */ - if (lasterr == ERROR_SHARING_VIOLATION) - { - cygwin_shared->delqueue.queue_file (win32_name); - res = 0; - break; - } + bool delete_on_close_ok; - /* if access denied, chmod to be writable in case it is not - and try again */ - /* FIXME: Should check whether ourname is directory or file - and only try again if permissions are not sufficient */ - if (lasterr == ERROR_ACCESS_DENIED && chmod (win32_name, 0777) == 0) - continue; + delete_on_close_ok = !win32_name.isremote () && os_being_run == winNT; - err: - __seterrno (); - res = -1; - break; + /* Attempt to use "delete on close" semantics to handle removing + a file which may be open. */ + HANDLE h; + h = CreateFile (win32_name, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, + OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); + if (h == INVALID_HANDLE_VALUE) + { + if (GetLastError () == ERROR_FILE_NOT_FOUND) + goto ok; + } + else + { + CloseHandle (h); + syscall_printf ("CreateFile/CloseHandle succeeded"); + /* Everything is fine if the file has disappeared or if we know that the + FILE_FLAG_DELETE_ON_CLOSE will eventually work. */ + if (GetFileAttributes (win32_name) == (DWORD) -1 || delete_on_close_ok) + goto ok; /* The file is either gone already or will eventually be + deleted by the OS. */ } -done: + /* FILE_FLAGS_DELETE_ON_CLOSE was a bust. If delete_on_close_ok is + true then it should have worked. If it didn't work, that was an + error. Windows 9x seems to return ERROR_ACCESS_DENIED in "sharing + violation" type of situations. */ + if (delete_on_close_ok + || (lasterr != ERROR_ACCESS_DENIED && lasterr != ERROR_SHARING_VIOLATION)) + goto err; + + /* Can't reliably detect sharing violations on remote shares, so if we + didn't specifically get that error, then punt. */ + if (lasterr != ERROR_SHARING_VIOLATION && win32_name.isremote ()) + { + syscall_printf ("access denied on remote drive"); + goto err; /* Can't detect this, unfortunately */ + } + + syscall_printf ("couldn't delete file, err %d", lasterr); + + /* Add file to the "to be deleted" queue. */ + cygwin_shared->delqueue.queue_file (win32_name); + + /* Success condition. */ + ok: + res = 0; + goto done; + + /* Error condition. */ + err: + __seterrno (); + res = -1; + + done: syscall_printf ("%d = unlink (%s)", res, ourname); return res; } @@ -2084,7 +2105,7 @@ seteuid (uid_t uid) } /* Only when ntsec is ON! */ - /* If no impersonation token is available, try to + /* If no impersonation token is available, try to authenticate using NtCreateToken() or subauthentication. */ if (allow_ntsec && cygheap->user.token == INVALID_HANDLE_VALUE) { -- 2.43.5