/* 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; }
/* 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; }
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; }
/* Get information about the file descriptor FD in BUF. */ int __fxstatat64 (int vers, int fd, const char *filename, struct stat64 *buf, int flag) { error_t err; io_t port; if (vers != _STAT_VER) return __hurd_fail (EINVAL); port = __file_name_lookup_at (fd, flag, filename, 0, 0); if (port == MACH_PORT_NULL) return -1; err = __io_stat (port, buf); __mach_port_deallocate (__mach_task_self (), port); return __hurd_fail (err); }