DMARC-Filter: OpenDMARC Filter v1.4.2 delorie.com 56UB21nR1771348
Authentication-Results: delorie.com; dmarc=pass (p=none dis=none) header.from=cygwin.com
Authentication-Results: delorie.com; spf=pass smtp.mailfrom=cygwin.com
DKIM-Filter: OpenDKIM Filter v2.11.0 delorie.com 56UB21nR1771348
Authentication-Results: delorie.com;
	dkim=pass (1024-bit key, unprotected) header.d=cygwin.com header.i=@cygwin.com header.a=rsa-sha256 header.s=default header.b=vBs7DZxp
X-Recipient: archive-cygwin@delorie.com
DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6A8023858D32
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cygwin.com;
	s=default; t=1753873318;
	bh=gugYleXlnPySXEszfoOEVFbmMpaKWhQe7Vw8H/VhM9I=;
	h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe:
	 List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:
	 From;
	b=vBs7DZxpTdPPHVxSgXzmeIr9TN4rGB7OKylRPzCiWbBfm4RG3PoltUltG8i3s8HnI
	 pjhOh3UZczIrgTx1WEUejBDie+RQt51CimYxGXxJx/HMgF9QhGOfSzfa/SpAC2ssd3
	 AjMCKs7zaI5raU2sSQnR6lzrUCStWUgzuKAhyVyQ=
X-Original-To: cygwin@cygwin.com
Delivered-To: cygwin@cygwin.com
DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B69A23858D1E
Date: Wed, 30 Jul 2025 13:01:09 +0200
To: cygwin@cygwin.com
Subject: Re: getcwd() and ENOENT
Message-ID: <aIn7dR4Wu-3GfnDN@calimero.vinschen.de>
Mail-Followup-To: cygwin@cygwin.com
References: <635c3b61-6ce7-5b77-2b0c-2c673c40e198@jdrake.com>
MIME-Version: 1.0
Content-Disposition: inline
In-Reply-To: <635c3b61-6ce7-5b77-2b0c-2c673c40e198@jdrake.com>
X-BeenThere: cygwin@cygwin.com
X-Mailman-Version: 2.1.30
Precedence: list
List-Id: General Cygwin discussions and problem reports <cygwin.cygwin.com>
List-Unsubscribe: <https://cygwin.com/mailman/options/cygwin>,
 <mailto:cygwin-request@cygwin.com?subject=unsubscribe>
List-Archive: <https://cygwin.com/pipermail/cygwin/>
List-Post: <mailto:cygwin@cygwin.com>
List-Help: <mailto:cygwin-request@cygwin.com?subject=help>
List-Subscribe: <https://cygwin.com/mailman/listinfo/cygwin>,
 <mailto:cygwin-request@cygwin.com?subject=subscribe>
From: Corinna Vinschen via Cygwin <cygwin@cygwin.com>
Reply-To: cygwin@cygwin.com
Cc: Corinna Vinschen <corinna-cygwin@cygwin.com>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: cygwin-bounces~archive-cygwin=delorie.com@cygwin.com
Sender: "Cygwin" <cygwin-bounces~archive-cygwin=delorie.com@cygwin.com>

On Jul 29 16:22, Jeremy Drake via Cygwin wrote:
> I have been looking at test failures in LLVM, and I've come across a
> strange one (to me).  It appears to be failing because it expects to:
> 
> create a temp directory
> chdir to the temp directory
> rmdir the temp directory
> (skip the test if the rmdir fails)
> call getcwd
> fail the test if it doesn't get an error of ENOENT
> ...
> 
> POSIX Issue 8 doesn't specify ENOENT on getcwd[1], but the Linux man page
> does[2].
> 
> Is this an issue in the test and it should just be skipped on Cygwin, or
> should Cygwin's getcwd be failing with ENOENT in that case?

At the moment, the right thing to do is to skip the test.  No current
Cygwin version is capable of recognizing this situation, given the
getcwd() function does not try to test the CWD handle.  It just copies
the path stored in the global cwdstuff.  And that's ok, because POSIX
doesn't define an error if the directory has been deleted, as you noted.

But even if we *do* check the directory handle as in...

diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 310876b5accd..2df00d16bd03 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -4985,10 +4985,30 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen)
 		    win32.Length / sizeof (WCHAR));
     }
   else
-    tocopy = posix;
+    {
+      tocopy = posix;
+      if (get_handle ())
+	{
+	  FILE_STANDARD_INFORMATION fsi;
+	  IO_STATUS_BLOCK io;
+	  NTSTATUS status;
+
+	  status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
+					   FileStandardInformation);
+	  if (!NT_SUCCESS (status) || fsi.NumberOfLinks == 0
+	      || fsi.DeletePending == TRUE)
+	    {
+	      set_errno (ENOENT);
+	      tocopy = NULL;
+	      buf = NULL;
+	    }
+	}
+    }
 
   debug_printf ("posix %s", posix);
-  if (strlen (tocopy) >= ulen)
+  if (!tocopy)
+    ;
+  else if (strlen (tocopy) >= ulen)
     {
       set_errno (ERANGE);
       buf = NULL;

...we only cover some scenarios:

- On NTFS with POSIX unlink semantics NtQueryInformationFile
  returns STATUS_SUCCESS, NumberOfLinks is 0, DeletePending is 1.

- On NFS, NumberOfLinks is 2, but DeletePending is 1 as well.

- On Samba, NtQueryInformationFile fails with STATUS_OBJECT_NAME_NOT_FOUND.

- WHile on NTFS without POSIX unlink semantics, the check fails.
  NtQueryInformationFile returns STATUS_SUCCESS, NumberOfLinks is 2,
  DeletePending is 0.

So we would have to use NtQueryAttributesFile, or, even simpler
(but incorrect) in this scenario, GetFileAttributes.

However!

Either way, with NtQueryInformationFile, NtQueryAttributesFile or
GetFileAttributes: What we get is a general slowdown of getcwd() for a
questionable gain.

Do we really need this?


Corinna

-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple
