/* 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; }
/* Read the contents of the symbolic link FILE_NAME 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 __readlink (const char *file_name, char *buf, size_t len) { error_t err; file_t file; struct stat64 st; file = __file_name_lookup (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); if (err) return __hurd_fail (err); else return len; }
/* 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; }
int _hurd_change_directory_port_from_name (struct hurd_port *portcell, const char *name) { size_t len; const char *lookup; file_t dir; /* Append trailing "/." to directory name to force ENOTDIR if it's not a directory and EACCES if we don't have search permission. */ len = strlen (name); if (len >= 2 && name[len - 2] == '/' && name[len - 1] == '.') lookup = name; else if (len == 0) /* Special-case empty file name according to POSIX. */ return __hurd_fail (ENOENT); else { char *n = alloca (len + 3); memcpy (n, name, len); n[len] = '/'; n[len + 1] = '.'; n[len + 2] = '\0'; lookup = n; } dir = __file_name_lookup (lookup, 0, 0); if (dir == MACH_PORT_NULL) return -1; _hurd_port_set (portcell, dir); return 0; }
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; }
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 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 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; }
/* 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; }
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; }
/* 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; }
/* Return information about the filesystem on which FILE resides. */ int __statfs64 (const char *file, struct statfs64 *buf) { error_t err; file_t port; port = __file_name_lookup (file, 0, 0); if (port == MACH_PORT_NULL) return -1; err = __file_statfs (port, buf); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err); return 0; }
/* Truncate FILE_NAME to LENGTH bytes. */ int __truncate64 (const char *file_name, off64_t length) { error_t err; file_t file = __file_name_lookup (file_name, O_WRITE, 0); if (file == MACH_PORT_NULL) return -1; err = __file_set_size (file, length); __mach_port_deallocate (__mach_task_self (), file); if (err) return __hurd_fail (err); return 0; }
int revoke (const char *file_name) { error_t err; file_t file = __file_name_lookup (file_name, 0, 0); if (file == MACH_PORT_NULL) return -1; err = __io_revoke (file); __mach_port_deallocate (__mach_task_self (), file); if (err) return __hurd_fail (err); return 0; }
/* Replace the current process, executing FILE_NAME with arguments ARGV and environment ENVP. ARGV and ENVP are terminated by NULL pointers. */ int __execve (const char *file_name, char *const argv[], char *const envp[]) { error_t err; file_t file = __file_name_lookup (file_name, O_EXEC, 0); if (file == MACH_PORT_NULL) return -1; /* Hopefully this will not return. */ err = _hurd_exec (__mach_task_self (), file, argv, envp); /* Oh well. Might as well be tidy. */ __mach_port_deallocate (__mach_task_self (), file); return __hurd_fail (err); }
/* 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]) { error_t err; file_t port; port = __file_name_lookup (file, O_NOLINK, 0); if (port == MACH_PORT_NULL) return -1; err = hurd_futimes (port, tvp); __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 __lxstat64 (int vers, const char *file, struct stat64 *buf) { error_t err; file_t port; if (vers != _STAT_VER) return __hurd_fail (EINVAL); port = __file_name_lookup (file, O_NOLINK, 0); if (port == MACH_PORT_NULL) return -1; err = __io_stat (port, buf); __mach_port_deallocate (__mach_task_self (), port); if (err) return __hurd_fail (err); return 0; }
/* Send N bytes of BUF on socket FD to peer at address ADDR (which is ADDR_LEN bytes long). Returns the number sent, or -1 for errors. */ ssize_t __sendto (int fd, const void *buf, size_t n, int flags, const struct sockaddr_un *addr, socklen_t addr_len) { addr_port_t aport = MACH_PORT_NULL; error_t err; size_t wrote; /* Get an address port for the desired destination address. */ error_t create_address_port (io_t port, const struct sockaddr_un *addr, socklen_t addr_len, addr_port_t *aport) { error_t err_port; if (addr->sun_family == AF_LOCAL) { /* For the local domain, we must look up the name as a file and talk to it with the ifsock protocol. */ file_t file = __file_name_lookup (addr->sun_path, 0, 0); if (file == MACH_PORT_NULL) return errno; err_port = __ifsock_getsockaddr (file, aport); __mach_port_deallocate (__mach_task_self (), file); if (err_port == MIG_BAD_ID || err_port == EOPNOTSUPP) /* The file did not grok the ifsock protocol. */ err_port = ENOTSOCK; } else { err_port = __socket_create_address (port, addr->sun_family, (char *) addr, addr_len, aport); } return err_port; }
/* Open FILE with access OFLAG. If O_CREAT or O_TMPFILE is in OFLAG, a third argument is the file protection. */ int __libc_open (const char *file, int oflag, ...) { mode_t mode; io_t port; if (__OPEN_NEEDS_MODE (oflag)) { va_list arg; va_start (arg, oflag); mode = va_arg (arg, mode_t); va_end (arg); } else mode = 0; port = __file_name_lookup (file, oflag, mode); if (port == MACH_PORT_NULL) return -1; return _hurd_intern_fd (port, oflag, 1); }
/* Make PATH be the root directory (the starting point for absolute paths). Note that while on traditional UNIX systems this call is restricted to the super-user, it isn't on the Hurd. */ int chroot (const char *path) { const char *lookup; size_t len; file_t dir, root; error_t err; /* Append trailing "/." to directory name to force ENOTDIR if it's not a directory and EACCES if we don't have search permission. */ len = strlen (path); if (len >= 2 && path[len - 2] == '/' && path[len - 1] == '.') lookup = path; else if (len == 0) /* Special-case empty file name according to POSIX. */ return __hurd_fail (ENOENT); else { char *n = alloca (len + 3); memcpy (n, path, len); n[len] = '/'; n[len + 1] = '.'; n[len + 2] = '\0'; lookup = n; } dir = __file_name_lookup (lookup, 0, 0); if (dir == MACH_PORT_NULL) return -1; /* Prevent going through DIR's .. */ err = __file_reparent (dir, MACH_PORT_NULL, &root); __mach_port_deallocate (__mach_task_self (), dir); if (err) return __hurd_fail (err); _hurd_port_set (&_hurd_ports[INIT_PORT_CRDIR], root); return 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; }
static void check_one_fd (int fd, int mode) { struct hurd_fd *d; d = _hurd_fd_get (fd); if (d == NULL) { /* This descriptor hasn't been opened. We try to allocate the descriptor and open /dev/null on it so that the SUID program we are about to start does not accidentally use this descriptor. */ d = _hurd_alloc_fd (NULL, fd); if (d != NULL) { mach_port_t port; port = __file_name_lookup (_PATH_DEVNULL, mode, 0); if (port) { /* Since /dev/null isn't supposed to be a terminal, we avoid any ctty magic. */ d->port.port = port; d->flags = 0; __spin_unlock (&d->port.lock); return; } } /* We cannot even give an error message here since it would run into the same problems. */ while (1) /* Try for ever and ever. */ ABORT_INSTRUCTION; } }
/* 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; }
not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ansidecl.h> #include <errno.h> #include <stddef.h> #include <unistd.h> #include <hurd.h> #include <fcntl.h> #include <hurd/port.h> /* Change the current root to FILE_NAME. */ int DEFUN(chroot, (file_name), CONST char *file_name) { file_t file, dir; error_t err; file = __file_name_lookup (file_name, O_EXEC, 0); if (file == MACH_PORT_NULL) return -1; err = __USEPORT (CRDIR, __hurd_file_name_lookup (port, file, "", O_EXEC, 0, &dir)); __mach_port_deallocate (__mach_task_self (), file); if (err) return __hurd_fail (err); _hurd_port_set (&_hurd_ports[INIT_PORT_CRDIR], dir); return 0; }
#include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include <hurd.h> /* Open a directory stream on NAME. */ DIR * DEFUN(opendir, (name), CONST char *name) { DIR *dirp; file_t port; port = __file_name_lookup (name, O_RDONLY, 0); if (port == MACH_PORT_NULL) return NULL; /* XXX this port should be deallocated on exec */ dirp = (DIR *) malloc (sizeof (DIR)); if (dirp == NULL) { __mach_port_deallocate (__mach_task_self (), port); return NULL; } dirp->__port = port; dirp->__data = dirp->__ptr = NULL; dirp->__entry_data = dirp->__entry_ptr = 0;
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 <stddef.h> #include <sys/stat.h> #include <hurd.h> /* Change the flags of FILE to FLAGS. */ int DEFUN(chflags, (file, flags), CONST char *file AND 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; }
/* Call the crash dump server to mummify us before we die. Returns nonzero if a core file was written. */ static int write_corefile (int signo, const struct hurd_signal_detail *detail) { error_t err; mach_port_t coreserver; file_t file, coredir; const char *name; /* Don't bother locking since we just read the one word. */ rlim_t corelimit = _hurd_rlimits[RLIMIT_CORE].rlim_cur; if (corelimit == 0) /* No core dumping, thank you very much. Note that this makes `ulimit -c 0' prevent crash-suspension too, which is probably what the user wanted. */ return 0; /* XXX RLIMIT_CORE: When we have a protocol to make the server return an error for RLIMIT_FSIZE, then tell the corefile fs server the RLIMIT_CORE value in place of the RLIMIT_FSIZE value. */ /* First get a port to the core dumping server. */ coreserver = MACH_PORT_NULL; name = _hurdsig_getenv ("CRASHSERVER"); if (name != NULL) coreserver = __file_name_lookup (name, 0, 0); if (coreserver == MACH_PORT_NULL) coreserver = __file_name_lookup (_SERVERS_CRASH, 0, 0); if (coreserver == MACH_PORT_NULL) return 0; /* Get a port to the directory where the new core file will reside. */ file = MACH_PORT_NULL; name = _hurdsig_getenv ("COREFILE"); if (name == NULL) name = "core"; coredir = __file_name_split (name, (char **) &name); if (coredir != MACH_PORT_NULL) /* Create the new file, but don't link it into the directory yet. */ __dir_mkfile (coredir, O_WRONLY|O_CREAT, 0600 & ~_hurd_umask, /* XXX ? */ &file); /* Call the core dumping server to write the core file. */ err = __crash_dump_task (coreserver, __mach_task_self (), file, signo, detail->code, detail->error, detail->exc, detail->exc_code, detail->exc_subcode, _hurd_ports[INIT_PORT_CTTYID].port, MACH_MSG_TYPE_COPY_SEND); __mach_port_deallocate (__mach_task_self (), coreserver); if (! err && file != MACH_PORT_NULL) /* The core dump into FILE succeeded, so now link it into the directory. */ err = __dir_link (coredir, file, name, 1); __mach_port_deallocate (__mach_task_self (), file); __mach_port_deallocate (__mach_task_self (), coredir); return !err && file != MACH_PORT_NULL; }