error_t _hurd_fd_read (struct hurd_fd *fd, void *buf, size_t *nbytes, loff_t offset) { error_t err; char *data; mach_msg_type_number_t nread; error_t readfd (io_t port) { return __io_read (port, &data, &nread, offset, *nbytes); } data = buf; nread = *nbytes; if (err = HURD_FD_PORT_USE (fd, _hurd_ctty_input (port, ctty, readfd))) return err; if (data != buf) { if (nread > *nbytes) /* Sanity check for bogus server. */ { __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread); return EGRATUITOUS; } memcpy (buf, data, nread); __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread); } *nbytes = nread; return 0; }
/* 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; }
/* Read up to N chars into BUF from COOKIE. Return how many chars were read, 0 for EOF or -1 for error. */ static ssize_t readio (void *cookie, char *buf, size_t n) { mach_msg_type_number_t nread; error_t err; char *bufp = buf; nread = n; if (err = __io_read ((io_t) cookie, &bufp, &nread, -1, n)) return __hurd_fail (err); if (bufp != buf) { memcpy (buf, bufp, nread); __vm_deallocate (__mach_task_self (), (vm_address_t) bufp, (vm_size_t) nread); } return nread; }