about summary refs log tree commit diff
path: root/sysdeps/mach/hurd/dl-sysdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd/dl-sysdep.c')
-rw-r--r--sysdeps/mach/hurd/dl-sysdep.c251
1 files changed, 36 insertions, 215 deletions
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index 8bcce13588..d30717b197 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -29,8 +29,7 @@
 #include <sysdep.h>
 #include <mach/mig_support.h>
 #include "hurdstartup.h"
-#include <mach/host_info.h>
-#include <stdio-common/_itoa.h>
+#include <hurd/lookup.h>
 #include <hurd/auth.h>
 #include <hurd/term.h>
 #include <stdarg.h>
@@ -266,20 +265,37 @@ _dl_sysdep_start_cleanup (void)
    dynamic linker re-relocates itself to be user-visible (for -ldl),
    it will get the user's definition (i.e. usually libc's).  */
 
-/* Open FILE_NAME and return a Hurd I/O for it in *PORT, or
-   return an error.  If STAT is non-zero, stat the file into that stat buffer.  */
+/* Open FILE_NAME and return a Hurd I/O for it in *PORT, or return an
+   error.  If STAT is non-zero, stat the file into that stat buffer.  */
 static error_t
-open_file (const char *file_name, int mode,
+open_file (const char *file_name, int flags,
 	   mach_port_t *port, struct stat *stat)
 {
   enum retry_type doretry;
   char retryname[1024];		/* XXX string_t LOSES! */
-  file_t startdir, newpt, fileport;
-  int dealloc_dir;
-  int nloops;
+  file_t startdir;
   error_t err;
 
-  assert (!(mode & ~O_READ));
+  error_t use_init_port (int which, error_t (*operate) (file_t))
+    {
+      return (which < _dl_hurd_data->portarraysize
+	      ? ((*operate) (_dl_hurd_data->portarray[which]))
+	      : EGRATUITOUS);
+    }
+  file_t get_dtable_port (int fd)
+    {
+      if ((unsigned int) fd < _dl_hurd_data->dtablesize
+	  && _dl_hurd_data->dtable[fd] != MACH_PORT_NULL)
+	{
+	  __mach_port_mod_refs (__mach_task_self (), _dl_hurd_data->dtable[fd],
+				MACH_PORT_RIGHT_SEND, +1);
+	  return _dl_hurd_data->dtable[fd];
+	}
+      errno = EBADF;
+      return MACH_PORT_NULL;
+    }
+
+  assert (!(flags & ~O_READ));
 
   startdir = _dl_hurd_data->portarray[file_name[0] == '/' ?
 				      INIT_PORT_CRDIR : INIT_PORT_CWDIR];
@@ -287,216 +303,21 @@ open_file (const char *file_name, int mode,
   while (file_name[0] == '/')
     file_name++;
 
-  if (err = __dir_lookup (startdir, (char *)file_name, mode, 0,
-			  &doretry, retryname, &fileport))
-    return err;
+  err = __dir_lookup (startdir, (char *)file_name, O_RDONLY, 0,
+		      &doretry, retryname, port);
 
-  dealloc_dir = 0;
-  nloops = 0;
-
-  while (1)
+  if (!err)
+    err = __hurd_file_name_lookup_retry (use_init_port, get_dtable_port,
+					 __dir_lookup, doretry, retryname,
+					 O_RDONLY, 0, port);
+  if (!err && stat)
     {
-      if (dealloc_dir)
-	__mach_port_deallocate (__mach_task_self (), startdir);
+      err = __io_stat (*port, stat);
       if (err)
-	return err;
-
-      switch (doretry)
-	{
-	case FS_RETRY_REAUTH:
-	  {
-	    mach_port_t ref = __mach_reply_port ();
-	    err = __io_reauthenticate (fileport, ref, MACH_MSG_TYPE_MAKE_SEND);
-	    if (! err)
-	      err = __auth_user_authenticate
-		(_dl_hurd_data->portarray[INIT_PORT_AUTH],
-		 ref, MACH_MSG_TYPE_MAKE_SEND,
-		 &newpt);
-	    __mach_port_destroy (__mach_task_self (), ref);
-	  }
-	  __mach_port_deallocate (__mach_task_self (), fileport);
-	  if (err)
-	    return err;
-	  fileport = newpt;
-	  /* Fall through.  */
-
-	case FS_RETRY_NORMAL:
-#ifdef SYMLOOP_MAX
-	  if (nloops++ >= SYMLOOP_MAX)
-	    return ELOOP;
-#endif
-
-	  /* An empty RETRYNAME indicates we have the final port.  */
-	  if (retryname[0] == '\0')
-	    {
-	      dealloc_dir = 1;
-	    opened:
-	      /* We have the file open.  Now map it.  */
-	      if (stat)
-		err = __io_stat (fileport, stat);
-
-	      if (err)
-		{
-		  if (dealloc_dir)
-		    __mach_port_deallocate (__mach_task_self (), fileport);
-		}
-	      else
-		{
-		  if (!dealloc_dir)
-		    __mach_port_mod_refs (__mach_task_self (), fileport,
-					  MACH_PORT_RIGHT_SEND, 1);
-		  *port = fileport;
-		}
-
-	      return err;
-	    }
-
-	  startdir = fileport;
-	  dealloc_dir = 1;
-	  file_name = retryname;
-	  break;
-
-	case FS_RETRY_MAGICAL:
-	  switch (retryname[0])
-	    {
-	    case '/':
-	      startdir = _dl_hurd_data->portarray[INIT_PORT_CRDIR];
-	      dealloc_dir = 0;
-	      if (fileport != MACH_PORT_NULL)
-		__mach_port_deallocate (__mach_task_self (), fileport);
-	      file_name = &retryname[1];
-	      break;
-
-	    case 'f':
-	      if (retryname[1] == 'd' && retryname[2] == '/' &&
-		  isdigit (retryname[3]))
-		{
-		  /* We can't use strtol for the decoding here
-		     because it brings in hairy locale bloat.  */
-		  char *p;
-		  int fd = 0;
-		  for (p = &retryname[3]; isdigit (*p); ++p)
-		    fd = (fd * 10) + (*p - '0');
-		  /* Check for excess text after the number.  A slash is
-		     valid; it ends the component.  Anything else does not
-		     name a numeric file descriptor.  */
-		  if (*p != '/' && *p != '\0')
-		    return ENOENT;
-		  if (fd < 0 || fd >= _dl_hurd_data->dtablesize ||
-		      _dl_hurd_data->dtable[fd] == MACH_PORT_NULL)
-		    /* If the name was a proper number, but the file
-		       descriptor does not exist, we return EBADF instead
-		       of ENOENT.  */
-		    return EBADF;
-		  fileport = _dl_hurd_data->dtable[fd];
-		  if (*p == '\0')
-		    {
-		      /* This descriptor is the file port we want.  */
-		      dealloc_dir = 0;
-		      goto opened;
-		    }
-		  else
-		    {
-		      /* Do a normal retry on the remaining components.  */
-		      startdir = fileport;
-		      dealloc_dir = 1;
-		      file_name = p + 1; /* Skip the slash.  */
-		      break;
-		    }
-		}
-	      else
-		goto bad_magic;
-	      break;
-
-	    case 'm':
-	      if (retryname[1] == 'a' && retryname[2] == 'c' &&
-		  retryname[3] == 'h' && retryname[4] == 't' &&
-		  retryname[5] == 'y' && retryname[6] == 'p' &&
-		  retryname[7] == 'e')
-		{
-		  error_t err;
-		  struct host_basic_info hostinfo;
-		  mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT;
-		  char *p;
-		  if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO,
-					 (natural_t *) &hostinfo,
-					 &hostinfocnt))
-		    return err;
-		  if (hostinfocnt != HOST_BASIC_INFO_COUNT)
-		    return EGRATUITOUS;
-		  p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0);
-		  *--p = '/';
-		  p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0);
-		  if (p < retryname)
-		    abort ();	/* XXX write this right if this ever happens */
-		  if (p > retryname)
-		    strcpy (retryname, p);
-		  startdir = fileport;
-		  dealloc_dir = 1;
-		}
-	      else
-		goto bad_magic;
-	      break;
-
-	    case 't':
-	      if (retryname[1] == 't' && retryname[2] == 'y')
-		switch (retryname[3])
-		  {
-		    error_t opentty (file_t *result)
-		      {
-			error_t err;
-			file_t unauth;
-			err = __termctty_open_terminal
-			  (_dl_hurd_data->portarray[INIT_PORT_CTTYID],
-			   mode, &unauth);
-			if (! err)
-			  {
-			    mach_port_t ref = __mach_reply_port ();
-			    err = __io_reauthenticate
-			      (unauth, ref, MACH_MSG_TYPE_MAKE_SEND);
-			    if (! err)
-			      err = __auth_user_authenticate
-				(_dl_hurd_data->portarray[INIT_PORT_AUTH],
-				 ref, MACH_MSG_TYPE_MAKE_SEND,
-				 result);
-			    __mach_port_deallocate (__mach_task_self (),
-						    unauth);
-			    __mach_port_destroy (__mach_task_self (), ref);
-			  }
-			return err;
-		      }
-
-		  case '\0':
-		    if (err = opentty (&fileport))
-		      return err;
-		    dealloc_dir = 1;
-		    goto opened;
-		  case '/':
-		    if (err = opentty (&startdir))
-		      return err;
-		    dealloc_dir = 1;
-		    strcpy (retryname, &retryname[4]);
-		    break;
-		  default:
-		    goto bad_magic;
-		  }
-	      else
-		goto bad_magic;
-	      break;
-
-	    default:
-	    bad_magic:
-	      return EGRATUITOUS;
-	    }
-	  break;
-
-	default:
-	  return EGRATUITOUS;
-	}
-
-      err = __dir_lookup (startdir, (char *)file_name, mode, 0,
-			  &doretry, retryname, &fileport);
+	__mach_port_deallocate (__mach_task_self (), *port);
     }
+
+  return err;
 }
 
 int weak_function