Subject: Re: [PATCH] Treat unreachable current directory as error

From: Paul Eggert <[email-masked]>
Date: Sat, 7 Oct 2017 23:04:54 -0700

Philipp Stephani wrote:
> All of the current directory functions exhibit this behavior, including
> getwd and getcwd, so you need to make sure they are also covered.

Thanks for letting us know. I installed the 2nd attached patch, which addresses 
this by making the patch behave more like what you originally proposed, while 
still avoiding the need to use file_name_absolute_p (which is about Emacs file 
names, not OS names). Also, I noticed a related memory leak and fixed that by 
installing the 1st attached patch.
From 2202952b8307f3a6407820280e94e4d979b7a122 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sat, 7 Oct 2017 22:48:49 -0700
Subject: [PATCH 1/2] * src/xsmfns.c (x_session_initialize): Fix memory leak.

---
 src/xsmfns.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/xsmfns.c b/src/xsmfns.c
index 2cb4f3e..fb0d01b 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -401,12 +401,14 @@ x_session_initialize (struct x_display_info *dpyinfo)
   ptrdiff_t name_len = 0;
 
   /* libSM seems to crash if pwd is missing - see bug#18851.  */
-  if (! emacs_get_current_dir_name ())
+  char *pwd = emacs_get_current_dir_name ();
+  if (!pwd)
     {
       fprintf (stderr, "Disabling session management due to pwd error: %s\n",
                emacs_strerror (errno));
       return;
     }
+  xfree (pwd);
 
   ice_fd = -1;
   doing_interact = false;
-- 
2.7.4

From 7c2c117c91eeef5e7bd70c98cc7e201007016b1e Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Sat, 7 Oct 2017 22:56:29 -0700
Subject: [PATCH 2/2] Improve test for unreachable dirs

* src/sysdep.c (get_current_dir_name_or_unreachable):
New function, with most of the old contents of
emacs_get_current_dir_name.
(emacs_get_current_dir_name): Use it.  Use a simpler
test for unreachable directory strings, and also apply
it to getcwd etc. (Bug#27871)
---
 src/sysdep.c | 39 ++++++++++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/src/sysdep.c b/src/sysdep.c
index 8291a60..c348492 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -221,9 +221,12 @@ init_standard_fds (void)
 }
 
 /* Return the current working directory.  The result should be freed
-   with 'free'.  Return NULL on errors.  */
-char *
-emacs_get_current_dir_name (void)
+   with 'free'.  Return NULL (setting errno) on errors.  If the
+   current directory is unreachable, return either NULL or a string
+   beginning with '('.  */
+
+static char *
+get_current_dir_name_or_unreachable (void)
 {
 # if HAVE_GET_CURRENT_DIR_NAME && !BROKEN_GET_CURRENT_DIR_NAME
 #  ifdef HYBRID_MALLOC
@@ -233,16 +236,9 @@ emacs_get_current_dir_name (void)
 #  endif
   if (use_libc)
     {
-      /* GNU/Linux get_current_dir_name can return a string starting
-	 with "(unreachable)" (Bug#27871).  */
-      char *wd = get_current_dir_name ();
-      if (wd && ! (IS_DIRECTORY_SEP (*wd) || (*wd && IS_DEVICE_SEP (wd[1]))))
-	{
-	  free (wd);
-	  errno = ENOENT;
-	  return NULL;
-	}
-      return wd;
+      /* For an unreachable directory, this returns a string that starts
+	 with "(unreachable)"; see Bug#27871.  */
+      return get_current_dir_name ();
     }
 # endif
 
@@ -294,6 +290,23 @@ emacs_get_current_dir_name (void)
   return buf;
 }
 
+/* Return the current working directory.  The result should be freed
+   with 'free'.  Return NULL (setting errno) on errors; an unreachable
+   directory (e.g., its name starts with '(') counts as an error.  */
+
+char *
+emacs_get_current_dir_name (void)
+{
+  char *dir = get_current_dir_name_or_unreachable ();
+  if (dir && *dir == '(')
+    {
+      free (dir);
+      errno = ENOENT;
+      return NULL;
+    }
+  return dir;
+}
+
 
 /* Discard pending input on all input descriptors.  */
 
-- 
2.7.4