about summary refs log tree commit diff
path: root/sysdeps/mach
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2018-12-07 15:01:40 +0100
committerFlorian Weimer <fweimer@redhat.com>2018-12-07 16:04:05 +0100
commit7c857b6f0db01e8d6876e601f0cbcd21d23e4dd5 (patch)
treebb1326962589e7c74416aa329bb68c56f7f195d2 /sysdeps/mach
parent3a3fb7557274108ea3dc5ac62333c808a6c171db (diff)
downloadglibc-7c857b6f0db01e8d6876e601f0cbcd21d23e4dd5.tar.gz
glibc-7c857b6f0db01e8d6876e601f0cbcd21d23e4dd5.tar.xz
glibc-7c857b6f0db01e8d6876e601f0cbcd21d23e4dd5.zip
hurd: Implement support for posix_spawn_file_actions_addfchdir_np
Diffstat (limited to 'sysdeps/mach')
-rw-r--r--sysdeps/mach/hurd/spawni.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
index b98e991d3b..16c927be24 100644
--- a/sysdeps/mach/hurd/spawni.c
+++ b/sysdeps/mach/hurd/spawni.c
@@ -259,6 +259,46 @@ __spawni (pid_t *pid, const char *file,
 
       return err;
     }
+  inline error_t child_lookup_under (file_t startdir, const char *file,
+				     int oflag, mode_t mode, file_t *result)
+    {
+      error_t use_init_port (int which, error_t (*operate) (mach_port_t))
+	{
+	  return (which == INIT_PORT_CWDIR ? (*operate) (startdir) :
+		  child_init_port (which, operate));
+	}
+
+      return __hurd_file_name_lookup (&use_init_port, &child_fd, 0,
+				      file, oflag, mode, result);
+    }
+  auto error_t child_fchdir (int fd)
+    {
+      file_t new_ccwdir;
+      error_t err;
+
+      if ((unsigned int)fd >= dtablesize
+	  || dtable[fd] == MACH_PORT_NULL)
+	return EBADF;
+
+      /* We look up "." to force ENOTDIR if it's not a directory and EACCES if
+         we don't have search permission.  */
+      if (dtable_cells[fd] != NULL)
+	  err = HURD_PORT_USE (dtable_cells[fd],
+		    ({
+		      child_lookup_under (port, ".", O_NOTRANS, 0, &new_ccwdir);
+		     }));
+      else
+	  err = child_lookup_under (dtable[fd], ".", O_NOTRANS, 0, &new_ccwdir);
+
+      if (!err)
+	{
+	  if (ccwdir != MACH_PORT_NULL)
+	    __mach_port_deallocate (__mach_task_self (), ccwdir);
+	  ccwdir = new_ccwdir;
+	}
+
+      return err;
+    }
 
 
   /* Do this once.  */
@@ -553,6 +593,10 @@ __spawni (pid_t *pid, const char *file,
 	  case spawn_do_chdir:
 	    err = child_chdir (action->action.chdir_action.path);
 	    break;
+
+	  case spawn_do_fchdir:
+	    err = child_fchdir (action->action.fchdir_action.fd);
+	    break;
 	  }
 
 	if (err)