int ioperm (unsigned long int from, unsigned long int num, int turn_on) { #if ! HAVE_I386_IO_PERM_MODIFY return __hurd_fail (ENOSYS); #else error_t err; device_t devmaster; /* With the device master port we get a capability that represents this range of io ports. */ err = __get_privileged_ports (NULL, &devmaster); if (! err) { io_perm_t perm; err = __i386_io_perm_create (devmaster, from, from + num - 1, &perm); __mach_port_deallocate (__mach_task_self (), devmaster); if (! err) { /* Now we add or remove that set from our task's bitmap. */ err = __i386_io_perm_modify (__mach_task_self (), perm, turn_on); __mach_port_deallocate (__mach_task_self (), perm); } if (err == MIG_BAD_ID) /* Old kernels don't have these RPCs. */ err = ENOSYS; } return err ? __hurd_fail (err) : 0; #endif }
/* Make a link to FROM relative to FROMFD called TO relative to TOFD. */ int linkat (int fromfd, const char *from, int tofd, const char *to, int flags) { error_t err; file_t oldfile, linknode, todir; char *toname; /* POSIX says linkat doesn't follow symlinks by default, so pass O_NOLINK. That can be overridden by AT_SYMLINK_FOLLOW in FLAGS. */ oldfile = __file_name_lookup_at (fromfd, flags, from, O_NOLINK, 0); if (oldfile == MACH_PORT_NULL) return -1; /* The file_getlinknode RPC returns the port that should be passed to the receiving filesystem (the one containing TODIR) in dir_link. */ err = __file_getlinknode (oldfile, &linknode); __mach_port_deallocate (__mach_task_self (), oldfile); if (err) return __hurd_fail (err); todir = __file_name_split_at (tofd, to, &toname); if (todir != MACH_PORT_NULL) { err = __dir_link (todir, linknode, toname, 1); __mach_port_deallocate (__mach_task_self (), todir); } __mach_port_deallocate (__mach_task_self (), linknode); if (todir == MACH_PORT_NULL) return -1; if (err) return __hurd_fail (err); return 0; }
/* Fetch a thread state structure from PID and store it at ADDR. */ int get_regs (int flavor, mach_msg_type_number_t count) { error_t err; task_t task = __pid2task (pid); thread_t thread; if (task == MACH_PORT_NULL) return -1; err = fetch_user_thread (task, &thread); __mach_port_deallocate (__mach_task_self (), task); if (!err) err = __thread_get_state (thread, flavor, addr, &count); __mach_port_deallocate (__mach_task_self (), thread); return err ? __hurd_fail (err) : 0; }
kern_return_t _S_get_init_ports (mach_port_t msgport, mach_port_t auth, mach_port_t **ports, mach_msg_type_name_t *ports_type, unsigned int *nports) { unsigned int i; error_t err; AUTHCHECK; if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports, _hurd_nports * sizeof (mach_port_t), 1)) return err; *nports = _hurd_nports; for (i = 0; i < _hurd_nports; ++i) /* This function adds a new user ref for the *RESULT it gives back. Our reply message uses move-send rights that consumes this ref. */ if (err = _hurd_ports_get (i, &(*ports)[i])) { /* Died part way through. Deallocate the ports already fetched. */ while (i-- > 0) __mach_port_deallocate (__mach_task_self (), (*ports)[i]); __vm_deallocate (__mach_task_self (), (vm_address_t) *ports, *nports * sizeof (mach_port_t)); return err; } *ports_type = MACH_MSG_TYPE_MOVE_SEND; return 0; }
/* In the childs, unlock the interlock, and start a profiling thread up if necessary. */ static void fork_profil_child (void) { u_short *sb; size_t n, o, ss; error_t err; __spin_unlock (&lock); if (profile_thread != MACH_PORT_NULL) { __mach_port_deallocate (__mach_task_self (), profile_thread); profile_thread = MACH_PORT_NULL; } sb = samples; samples = NULL; n = maxsamples; maxsamples = 0; o = pc_offset; pc_offset = 0; ss = sample_scale; sample_scale = 0; if (ss != 0) { err = update_waiter (sb, n * sizeof *sb, o, ss); assert_perror (err); } }
/* Set the current time of day and timezone information. This call is restricted to the super-user. */ int __settimeofday (const struct timeval *tv, const struct timezone *tz) { error_t err; mach_port_t hostpriv; if (tz != NULL) { errno = ENOSYS; return -1; } err = __get_privileged_ports (&hostpriv, NULL); if (err) return __hurd_fail (EPERM); /* `time_value_t' and `struct timeval' are in fact identical with the names changed. */ err = __host_set_time (hostpriv, *(time_value_t *) tv); __mach_port_deallocate (__mach_task_self (), hostpriv); if (err) return __hurd_fail (err); return 0; }
ssize_t __recv (int fd, void *buf, size_t n, int flags) { error_t err; mach_port_t addrport; char *bufp = buf; mach_msg_type_number_t nread = n; mach_port_t *ports; mach_msg_type_number_t nports = 0; char *cdata = NULL; mach_msg_type_number_t clen = 0; if (err = HURD_DPORT_USE (fd, __socket_recv (port, &addrport, flags, &bufp, &nread, &ports, &nports, &cdata, &clen, &flags, n))) return __hurd_sockfail (fd, flags, err); __mach_port_deallocate (__mach_task_self (), addrport); __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen); if (bufp != buf) { memcpy (buf, bufp, nread); __vm_deallocate (__mach_task_self (), (vm_address_t) bufp, nread); } return nread; }
/* This returns a new stream opened on a temporary file (generated by tmpnam). The file is opened with mode "w+b" (binary read/write). If we couldn't generate a unique filename or the file couldn't be opened, NULL is returned. */ FILE * __tmpfile (void) { error_t err; file_t file; int fd; FILE *f; /* Get a port to the directory that will contain the file. */ const char *dirname = __libc_secure_getenv ("TMPDIR") ?: P_tmpdir; file_t dir = __file_name_lookup (dirname, 0, 0); if (dir == MACH_PORT_NULL) return NULL; /* Create an unnamed file in the temporary directory. */ err = __dir_mkfile (dir, O_RDWR, S_IRUSR | S_IWUSR, &file); __mach_port_deallocate (__mach_task_self (), dir); if (err) return __hurd_fail (err), NULL; /* Get a file descriptor for that port. POSIX.1 requires that streams returned by tmpfile allocate file descriptors as fopen would. */ fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */ if (fd < 0) return NULL; /* Open a stream on the unnamed file. It will cease to exist when this stream is closed. */ if ((f = _IO_fdopen (fd, "w+b")) == NULL) __close (fd); return f; }
/* Read the contents of the symbolic link FILE_NAME relative to FD into no more than LEN bytes of BUF. The contents are not null-terminated. Returns the number of characters read, or -1 for errors. */ ssize_t readlinkat (int fd, const char *file_name, char *buf, size_t len) { error_t err; file_t file; struct stat64 st; file = __file_name_lookup_at (fd, 0, file_name, O_READ | O_NOLINK, 0); if (file == MACH_PORT_NULL) return -1; err = __io_stat (file, &st); if (! err) if (S_ISLNK (st.st_mode)) { char *rbuf = buf; err = __io_read (file, &rbuf, &len, 0, len); if (!err && rbuf != buf) { memcpy (buf, rbuf, len); __vm_deallocate (__mach_task_self (), (vm_address_t)rbuf, len); } } else err = EINVAL; __mach_port_deallocate (__mach_task_self (), file); return err ? __hurd_fail (err) : len; }
/* Change the access time of FILE to TVP[0] and the modification time of FILE to TVP[1]. */ int __lutimes (const char *file, 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; file_t port; 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; } port = __file_name_lookup (file, O_NOLINK, 0); if (port == MACH_PORT_NULL) return -1; err = __file_utimes (port, u[0].tvt, u[1].tvt); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err); return 0; }
void _hurd_port2fd (struct hurd_fd *d, io_t port, int flags) { io_t ctty; mach_port_t cttyid; int is_ctty = !(flags & O_IGNORE_CTTY) && ! __term_getctty (port, &cttyid); if (is_ctty) { /* This port is capable of being a controlling tty. Is it ours? */ struct hurd_port *const id = &_hurd_ports[INIT_PORT_CTTYID]; __spin_lock (&id->lock); if (id->port == MACH_PORT_NULL) /* We have no controlling tty, so make this one it. */ _hurd_port_locked_set (id, cttyid); else { if (cttyid != id->port) /* We have a controlling tty and this is not it. */ is_ctty = 0; /* Either we don't want CTTYID, or ID->port already is it. So we don't need to change ID->port, and we can release the reference to CTTYID. */ __spin_unlock (&id->lock); __mach_port_deallocate (__mach_task_self (), cttyid); } } if (!is_ctty || __term_open_ctty (port, _hurd_pid, _hurd_pgrp, &ctty) != 0) /* XXX if IS_CTTY, then this port is our ctty, but we are not doing ctty style i/o because term_become_ctty barfed. What to do? */ /* No ctty magic happening here. */ ctty = MACH_PORT_NULL; /* Install PORT in the descriptor cell, leaving it locked. */ { mach_port_t old = _hurd_userlink_clear (&d->port.users) ? d->port.port : MACH_PORT_NULL; d->port.port = port; if (old != MACH_PORT_NULL) __mach_port_deallocate (__mach_task_self (), old); } _hurd_port_set (&d->ctty, ctty); }
/* Close the file associated with COOKIE. Return 0 for success or -1 for failure. */ static int closeio (void *cookie) { error_t error = __mach_port_deallocate (__mach_task_self (), (mach_port_t) cookie); if (error) return __hurd_fail (error); return 0; }
/* Make a link to FROM called TO. */ int __symlink (const char *from, const char *to) { error_t err; file_t dir, node; char *name; const size_t len = strlen (from) + 1; char buf[sizeof (_HURD_SYMLINK) + len]; /* A symlink is a file whose translator is "/hurd/symlink\0target\0". */ memcpy (buf, _HURD_SYMLINK, sizeof (_HURD_SYMLINK)); memcpy (&buf[sizeof (_HURD_SYMLINK)], from, len); dir = __file_name_split (to, &name); if (dir == MACH_PORT_NULL) return -1; /* Create a new, unlinked node in the target directory. */ err = __dir_mkfile (dir, O_WRITE, 0777 & ~_hurd_umask, &node); if (! err) { /* Set the node's translator to make it a symlink. */ err = __file_set_translator (node, FS_TRANS_EXCL|FS_TRANS_SET, FS_TRANS_EXCL|FS_TRANS_SET, 0, buf, sizeof (_HURD_SYMLINK) + len, MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); if (! err) /* Link the node, now a valid symlink, into the target directory. */ err = __dir_link (dir, node, name, 1); __mach_port_deallocate (__mach_task_self (), node); } __mach_port_deallocate (__mach_task_self (), dir); if (err) return __hurd_fail (err); return 0; }
/* Set the priority of all processes specified by WHICH and WHO to PRIO. Returns 0 on success, -1 on errors. */ int __setpriority (enum __priority_which which, id_t who, int prio) { error_t err; error_t pidloser, priloser; unsigned int npids, ntasks, nwin, nperm, nacces; error_t setonepriority (pid_t pid, struct procinfo *pi) { task_t task; error_t piderr = __USEPORT (PROC, __proc_pid2task (port, pid, &task)); if (piderr == EPERM) ++nperm; if (piderr != ESRCH) { ++npids; if (piderr && piderr != EPERM) pidloser = piderr; } if (! piderr) { error_t prierr; ++ntasks; #ifdef POLICY_TIMESHARE_BASE_COUNT { /* XXX This assumes timeshare policy. */ struct policy_timeshare_base base = { NICE_TO_MACH_PRIORITY (prio) }; prierr = __task_policy (task, POLICY_TIMESHARE, (policy_base_t) &base, POLICY_TIMESHARE_BASE_COUNT, 0, 1); } #else prierr = __task_priority (task, NICE_TO_MACH_PRIORITY (prio), 1); #endif __mach_port_deallocate (__mach_task_self (), task); switch (prierr) { case KERN_FAILURE: ++nacces; break; case KERN_SUCCESS: ++nwin; break; case KERN_INVALID_ARGUMENT: /* Task died. */ --npids; --ntasks; break; default: priloser = prierr; } } return 0; }
ssize_t lremovexattr (const char *path, const char *name) { error_t err; file_t port = __file_name_lookup (path, O_NOLINK, 0); if (port == MACH_PORT_NULL) return -1; err = _hurd_xattr_remove (port, name); __mach_port_deallocate (__mach_task_self (), port); return __hurd_fail (err); }
ssize_t lgetxattr (const char *path, const char *name, void *value, size_t size) { error_t err; file_t port = __file_name_lookup (path, O_NOLINK, 0); if (port == MACH_PORT_NULL) return -1; err = _hurd_xattr_get (port, name, value, &size); __mach_port_deallocate (__mach_task_self (), port); return err ? __hurd_fail (err) : size; }
ssize_t listxattr (const char *path, char *list, size_t size) { error_t err; file_t port = __file_name_lookup (path, 0, 0); if (port == MACH_PORT_NULL) return -1; err = _hurd_xattr_list (port, list, &size); __mach_port_deallocate (__mach_task_self (), port); return err ? __hurd_fail (err) : size; }
/* 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; }
ssize_t setxattr (const char *path, const char *name, const void *value, size_t size, int flags) { error_t err; file_t port = __file_name_lookup (path, 0, 0); if (port == MACH_PORT_NULL) return -1; err = _hurd_xattr_set (port, name, value, size, flags); __mach_port_deallocate (__mach_task_self (), port); return __hurd_fail (err); }
/* Change the protections of FILE to MODE. */ int lchmod (const char *file, mode_t mode) { error_t err; file_t port = __file_name_lookup (file, O_NOLINK, 0); if (port == MACH_PORT_NULL) return -1; err = __file_chmod (port, mode); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err); return 0; }
/* Change the owner and group of FILE; if it's a link, do the link and not the target. */ int __lchown (const char *file, uid_t owner, gid_t group) { error_t err; file_t port = __file_name_lookup (file, O_NOLINK, 0); if (port == MACH_PORT_NULL) return -1; err = __file_chown (port, owner, group); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err); return 0; }
int fchmodat (int fd, const char *file, mode_t mode, int flag) { error_t err; file_t port = __file_name_lookup_at (fd, flag, file, 0, 0); if (port == MACH_PORT_NULL) return -1; err = __file_chmod (port, mode); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err); return 0; }
/* XXX shouldn't this be __chflags? */ int chflags (const char *file, int flags) { error_t err; file_t port = __file_name_lookup (file, 0, 0); if (port == MACH_PORT_NULL) return -1; err = __file_chflags (port, flags); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err); return 0; }
error_t __hurd_file_name_lookup_retry (error_t (*use_init_port) (int which, error_t (*operate) (file_t)), file_t (*get_dtable_port) (int fd), error_t (*lookup) (file_t dir, char *name, int flags, mode_t mode, retry_type *do_retry, string_t retry_name, mach_port_t *result), enum retry_type doretry, char retryname[1024], int flags, mode_t mode, file_t *result) { error_t err; char *file_name; int nloops; error_t lookup_op (file_t startdir) { if (file_name[0] == '/' && file_name[1] != '\0') { while (file_name[1] == '/') /* Remove double leading slash. */ file_name++; if (file_name[1] != '\0') /* Remove leading slash when we have more than the slash. */ file_name++; } return lookup_error ((*lookup) (startdir, file_name, flags, mode, &doretry, retryname, result)); } error_t reauthenticate (file_t unauth) { error_t err; mach_port_t ref = __mach_reply_port (); error_t reauth (auth_t auth) { return __auth_user_authenticate (auth, ref, MACH_MSG_TYPE_MAKE_SEND, result); } err = __io_reauthenticate (unauth, ref, MACH_MSG_TYPE_MAKE_SEND); if (! err) err = (*use_init_port) (INIT_PORT_AUTH, &reauth); __mach_port_destroy (__mach_task_self (), ref); __mach_port_deallocate (__mach_task_self (), unauth); return err; }
kern_return_t _S_set_init_port (mach_port_t msgport, mach_port_t auth, int which, mach_port_t port) { error_t err; AUTHCHECK; err = _hurd_ports_set (which, port); if (err == 0) __mach_port_deallocate (__mach_task_self (), port); return 0; }
/* Get file-specific information about FILE. */ long int __pathconf (const char *file, int name) { error_t err; int value; /* RPC returns an `int', not a `long int'. */ file_t port = __file_name_lookup (file, 0, 0); if (port == MACH_PORT_NULL) return -1L; err = __io_pathconf (port, name, &value); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err), -1L; return value; }
/* Remove the directory FILE_NAME. */ int __rmdir (const char *file_name) { error_t err; const char *name; file_t parent = __directory_name_split (file_name, (char **) &name); if (parent == MACH_PORT_NULL) return -1; err = __dir_rmdir (parent, name); __mach_port_deallocate (__mach_task_self (), parent); if (err) return __hurd_fail (err); return 0; }
error_t _hurd_check_ids (void) { if (! _hurd_id.valid) { inline void dealloc (__typeof (_hurd_id.gen) *p) { if (p->uids) { __vm_deallocate (__mach_task_self (), (vm_address_t) p->uids, p->nuids * sizeof (uid_t)); p->uids = NULL; } p->nuids = 0; if (p->gids) { __vm_deallocate (__mach_task_self (), (vm_address_t) p->gids, p->ngids * sizeof (gid_t)); p->gids = NULL; } p->ngids = 0; } error_t err; dealloc (&_hurd_id.gen); dealloc (&_hurd_id.aux); if (_hurd_id.rid_auth != MACH_PORT_NULL) { __mach_port_deallocate (__mach_task_self (), _hurd_id.rid_auth); _hurd_id.rid_auth = MACH_PORT_NULL; } if (err = __USEPORT (AUTH, __auth_getids (port, &_hurd_id.gen.uids, &_hurd_id.gen.nuids, &_hurd_id.aux.uids, &_hurd_id.aux.nuids, &_hurd_id.gen.gids, &_hurd_id.gen.ngids, &_hurd_id.aux.gids, &_hurd_id.aux.ngids))) return err; _hurd_id.valid = 1; } return 0; }
/* Create a new shared memory segment file without linking it into the filesystem. Return the directory and file ports in R_DIR and R_FILE. */ static error_t create_shm_file (size_t size, int flags, file_t *r_dir, file_t *r_file) { error_t err; file_t dir; file_t file; flags &= 0777; /* Get a port to the directory that will contain the file. */ dir = __file_name_lookup (SHM_DIR, 0, 0); if (dir == MACH_PORT_NULL) return errno; /* Create an unnamed file in the directory. */ err = __dir_mkfile (dir, O_RDWR, flags, &file); if (err) { __mach_port_deallocate (__mach_task_self (), dir); return err; } err = __file_set_size (file, size); if (err) { __mach_port_deallocate (__mach_task_self (), file); __mach_port_deallocate (__mach_task_self (), dir); return err; } *r_dir = dir; *r_file = file; return 0; }
/* Adjust the current time of day by the amount in DELTA. If OLDDELTA is not NULL, it is filled in with the amount of time adjustment remaining to be done from the last `__adjtime' call. This call is restricted to the super-user. */ int __adjtime (const struct timeval *delta, struct timeval *olddelta) { error_t err; mach_port_t hostpriv; hostpriv = __pid2task (-1); if (hostpriv == MACH_PORT_NULL) return -1; err = __host_adjust_time (hostpriv, delta, olddelta); __mach_port_deallocate (__mach_task_self (), hostpriv); if (err) return __hurd_fail (err); return 0; }