Exemplo n.º 1
0
/* Change the permissions of the file referenced by FD to MODE.  */
int
__fchmod (int fd, mode_t mode)
{
  error_t err;

  if (err = HURD_DPORT_USE (fd, __file_chmod (port, mode)))
    return __hurd_dfail (fd, err);

  return 0;
}
Exemplo n.º 2
0
/* Apply or remove an advisory lock, according to OPERATION,
   on the file FD refers to.  */
int
__flock (int fd, int operation)
{
  error_t err;

  if (err = HURD_DPORT_USE (fd, __file_lock (port, operation)))
    return __hurd_dfail (fd, err);

  return 0;
}
Exemplo n.º 3
0
/* Return information about the filesystem on which FD resides.  */
int
__fstatfs (int fd, struct statfs *buf)
{
  error_t err;

  if (err = HURD_DPORT_USE (fd, __file_statfs (port, buf)))
    return __hurd_dfail (fd, err);

  return 0;
}
Exemplo n.º 4
0
/* Get file-specific information about descriptor FD.  */
long int
__fpathconf (int fd, int name)
{
  error_t err;
  int value;

  if (err = HURD_DPORT_USE (fd, __io_pathconf (port, name, &value)))
    return __hurd_dfail (fd, err), -1L;

  return value;
}
Exemplo n.º 5
0
/* Return the pathname of the terminal FD is open on, or NULL on errors.
   The returned storage is good only until the next call to this function.  */
char *
ttyname (int fd)
{
  error_t err;
  static char nodename[1024];	/* XXX */

  nodename[0] = '\0';
  if (err = HURD_DPORT_USE (fd, __term_get_nodename (port, nodename)))
    return __hurd_dfail (fd, err), NULL;

  return nodename;
}
Exemplo n.º 6
0
/* Return 1 if FD is a terminal, 0 if not.  */
int
__isatty (int fd)
{
  error_t err;
  mach_port_t id;

  err = HURD_DPORT_USE (fd, __term_getctty (port, &id));
  if (! err)
    __mach_port_deallocate (__mach_task_self (), id);

  return !err;
}
Exemplo n.º 7
0
/* Get information about the file descriptor FD in BUF.  */
int
__fxstat64 (int vers, int fd, struct stat64 *buf)
{
  error_t err;

  if (vers != _STAT_VER)
    return __hurd_fail (EINVAL);

  if (err = HURD_DPORT_USE (fd, __io_stat (port, buf)))
    return __hurd_dfail (fd, err);

  return 0;
}
Exemplo n.º 8
0
/* Set socket FD's option OPTNAME at protocol level LEVEL
   to *OPTVAL (which is OPTLEN bytes long).
   Returns 0 on success, -1 for errors.  */
int
__setsockopt (int fd,
	      int level,
	      int optname,
	      const void *optval,
	      socklen_t optlen)
{
  error_t err = HURD_DPORT_USE (fd, __socket_setopt (port,
						     level, optname,
						     optval, optlen));
  if (err)
    return __hurd_dfail (fd, err);
  return 0;
}
Exemplo n.º 9
0
/* Make all changes done to FD's file data actually appear on disk.  */
int
fdatasync (int fd)
{
  error_t err = HURD_DPORT_USE (fd, __file_sync (port, 1, 1));
  if (err)
    {
      if (err == EOPNOTSUPP)
	/* If the file descriptor does not support sync, return EINVAL
	   as POSIX specifies.  */
	err = EINVAL;
      return __hurd_dfail (fd, err);
    }
  return 0;
}
Exemplo n.º 10
0
/* Return the pathname of the terminal FD is open on, or NULL on errors.
   The returned storage is good only until the next call to this function.  */
