Beispiel #1
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;
  int empty = at_flags & AT_EMPTY_PATH;

  at_flags &= ~AT_EMPTY_PATH;

  err = __hurd_at_flags (&at_flags, &flags);
  if (err)
    return (__hurd_fail (err), MACH_PORT_NULL);

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

  if (empty != 0 && file_name[0] == '\0')
    {
      enum retry_type doretry;
      char retryname[1024];	/* XXX string_t LOSES! */

      err = HURD_DPORT_USE (fd, __dir_lookup (port, "", flags, mode,
					      &doretry, retryname,
					      &result));

      if (! err)
	err = __hurd_file_name_lookup_retry (&_hurd_ports_use, &__getdport,
					     NULL, doretry, retryname,
					     flags, mode, &result);

      return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
    }

  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;
}
/* XXX should be __getsockopt ? */
int
getsockopt (int fd,
	    int level,
	    int optname,
	    void *optval,
	    socklen_t *optlen)
{
  error_t err;
  char *buf = optval;
  mach_msg_type_number_t buflen = *optlen;

  if (err = HURD_DPORT_USE (fd, __socket_getopt (port,
						 level, optname,
						 &buf, &buflen)))
    return __hurd_dfail (fd, err);

  if (*optlen > buflen)
    *optlen = buflen;
  if (buf != optval)
    {
      memcpy (optval, buf, *optlen);
      __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
    }

  return 0;
}
Beispiel #3
0
ssize_t
__libc_write (int fd, const void *buf, size_t nbytes)
{
  error_t err = HURD_FD_USE (fd, _hurd_fd_write (descriptor,
						 buf, &nbytes, -1));
  return err ? __hurd_dfail (fd, err) : nbytes;
}
Beispiel #4
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)))
    {
      if (err == MIG_BAD_ID || err == EOPNOTSUPP)
        err = ENOTTY;
      return __hurd_dfail (fd, err), errno;
    }

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

  memcpy (buf, nodename, len);
  return 0;
}
Beispiel #5
0
file_t
__file_name_split_at (int fd, const char *file_name, char **name)
{
  error_t err;
  file_t result;

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

  err = __hurd_file_name_split (&_hurd_ports_use, &__getdport, 0,
				file_name, &result, 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_file_name_split (&use_init_port,
						     &__getdport, 0,
						     file_name,
						     &result, name)));

  return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
}
Beispiel #6
0
/* Truncate the file referenced by FD to LENGTH bytes.  */
int
__ftruncate (int fd, __off_t length)
{
  error_t err;
  if (err = HURD_DPORT_USE (fd, __file_set_size (port, length)))
    return __hurd_dfail (fd, err);
  return 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)
    return __hurd_dfail (fd, err);
  return 0;
}
ssize_t
fgetxattr (int fd, const char *name, void *value, size_t size)
{
  error_t err;

  err = HURD_DPORT_USE (fd, _hurd_xattr_get (port, name, value, &size));

  return err ? __hurd_dfail (fd, err) : size;
}
ssize_t
fsetxattr (int fd, const char *name, const void *value, size_t size, int flags)
{
  error_t err;

  err = HURD_DPORT_USE (fd, _hurd_xattr_set (port, name, value, size, flags));

  return err ? __hurd_dfail (fd, err) : 0;
}
ssize_t
flistxattr (int fd, char *list, size_t size)
{
  error_t err;

  err = HURD_DPORT_USE (fd, _hurd_xattr_list (port, list, &size));

  return err ? __hurd_dfail (fd, err) : size;
}
Beispiel #11
0
int
fremovexattr (int fd, const char *name)
{
  error_t err;

  err = HURD_DPORT_USE (fd, _hurd_xattr_remove (port, name));

  return err ? __hurd_dfail (fd, err) : 0;
}
Beispiel #12
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;
}
Beispiel #13
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;
}
Beispiel #14
0
/* Return information about the filesystem on which FD resides.  */
int
__fstatfs64 (int fd, struct statfs64 *buf)
{
  error_t err;

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

  return 0;
}
Beispiel #15
0
/* XXX should be __fchflags? */
int
fchflags (int fd, int flags)
{
    error_t err;

    if (err = HURD_DPORT_USE (fd, __file_chflags (port, flags)))
        return __hurd_dfail (fd, err);

    return 0;
}
Beispiel #16
0
ssize_t
__libc_pread64 (int fd, void *buf, size_t nbytes, off64_t offset)
{
  error_t err;
  if (offset < 0)
    err = EINVAL;
  else
    err = HURD_FD_USE (fd, _hurd_fd_read (descriptor, buf, &nbytes, offset));
  return err ? __hurd_dfail (fd, err) : nbytes;
}
Beispiel #17
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;
}
Beispiel #18
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;
}
Beispiel #19
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;
}
Beispiel #20
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;
}
Beispiel #21
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;
}
Beispiel #22
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;
}
Beispiel #23
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;
}
Beispiel #24
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;
}
Beispiel #25
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;
}
Beispiel #26
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;
}
Beispiel #27
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;
}
Beispiel #28
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;
}