char *
ttyname (int fd)
{
  error_t err;
  static char nodename[1024];	/* XXX */

  nodename[0] = '\0';
  if (err = HURD_DPORT_USE (fd, __term_get_nodename (port, nodename)))
    {
      if (err == MIG_BAD_ID || err == EOPNOTSUPP)
	err = ENOTTY;
      return __hurd_dfail (fd, err), NULL;
    }

  return nodename;
}
Exemplo n.º 11
0
/* Send N bytes of BUF to socket FD.  Returns the number sent or -1.  */
ssize_t
__send (int fd, const void *buf, size_t n, int flags)
{
  error_t err;
  size_t wrote;

  err = HURD_DPORT_USE (fd, __socket_send (port, MACH_PORT_NULL,
					   flags, buf, n,
					   NULL, MACH_MSG_TYPE_COPY_SEND, 0,
					   NULL, 0, &wrote));

  if (err == MIG_BAD_ID || err == EOPNOTSUPP)
    /* The file did not grok the socket protocol.  */
    err = ENOTSOCK;

  return err ? __hurd_sockfail (fd, flags, err) : wrote;
}
Exemplo n.º 12
0
/* Store at most BUFLEN characters of the pathname of the slave pseudo
   terminal associated with the master FD is open on in BUF.
   Return 0 on success, otherwise an error number.  */
int
__ptsname_r (int fd, char *buf, size_t buflen)
{
  string_t peername;
  size_t len;
  error_t err;

  if (err = HURD_DPORT_USE (fd, __term_get_peername (port, peername)))
    return __hurd_dfail (fd, err), errno;

  len = __strnlen (peername, sizeof peername - 1) + 1;
  if (len > buflen)
    {
      errno = ERANGE;
      return ERANGE;
    }

  memcpy (buf, peername, len);
  return 0;
}
Exemplo n.º 13
0
/* Store at most BUFLEN characters of the pathname of the terminal FD is
   open on in BUF.  Return 0 on success, -1 otherwise.  */
int
__ttyname_r (int fd, char *buf, size_t buflen)
{
  error_t err;
  char nodename[1024];	/* XXX */
  size_t len;

  nodename[0] = '\0';
  if (err = HURD_DPORT_USE (fd, __term_get_nodename (port, nodename)))
    return __hurd_dfail (fd, err), -1;

  len = strlen (nodename) + 1;
  if (len > buflen)
    {
      errno = EINVAL;
      return -1;
    }

  memcpy (buf, nodename, len);
  return 0;
}
Exemplo n.º 14
0
file_t
__file_name_lookup_at (int fd, int at_flags,
		       const char *file_name, int flags, mode_t mode)
{
  error_t err;
  file_t result;

  if ((at_flags & AT_SYMLINK_FOLLOW) && (at_flags & AT_SYMLINK_NOFOLLOW))
    return (__hurd_fail (EINVAL), MACH_PORT_NULL);

  flags |= (at_flags & AT_SYMLINK_NOFOLLOW) ? O_NOLINK : 0;
  at_flags &= ~AT_SYMLINK_NOFOLLOW;
  if (at_flags & AT_SYMLINK_FOLLOW)
    flags &= ~O_NOLINK;
  at_flags &= ~AT_SYMLINK_FOLLOW;
  if (at_flags != 0)
    return (__hurd_fail (EINVAL), MACH_PORT_NULL);

  if (fd == AT_FDCWD || file_name[0] == '/')
    return __file_name_lookup (file_name, flags, mode);

  file_t startdir;
  error_t use_init_port (int which, error_t (*operate) (mach_port_t))
    {
      return (which == INIT_PORT_CWDIR ? (*operate) (startdir) :
	      _hurd_ports_use (which, operate));
    }

  err = HURD_DPORT_USE (fd, (startdir = port,
			     __hurd_file_name_lookup (&use_init_port,
						      &__getdport, NULL,
						      file_name,
						      flags,
						      mode & ~_hurd_umask,
						      &result)));

  return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
}
Exemplo n.º 15
0
/* Change the access time of FD to TVP[0] and
   the modification time of FD to TVP[1].  */
int
__futimes (int fd, const struct timeval tvp[2])
{
  union tv
  {
    struct timeval tv;
    time_value_t tvt;
  };
  const union tv *u = (const union tv *) tvp;
  union tv nulltv[2];
  error_t err;

  if (tvp == NULL)
    {
      /* Setting the number of microseconds to `-1' tells the
         underlying filesystems to use the current time.  */
      nulltv[0].tvt.microseconds = nulltv[1].tvt.microseconds = -1;
      u = nulltv;
    }

  err = HURD_DPORT_USE (fd, __file_utimes (port, u[0].tvt, u[1].tvt));
  return err ? __hurd_dfail (fd, err) : 0;
}
Exemplo n.º 16
0
file_t
__directory_name_split_at (int fd, const char *directory_name, char **name)
{
  error_t err;
  file_t result;

  if (fd == AT_FDCWD || directory_name[0] == '/')
    return __directory_name_split (directory_name, name);

  file_t startdir;
  error_t use_init_port (int which, error_t (*operate) (mach_port_t))
    {
      return (which == INIT_PORT_CWDIR ? (*operate) (startdir) :
	      _hurd_ports_use (which, operate));
    }

  err = HURD_DPORT_USE (fd, (startdir = port,
			     __hurd_directory_name_split (&use_init_port,
							  &__getdport, 0,
							  directory_name,
							  &result, name)));

  return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
}
Exemplo n.º 17
0
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.  */

#include <ansidecl.h>
#include <errno.h>
#include <unistd.h>
#include <hurd.h>
#include <hurd/fd.h>

/* Make all changes done to FD actually appear on disk.  */
int
DEFUN(fsync, (fd), int fd)
{
  error_t err = HURD_DPORT_USE (fd, __file_sync (port, 1));
  if (err)
    return __hurd_dfail (fd, err);
  return 0;
}
Exemplo n.º 18
0
Arquivo: send.c Projeto: angelhunt/SNP
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.  */

#include <ansidecl.h>
#include <errno.h>
#include <sys/socket.h>
#include <hurd.h>
#include <hurd/socket.h>
#include <hurd/fd.h>

/* Send N bytes of BUF to socket FD.  Returns the number sent or -1.  */
int
DEFUN(send, (fd, buf, n, flags),
      int fd AND PTR buf AND size_t n AND int flags)
{
  error_t err;
  int wrote;

  err = HURD_DPORT_USE (fd, __socket_send (port, MACH_PORT_NULL,
					   flags, buf, n,
					   NULL, MACH_MSG_TYPE_COPY_SEND, 0,
					   NULL, 0, &wrote));

  return err ? __hurd_dfail (fd, err) : wrote;
}
Exemplo n.º 19
0
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
  error_t err;
  vm_prot_t vmprot;
  memory_object_t memobj;
  vm_address_t mapaddr;
  vm_size_t pageoff;

  mapaddr = (vm_address_t) addr;

  if ((flags & (MAP_TYPE|MAP_INHERIT)) == MAP_ANON
      && prot == (PROT_READ|PROT_WRITE)) /* cf VM_PROT_DEFAULT */
    {
      /* vm_allocate has (a little) less overhead in the kernel too.  */
      err = __vm_allocate (__mach_task_self (), &mapaddr, len,
			   !(flags & MAP_FIXED));

      if (err == KERN_NO_SPACE && (flags & MAP_FIXED))
	{
	  /* XXX this is not atomic as it is in unix! */
	  /* The region is already allocated; deallocate it first.  */
	  err = __vm_deallocate (__mach_task_self (), mapaddr, len);
	  if (!err)
	    err = __vm_allocate (__mach_task_self (), &mapaddr, len, 0);
	}

      return err ? (__ptr_t) (long int) __hurd_fail (err) : (__ptr_t) mapaddr;
    }

  pageoff = offset & (vm_page_size - 1);
  offset &= ~(vm_page_size - 1);

  if (flags & MAP_FIXED)
    {
      /* A specific address is requested.  It need not be page-aligned;
	 it just needs to be congruent with the object offset.  */
      if ((mapaddr & (vm_page_size - 1)) != pageoff)
	return (__ptr_t) (long int) __hurd_fail (EINVAL);
      else
	/* We will add back PAGEOFF after mapping.  */
	mapaddr -= pageoff;
    }

  vmprot = VM_PROT_NONE;
  if (prot & PROT_READ)
    vmprot |= VM_PROT_READ;
  if (prot & PROT_WRITE)
    vmprot |= VM_PROT_WRITE;
  if (prot & PROT_EXEC)
    vmprot |= VM_PROT_EXECUTE;

  switch (flags & MAP_TYPE)
    {
    default:
      return (__ptr_t) (long int) __hurd_fail (EINVAL);

    case MAP_ANON:
      memobj = MACH_PORT_NULL;
      break;

    case MAP_FILE:
    case 0:			/* Allow, e.g., just MAP_SHARED.  */
      {
	mach_port_t robj, wobj;
	if (err = HURD_DPORT_USE (fd, __io_map (port, &robj, &wobj)))
	  return (__ptr_t) (long int) __hurd_dfail (fd, err);
	switch (prot & (PROT_READ|PROT_WRITE))
	  {
	  case PROT_READ:
	    memobj = robj;
	    if (wobj != MACH_PORT_NULL)
	      __mach_port_deallocate (__mach_task_self (), wobj);
	    break;
	  case PROT_WRITE:
	    memobj = wobj;
	    if (robj != MACH_PORT_NULL)
	      __mach_port_deallocate (__mach_task_self (), robj);
	    break;
	  case PROT_READ|PROT_WRITE:
	    if (robj == wobj)
	      {
		memobj = wobj;
		/* Remove extra reference.  */
		__mach_port_deallocate (__mach_task_self (), memobj);
	      }
	    else if (wobj == MACH_PORT_NULL && /* Not writable by mapping.  */
		     !(flags & MAP_SHARED))
	      /* The file can only be mapped for reading.  Since we are
		 making a private mapping, we will never try to write the
		 object anyway, so we don't care.  */
	      memobj = robj;
	    else
	      {
		__mach_port_deallocate (__mach_task_self (), wobj);
		return (__ptr_t) (long int) __hurd_fail (EACCES);
	      }
	    break;
	  }
	break;
	/* XXX handle MAP_NOEXTEND */
      }
    }

  /* XXX handle MAP_INHERIT */

  err = __vm_map (__mach_task_self (),
		  &mapaddr, (vm_size_t) len, (vm_address_t) 0,
		  ! (flags & MAP_FIXED),
		  memobj, (vm_offset_t) offset,
		  ! (flags & MAP_SHARED),
		  vmprot, VM_PROT_ALL,
		  (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);

  if (err == KERN_NO_SPACE && (flags & MAP_FIXED))
    {
      /* XXX this is not atomic as it is in unix! */
      /* The region is already allocated; deallocate it first.  */
      err = __vm_deallocate (__mach_task_self (), mapaddr, len);
      if (! err)
	err = __vm_map (__mach_task_self (),
			&mapaddr, (vm_size_t) len, (vm_address_t) 0,
			0, memobj, (vm_offset_t) offset,
			! (flags & MAP_SHARED),
			vmprot, VM_PROT_ALL,
			(flags & MAP_SHARED) ? VM_INHERIT_SHARE
			: VM_INHERIT_COPY);
    }

  if (memobj != MACH_PORT_NULL)
    __mach_port_deallocate (__mach_task_self (), memobj);

  if (err)
    return (__ptr_t) (long int) __hurd_fail (err);

  /* Adjust the mapping address for the offset-within-page.  */
  mapaddr += pageoff;

  return (__ptr_t) mapaddr;
}
Exemplo n.º 20
0
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.  */

#include <ansidecl.h>
#include <errno.h>
#include <sys/socket.h>
#include <hurd.h>
#include <hurd/socket.h>
#include <hurd/fd.h>

/* Shut down all or part of the connection open on socket FD.
   HOW determines what to shut down:
     0 = No more receptions;
     1 = No more transmissions;
     2 = No more receptions or transmissions.
   Returns 0 on success, -1 for errors.  */
int
DEFUN(shutdown, (fd, how),
      int fd AND int how)
{
  error_t err = HURD_DPORT_USE (fd, __socket_shutdown (port, how));
  if (err)
    return __hurd_dfail (fd, err);
  return 0;
}
Exemplo n.º 21
0
__ptr_t
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
{
  error_t err;
  vm_prot_t vmprot;
  memory_object_t memobj;
  vm_address_t mapaddr;

  mapaddr = (vm_address_t) addr;

  /* ADDR and OFFSET must be page-aligned.  */
  if ((mapaddr & (__vm_page_size - 1)) || (offset & (__vm_page_size - 1)))
    return (__ptr_t) (long int) __hurd_fail (EINVAL);

  if ((flags & (MAP_TYPE|MAP_INHERIT)) == MAP_ANON
      && prot == (PROT_READ|PROT_WRITE)) /* cf VM_PROT_DEFAULT */
    {
      /* vm_allocate has (a little) less overhead in the kernel too.  */
      err = __vm_allocate (__mach_task_self (), &mapaddr, len, mapaddr == 0);

      if (err == KERN_NO_SPACE)
	{
	  if (flags & MAP_FIXED)
	    {
	      /* XXX this is not atomic as it is in unix! */
	      /* The region is already allocated; deallocate it first.  */
	      err = __vm_deallocate (__mach_task_self (), mapaddr, len);
	      if (!err)
		err = __vm_allocate (__mach_task_self (), &mapaddr, len, 0);
	    }
	  else if (mapaddr != 0)
	    err = __vm_allocate (__mach_task_self (), &mapaddr, len, 1);
	}

      return err ? (__ptr_t) (long int) __hurd_fail (err) : (__ptr_t) mapaddr;
    }

  vmprot = VM_PROT_NONE;
  if (prot & PROT_READ)
    vmprot |= VM_PROT_READ;
  if (prot & PROT_WRITE)
    vmprot |= VM_PROT_WRITE;
  if (prot & PROT_EXEC)
    vmprot |= VM_PROT_EXECUTE;

  switch (flags & MAP_TYPE)
    {
    default:
      return (__ptr_t) (long int) __hurd_fail (EINVAL);

    case MAP_ANON:
      memobj = MACH_PORT_NULL;
      break;

    case MAP_FILE:
    case 0:			/* Allow, e.g., just MAP_SHARED.  */
      {
	mach_port_t robj, wobj;
	if (err = HURD_DPORT_USE (fd, __io_map (port, &robj, &wobj)))
	  {
	    if (err == MIG_BAD_ID || err == EOPNOTSUPP || err == ENOSYS)
	      err = ENODEV;	/* File descriptor doesn't support mmap.  */
	    return (__ptr_t) (long int) __hurd_dfail (fd, err);
	  }
	switch (prot & (PROT_READ|PROT_WRITE))
	  {
	  /* Although it apparently doesn't make sense to map a file with
	     protection set to PROT_NONE, it is actually sometimes done.
	     In particular, that's how localedef reserves some space for
	     the locale archive file, the rationale being that some
	     implementations take into account whether the mapping is
	     anonymous or not when selecting addresses.  */
	  case PROT_NONE:
	  case PROT_READ:
	    memobj = robj;
	    if (wobj != MACH_PORT_NULL)
	      __mach_port_deallocate (__mach_task_self (), wobj);
	    break;
	  case PROT_WRITE:
	    memobj = wobj;
	    if (robj != MACH_PORT_NULL)
	      __mach_port_deallocate (__mach_task_self (), robj);
	    break;
	  case PROT_READ|PROT_WRITE:
	    if (robj == wobj)
	      {
		memobj = wobj;
		/* Remove extra reference.  */
		__mach_port_deallocate (__mach_task_self (), memobj);
	      }
	    else if (wobj == MACH_PORT_NULL && /* Not writable by mapping.  */
		     !(flags & MAP_SHARED))
	      /* The file can only be mapped for reading.  Since we are
		 making a private mapping, we will never try to write the
		 object anyway, so we don't care.  */
	      memobj = robj;
	    else
	      {
		__mach_port_deallocate (__mach_task_self (), wobj);
		return (__ptr_t) (long int) __hurd_fail (EACCES);
	      }
	    break;
	  default:
	    __builtin_unreachable ();
	  }
	break;
	/* XXX handle MAP_NOEXTEND */
      }
    }

  /* XXX handle MAP_INHERIT */

  err = __vm_map (__mach_task_self (),
		  &mapaddr, (vm_size_t) len, (vm_address_t) 0,
		  mapaddr == 0,
		  memobj, (vm_offset_t) offset,
		  ! (flags & MAP_SHARED),
		  vmprot, VM_PROT_ALL,
		  (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);

  if (err == KERN_NO_SPACE)
    {
      if (flags & MAP_FIXED)
	{
	  /* XXX this is not atomic as it is in unix! */
	  /* The region is already allocated; deallocate it first.  */
	  err = __vm_deallocate (__mach_task_self (), mapaddr, len);
	  if (! err)
	    err = __vm_map (__mach_task_self (),
			    &mapaddr, (vm_size_t) len, (vm_address_t) 0,
			    0, memobj, (vm_offset_t) offset,
			    ! (flags & MAP_SHARED),
			    vmprot, VM_PROT_ALL,
			    (flags & MAP_SHARED) ? VM_INHERIT_SHARE
			    : VM_INHERIT_COPY);
	}
      else if (mapaddr != 0)
	err = __vm_map (__mach_task_self (),
			&mapaddr, (vm_size_t) len, (vm_address_t) 0,
			1, memobj, (vm_offset_t) offset,
			! (flags & MAP_SHARED),
			vmprot, VM_PROT_ALL,
			(flags & MAP_SHARED) ? VM_INHERIT_SHARE
			: VM_INHERIT_COPY);
    }

  if (memobj != MACH_PORT_NULL)
    __mach_port_deallocate (__mach_task_self (), memobj);

  if (err)
    return (__ptr_t) (long int) __hurd_fail (err);

  return (__ptr_t) mapaddr;
}
Exemplo n.º 22
0
/* Receive a message as described by MESSAGE from socket FD.
   Returns the number of bytes read or -1 for errors.  */
ssize_t
__libc_recvmsg (int fd, struct msghdr *message, int flags)
{
  error_t err;
  addr_port_t aport;
  char *data = NULL;
  mach_msg_type_number_t len = 0;
  mach_port_t *ports;
  mach_msg_type_number_t nports = 0;
  char *cdata = NULL;
  mach_msg_type_number_t clen = 0;
  size_t amount;
  char *buf;
  int i;

  /* Find the total number of bytes to be read.  */
  amount = 0;
  for (i = 0; i < message->msg_iovlen; i++)
    {
      amount += message->msg_iov[i].iov_len;

      /* As an optimization, we set the initial values of DATA and LEN
         from the first non-empty iovec.  This kicks-in in the case
         where the whole packet fits into that iovec buffer.  */
      if (data == NULL && message->msg_iov[i].iov_len > 0)
	{
	  data = message->msg_iov[i].iov_base;
	  len = message->msg_iov[i].iov_len;
	}
    }

  buf = data;
  if (err = HURD_DPORT_USE (fd, __socket_recv (port, &aport,
					       flags, &data, &len,
					       &ports, &nports,
					       &cdata, &clen,
					       &message->msg_flags, amount)))
    return __hurd_sockfail (fd, flags, err);

  if (message->msg_name != NULL && aport != MACH_PORT_NULL)
    {
      char *buf = message->msg_name;
      mach_msg_type_number_t buflen = message->msg_namelen;
      int type;

      err = __socket_whatis_address (aport, &type, &buf, &buflen);
      if (err == EOPNOTSUPP)
	/* If the protocol server can't tell us the address, just return a
	   zero-length one.  */
	{
	  buf = message->msg_name;
	  buflen = 0;
	  err = 0;
	}

      if (err)
	{
	  __mach_port_deallocate (__mach_task_self (), aport);
	  return __hurd_sockfail (fd, flags, err);
	}

      if (message->msg_namelen > buflen)
	message->msg_namelen = buflen;

      if (buf != message->msg_name)
	{
	  memcpy (message->msg_name, buf, message->msg_namelen);
	  __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
	}

      if (buflen > 0)
	((struct sockaddr *) message->msg_name)->sa_family = type;
    }
  else if (message->msg_name != NULL)
    message->msg_namelen = 0;

  __mach_port_deallocate (__mach_task_self (), aport);

  if (buf == data)
    buf += len;
  else
    {
      /* Copy the data into MSG.  */
      if (len > amount)
	message->msg_flags |= MSG_TRUNC;
      else
	amount = len;

      buf = data;
      for (i = 0; i < message->msg_iovlen; i++)
	{
#define min(a, b)	((a) > (b) ? (b) : (a))
	  size_t copy = min (message->msg_iov[i].iov_len, amount);

	  memcpy (message->msg_iov[i].iov_base, buf, copy);

	  buf += copy;
	  amount -= copy;
	  if (len == 0)
	    break;
	}

      __vm_deallocate (__mach_task_self (), (vm_address_t) data, len);
    }

  /* Copy the control message into MSG.  */
  if (clen > message->msg_controllen)
    message->msg_flags |= MSG_CTRUNC;
  else
    message->msg_controllen = clen;
  memcpy (message->msg_control, cdata, message->msg_controllen);

  __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);

  return (buf - data);
}