xref: /kernel/linux/linux-5.10/arch/um/os-Linux/file.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <stdio.h>
78c2ecf20Sopenharmony_ci#include <unistd.h>
88c2ecf20Sopenharmony_ci#include <stdlib.h>
98c2ecf20Sopenharmony_ci#include <string.h>
108c2ecf20Sopenharmony_ci#include <errno.h>
118c2ecf20Sopenharmony_ci#include <fcntl.h>
128c2ecf20Sopenharmony_ci#include <signal.h>
138c2ecf20Sopenharmony_ci#include <linux/falloc.h>
148c2ecf20Sopenharmony_ci#include <sys/ioctl.h>
158c2ecf20Sopenharmony_ci#include <sys/mount.h>
168c2ecf20Sopenharmony_ci#include <sys/socket.h>
178c2ecf20Sopenharmony_ci#include <sys/stat.h>
188c2ecf20Sopenharmony_ci#include <sys/sysmacros.h>
198c2ecf20Sopenharmony_ci#include <sys/un.h>
208c2ecf20Sopenharmony_ci#include <sys/types.h>
218c2ecf20Sopenharmony_ci#include <sys/eventfd.h>
228c2ecf20Sopenharmony_ci#include <poll.h>
238c2ecf20Sopenharmony_ci#include <os.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic void copy_stat(struct uml_stat *dst, const struct stat64 *src)
268c2ecf20Sopenharmony_ci{
278c2ecf20Sopenharmony_ci	*dst = ((struct uml_stat) {
288c2ecf20Sopenharmony_ci		.ust_dev     = src->st_dev,     /* device */
298c2ecf20Sopenharmony_ci		.ust_ino     = src->st_ino,     /* inode */
308c2ecf20Sopenharmony_ci		.ust_mode    = src->st_mode,    /* protection */
318c2ecf20Sopenharmony_ci		.ust_nlink   = src->st_nlink,   /* number of hard links */
328c2ecf20Sopenharmony_ci		.ust_uid     = src->st_uid,     /* user ID of owner */
338c2ecf20Sopenharmony_ci		.ust_gid     = src->st_gid,     /* group ID of owner */
348c2ecf20Sopenharmony_ci		.ust_size    = src->st_size,    /* total size, in bytes */
358c2ecf20Sopenharmony_ci		.ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
368c2ecf20Sopenharmony_ci		.ust_blocks  = src->st_blocks,  /* number of blocks allocated */
378c2ecf20Sopenharmony_ci		.ust_atime   = src->st_atime,   /* time of last access */
388c2ecf20Sopenharmony_ci		.ust_mtime   = src->st_mtime,   /* time of last modification */
398c2ecf20Sopenharmony_ci		.ust_ctime   = src->st_ctime,   /* time of last change */
408c2ecf20Sopenharmony_ci	});
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ciint os_stat_fd(const int fd, struct uml_stat *ubuf)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	struct stat64 sbuf;
468c2ecf20Sopenharmony_ci	int err;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	CATCH_EINTR(err = fstat64(fd, &sbuf));
498c2ecf20Sopenharmony_ci	if (err < 0)
508c2ecf20Sopenharmony_ci		return -errno;
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	if (ubuf != NULL)
538c2ecf20Sopenharmony_ci		copy_stat(ubuf, &sbuf);
548c2ecf20Sopenharmony_ci	return err;
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ciint os_stat_file(const char *file_name, struct uml_stat *ubuf)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	struct stat64 sbuf;
608c2ecf20Sopenharmony_ci	int err;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	CATCH_EINTR(err = stat64(file_name, &sbuf));
638c2ecf20Sopenharmony_ci	if (err < 0)
648c2ecf20Sopenharmony_ci		return -errno;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	if (ubuf != NULL)
678c2ecf20Sopenharmony_ci		copy_stat(ubuf, &sbuf);
688c2ecf20Sopenharmony_ci	return err;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ciint os_access(const char *file, int mode)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	int amode, err;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
768c2ecf20Sopenharmony_ci		(mode & OS_ACC_W_OK ? W_OK : 0) |
778c2ecf20Sopenharmony_ci		(mode & OS_ACC_X_OK ? X_OK : 0) |
788c2ecf20Sopenharmony_ci		(mode & OS_ACC_F_OK ? F_OK : 0);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	err = access(file, amode);
818c2ecf20Sopenharmony_ci	if (err < 0)
828c2ecf20Sopenharmony_ci		return -errno;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	return 0;
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
888c2ecf20Sopenharmony_ciint os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	int err;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	err = ioctl(fd, cmd, arg);
938c2ecf20Sopenharmony_ci	if (err < 0)
948c2ecf20Sopenharmony_ci		return -errno;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	return err;
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/* FIXME: ensure namebuf in os_get_if_name is big enough */
1008c2ecf20Sopenharmony_ciint os_get_ifname(int fd, char* namebuf)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
1038c2ecf20Sopenharmony_ci		return -errno;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	return 0;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ciint os_set_slip(int fd)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	int disc, sencap;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	disc = N_SLIP;
1138c2ecf20Sopenharmony_ci	if (ioctl(fd, TIOCSETD, &disc) < 0)
1148c2ecf20Sopenharmony_ci		return -errno;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	sencap = 0;
1178c2ecf20Sopenharmony_ci	if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
1188c2ecf20Sopenharmony_ci		return -errno;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	return 0;
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ciint os_mode_fd(int fd, int mode)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	int err;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	CATCH_EINTR(err = fchmod(fd, mode));
1288c2ecf20Sopenharmony_ci	if (err < 0)
1298c2ecf20Sopenharmony_ci		return -errno;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	return 0;
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ciint os_file_type(char *file)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	struct uml_stat buf;
1378c2ecf20Sopenharmony_ci	int err;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	err = os_stat_file(file, &buf);
1408c2ecf20Sopenharmony_ci	if (err < 0)
1418c2ecf20Sopenharmony_ci		return err;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	if (S_ISDIR(buf.ust_mode))
1448c2ecf20Sopenharmony_ci		return OS_TYPE_DIR;
1458c2ecf20Sopenharmony_ci	else if (S_ISLNK(buf.ust_mode))
1468c2ecf20Sopenharmony_ci		return OS_TYPE_SYMLINK;
1478c2ecf20Sopenharmony_ci	else if (S_ISCHR(buf.ust_mode))
1488c2ecf20Sopenharmony_ci		return OS_TYPE_CHARDEV;
1498c2ecf20Sopenharmony_ci	else if (S_ISBLK(buf.ust_mode))
1508c2ecf20Sopenharmony_ci		return OS_TYPE_BLOCKDEV;
1518c2ecf20Sopenharmony_ci	else if (S_ISFIFO(buf.ust_mode))
1528c2ecf20Sopenharmony_ci		return OS_TYPE_FIFO;
1538c2ecf20Sopenharmony_ci	else if (S_ISSOCK(buf.ust_mode))
1548c2ecf20Sopenharmony_ci		return OS_TYPE_SOCK;
1558c2ecf20Sopenharmony_ci	else return OS_TYPE_FILE;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ciint os_file_mode(const char *file, struct openflags *mode_out)
1598c2ecf20Sopenharmony_ci{
1608c2ecf20Sopenharmony_ci	int err;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	*mode_out = OPENFLAGS();
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	err = access(file, W_OK);
1658c2ecf20Sopenharmony_ci	if (err && (errno != EACCES))
1668c2ecf20Sopenharmony_ci		return -errno;
1678c2ecf20Sopenharmony_ci	else if (!err)
1688c2ecf20Sopenharmony_ci		*mode_out = of_write(*mode_out);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	err = access(file, R_OK);
1718c2ecf20Sopenharmony_ci	if (err && (errno != EACCES))
1728c2ecf20Sopenharmony_ci		return -errno;
1738c2ecf20Sopenharmony_ci	else if (!err)
1748c2ecf20Sopenharmony_ci		*mode_out = of_read(*mode_out);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	return err;
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ciint os_open_file(const char *file, struct openflags flags, int mode)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	int fd, err, f = 0;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	if (flags.r && flags.w)
1848c2ecf20Sopenharmony_ci		f = O_RDWR;
1858c2ecf20Sopenharmony_ci	else if (flags.r)
1868c2ecf20Sopenharmony_ci		f = O_RDONLY;
1878c2ecf20Sopenharmony_ci	else if (flags.w)
1888c2ecf20Sopenharmony_ci		f = O_WRONLY;
1898c2ecf20Sopenharmony_ci	else f = 0;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	if (flags.s)
1928c2ecf20Sopenharmony_ci		f |= O_SYNC;
1938c2ecf20Sopenharmony_ci	if (flags.c)
1948c2ecf20Sopenharmony_ci		f |= O_CREAT;
1958c2ecf20Sopenharmony_ci	if (flags.t)
1968c2ecf20Sopenharmony_ci		f |= O_TRUNC;
1978c2ecf20Sopenharmony_ci	if (flags.e)
1988c2ecf20Sopenharmony_ci		f |= O_EXCL;
1998c2ecf20Sopenharmony_ci	if (flags.a)
2008c2ecf20Sopenharmony_ci		f |= O_APPEND;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	fd = open64(file, f, mode);
2038c2ecf20Sopenharmony_ci	if (fd < 0)
2048c2ecf20Sopenharmony_ci		return -errno;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	if (flags.cl && fcntl(fd, F_SETFD, 1)) {
2078c2ecf20Sopenharmony_ci		err = -errno;
2088c2ecf20Sopenharmony_ci		close(fd);
2098c2ecf20Sopenharmony_ci		return err;
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	return fd;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ciint os_connect_socket(const char *name)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	struct sockaddr_un sock;
2188c2ecf20Sopenharmony_ci	int fd, err;
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	sock.sun_family = AF_UNIX;
2218c2ecf20Sopenharmony_ci	snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	fd = socket(AF_UNIX, SOCK_STREAM, 0);
2248c2ecf20Sopenharmony_ci	if (fd < 0) {
2258c2ecf20Sopenharmony_ci		err = -errno;
2268c2ecf20Sopenharmony_ci		goto out;
2278c2ecf20Sopenharmony_ci	}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
2308c2ecf20Sopenharmony_ci	if (err) {
2318c2ecf20Sopenharmony_ci		err = -errno;
2328c2ecf20Sopenharmony_ci		goto out_close;
2338c2ecf20Sopenharmony_ci	}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	return fd;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ciout_close:
2388c2ecf20Sopenharmony_ci	close(fd);
2398c2ecf20Sopenharmony_ciout:
2408c2ecf20Sopenharmony_ci	return err;
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_civoid os_close_file(int fd)
2448c2ecf20Sopenharmony_ci{
2458c2ecf20Sopenharmony_ci	close(fd);
2468c2ecf20Sopenharmony_ci}
2478c2ecf20Sopenharmony_ciint os_fsync_file(int fd)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	if (fsync(fd) < 0)
2508c2ecf20Sopenharmony_ci	    return -errno;
2518c2ecf20Sopenharmony_ci	return 0;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ciint os_seek_file(int fd, unsigned long long offset)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	unsigned long long actual;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	actual = lseek64(fd, offset, SEEK_SET);
2598c2ecf20Sopenharmony_ci	if (actual != offset)
2608c2ecf20Sopenharmony_ci		return -errno;
2618c2ecf20Sopenharmony_ci	return 0;
2628c2ecf20Sopenharmony_ci}
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ciint os_read_file(int fd, void *buf, int len)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	int n = read(fd, buf, len);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	if (n < 0)
2698c2ecf20Sopenharmony_ci		return -errno;
2708c2ecf20Sopenharmony_ci	return n;
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ciint os_pread_file(int fd, void *buf, int len, unsigned long long offset)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	int n = pread(fd, buf, len, offset);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	if (n < 0)
2788c2ecf20Sopenharmony_ci		return -errno;
2798c2ecf20Sopenharmony_ci	return n;
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ciint os_write_file(int fd, const void *buf, int len)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	int n = write(fd, (void *) buf, len);
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	if (n < 0)
2878c2ecf20Sopenharmony_ci		return -errno;
2888c2ecf20Sopenharmony_ci	return n;
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ciint os_sync_file(int fd)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	int n = fdatasync(fd);
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	if (n < 0)
2968c2ecf20Sopenharmony_ci		return -errno;
2978c2ecf20Sopenharmony_ci	return n;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ciint os_pwrite_file(int fd, const void *buf, int len, unsigned long long offset)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	int n = pwrite(fd, (void *) buf, len, offset);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	if (n < 0)
3058c2ecf20Sopenharmony_ci		return -errno;
3068c2ecf20Sopenharmony_ci	return n;
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ciint os_file_size(const char *file, unsigned long long *size_out)
3118c2ecf20Sopenharmony_ci{
3128c2ecf20Sopenharmony_ci	struct uml_stat buf;
3138c2ecf20Sopenharmony_ci	int err;
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	err = os_stat_file(file, &buf);
3168c2ecf20Sopenharmony_ci	if (err < 0) {
3178c2ecf20Sopenharmony_ci		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
3188c2ecf20Sopenharmony_ci		       -err);
3198c2ecf20Sopenharmony_ci		return err;
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if (S_ISBLK(buf.ust_mode)) {
3238c2ecf20Sopenharmony_ci		int fd;
3248c2ecf20Sopenharmony_ci		long blocks;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci		fd = open(file, O_RDONLY, 0);
3278c2ecf20Sopenharmony_ci		if (fd < 0) {
3288c2ecf20Sopenharmony_ci			err = -errno;
3298c2ecf20Sopenharmony_ci			printk(UM_KERN_ERR "Couldn't open \"%s\", "
3308c2ecf20Sopenharmony_ci			       "errno = %d\n", file, errno);
3318c2ecf20Sopenharmony_ci			return err;
3328c2ecf20Sopenharmony_ci		}
3338c2ecf20Sopenharmony_ci		if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
3348c2ecf20Sopenharmony_ci			err = -errno;
3358c2ecf20Sopenharmony_ci			printk(UM_KERN_ERR "Couldn't get the block size of "
3368c2ecf20Sopenharmony_ci			       "\"%s\", errno = %d\n", file, errno);
3378c2ecf20Sopenharmony_ci			close(fd);
3388c2ecf20Sopenharmony_ci			return err;
3398c2ecf20Sopenharmony_ci		}
3408c2ecf20Sopenharmony_ci		*size_out = ((long long) blocks) * 512;
3418c2ecf20Sopenharmony_ci		close(fd);
3428c2ecf20Sopenharmony_ci	}
3438c2ecf20Sopenharmony_ci	else *size_out = buf.ust_size;
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	return 0;
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ciint os_file_modtime(const char *file, long long *modtime)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	struct uml_stat buf;
3518c2ecf20Sopenharmony_ci	int err;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	err = os_stat_file(file, &buf);
3548c2ecf20Sopenharmony_ci	if (err < 0) {
3558c2ecf20Sopenharmony_ci		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
3568c2ecf20Sopenharmony_ci		       -err);
3578c2ecf20Sopenharmony_ci		return err;
3588c2ecf20Sopenharmony_ci	}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	*modtime = buf.ust_mtime;
3618c2ecf20Sopenharmony_ci	return 0;
3628c2ecf20Sopenharmony_ci}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ciint os_set_exec_close(int fd)
3658c2ecf20Sopenharmony_ci{
3668c2ecf20Sopenharmony_ci	int err;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	if (err < 0)
3718c2ecf20Sopenharmony_ci		return -errno;
3728c2ecf20Sopenharmony_ci	return err;
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ciint os_pipe(int *fds, int stream, int close_on_exec)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	err = socketpair(AF_UNIX, type, 0, fds);
3808c2ecf20Sopenharmony_ci	if (err < 0)
3818c2ecf20Sopenharmony_ci		return -errno;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	if (!close_on_exec)
3848c2ecf20Sopenharmony_ci		return 0;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	err = os_set_exec_close(fds[0]);
3878c2ecf20Sopenharmony_ci	if (err < 0)
3888c2ecf20Sopenharmony_ci		goto error;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	err = os_set_exec_close(fds[1]);
3918c2ecf20Sopenharmony_ci	if (err < 0)
3928c2ecf20Sopenharmony_ci		goto error;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	return 0;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci error:
3978c2ecf20Sopenharmony_ci	printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
3988c2ecf20Sopenharmony_ci	       -err);
3998c2ecf20Sopenharmony_ci	close(fds[1]);
4008c2ecf20Sopenharmony_ci	close(fds[0]);
4018c2ecf20Sopenharmony_ci	return err;
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ciint os_set_fd_async(int fd)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	int err, flags;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	flags = fcntl(fd, F_GETFL);
4098c2ecf20Sopenharmony_ci	if (flags < 0)
4108c2ecf20Sopenharmony_ci		return -errno;
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	flags |= O_ASYNC | O_NONBLOCK;
4138c2ecf20Sopenharmony_ci	if (fcntl(fd, F_SETFL, flags) < 0) {
4148c2ecf20Sopenharmony_ci		err = -errno;
4158c2ecf20Sopenharmony_ci		printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
4168c2ecf20Sopenharmony_ci		       "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
4178c2ecf20Sopenharmony_ci		return err;
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
4218c2ecf20Sopenharmony_ci	    (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
4228c2ecf20Sopenharmony_ci		err = -errno;
4238c2ecf20Sopenharmony_ci		printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
4248c2ecf20Sopenharmony_ci		       "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
4258c2ecf20Sopenharmony_ci		return err;
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	return 0;
4298c2ecf20Sopenharmony_ci}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ciint os_clear_fd_async(int fd)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	int flags;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	flags = fcntl(fd, F_GETFL);
4368c2ecf20Sopenharmony_ci	if (flags < 0)
4378c2ecf20Sopenharmony_ci		return -errno;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	flags &= ~(O_ASYNC | O_NONBLOCK);
4408c2ecf20Sopenharmony_ci	if (fcntl(fd, F_SETFL, flags) < 0)
4418c2ecf20Sopenharmony_ci		return -errno;
4428c2ecf20Sopenharmony_ci	return 0;
4438c2ecf20Sopenharmony_ci}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ciint os_set_fd_block(int fd, int blocking)
4468c2ecf20Sopenharmony_ci{
4478c2ecf20Sopenharmony_ci	int flags;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	flags = fcntl(fd, F_GETFL);
4508c2ecf20Sopenharmony_ci	if (flags < 0)
4518c2ecf20Sopenharmony_ci		return -errno;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	if (blocking)
4548c2ecf20Sopenharmony_ci		flags &= ~O_NONBLOCK;
4558c2ecf20Sopenharmony_ci	else
4568c2ecf20Sopenharmony_ci		flags |= O_NONBLOCK;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	if (fcntl(fd, F_SETFL, flags) < 0)
4598c2ecf20Sopenharmony_ci		return -errno;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	return 0;
4628c2ecf20Sopenharmony_ci}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ciint os_accept_connection(int fd)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	int new;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	new = accept(fd, NULL, 0);
4698c2ecf20Sopenharmony_ci	if (new < 0)
4708c2ecf20Sopenharmony_ci		return -errno;
4718c2ecf20Sopenharmony_ci	return new;
4728c2ecf20Sopenharmony_ci}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci#ifndef SHUT_RD
4758c2ecf20Sopenharmony_ci#define SHUT_RD 0
4768c2ecf20Sopenharmony_ci#endif
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci#ifndef SHUT_WR
4798c2ecf20Sopenharmony_ci#define SHUT_WR 1
4808c2ecf20Sopenharmony_ci#endif
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci#ifndef SHUT_RDWR
4838c2ecf20Sopenharmony_ci#define SHUT_RDWR 2
4848c2ecf20Sopenharmony_ci#endif
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ciint os_shutdown_socket(int fd, int r, int w)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	int what, err;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	if (r && w)
4918c2ecf20Sopenharmony_ci		what = SHUT_RDWR;
4928c2ecf20Sopenharmony_ci	else if (r)
4938c2ecf20Sopenharmony_ci		what = SHUT_RD;
4948c2ecf20Sopenharmony_ci	else if (w)
4958c2ecf20Sopenharmony_ci		what = SHUT_WR;
4968c2ecf20Sopenharmony_ci	else
4978c2ecf20Sopenharmony_ci		return -EINVAL;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	err = shutdown(fd, what);
5008c2ecf20Sopenharmony_ci	if (err < 0)
5018c2ecf20Sopenharmony_ci		return -errno;
5028c2ecf20Sopenharmony_ci	return 0;
5038c2ecf20Sopenharmony_ci}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ciint os_rcv_fd(int fd, int *helper_pid_out)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	int new, n;
5088c2ecf20Sopenharmony_ci	char buf[CMSG_SPACE(sizeof(new))];
5098c2ecf20Sopenharmony_ci	struct msghdr msg;
5108c2ecf20Sopenharmony_ci	struct cmsghdr *cmsg;
5118c2ecf20Sopenharmony_ci	struct iovec iov;
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	msg.msg_name = NULL;
5148c2ecf20Sopenharmony_ci	msg.msg_namelen = 0;
5158c2ecf20Sopenharmony_ci	iov = ((struct iovec) { .iov_base  = helper_pid_out,
5168c2ecf20Sopenharmony_ci				.iov_len   = sizeof(*helper_pid_out) });
5178c2ecf20Sopenharmony_ci	msg.msg_iov = &iov;
5188c2ecf20Sopenharmony_ci	msg.msg_iovlen = 1;
5198c2ecf20Sopenharmony_ci	msg.msg_control = buf;
5208c2ecf20Sopenharmony_ci	msg.msg_controllen = sizeof(buf);
5218c2ecf20Sopenharmony_ci	msg.msg_flags = 0;
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	n = recvmsg(fd, &msg, 0);
5248c2ecf20Sopenharmony_ci	if (n < 0)
5258c2ecf20Sopenharmony_ci		return -errno;
5268c2ecf20Sopenharmony_ci	else if (n != iov.iov_len)
5278c2ecf20Sopenharmony_ci		*helper_pid_out = -1;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	cmsg = CMSG_FIRSTHDR(&msg);
5308c2ecf20Sopenharmony_ci	if (cmsg == NULL) {
5318c2ecf20Sopenharmony_ci		printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
5328c2ecf20Sopenharmony_ci		       "error = %d\n", errno);
5338c2ecf20Sopenharmony_ci		return -1;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci	if ((cmsg->cmsg_level != SOL_SOCKET) ||
5368c2ecf20Sopenharmony_ci	    (cmsg->cmsg_type != SCM_RIGHTS)) {
5378c2ecf20Sopenharmony_ci		printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
5388c2ecf20Sopenharmony_ci		return -1;
5398c2ecf20Sopenharmony_ci	}
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	new = ((int *) CMSG_DATA(cmsg))[0];
5428c2ecf20Sopenharmony_ci	return new;
5438c2ecf20Sopenharmony_ci}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ciint os_create_unix_socket(const char *file, int len, int close_on_exec)
5468c2ecf20Sopenharmony_ci{
5478c2ecf20Sopenharmony_ci	struct sockaddr_un addr;
5488c2ecf20Sopenharmony_ci	int sock, err;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
5518c2ecf20Sopenharmony_ci	if (sock < 0)
5528c2ecf20Sopenharmony_ci		return -errno;
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	if (close_on_exec) {
5558c2ecf20Sopenharmony_ci		err = os_set_exec_close(sock);
5568c2ecf20Sopenharmony_ci		if (err < 0)
5578c2ecf20Sopenharmony_ci			printk(UM_KERN_ERR "create_unix_socket : "
5588c2ecf20Sopenharmony_ci			       "close_on_exec failed, err = %d", -err);
5598c2ecf20Sopenharmony_ci	}
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	addr.sun_family = AF_UNIX;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	snprintf(addr.sun_path, len, "%s", file);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
5668c2ecf20Sopenharmony_ci	if (err < 0)
5678c2ecf20Sopenharmony_ci		return -errno;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	return sock;
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_civoid os_flush_stdout(void)
5738c2ecf20Sopenharmony_ci{
5748c2ecf20Sopenharmony_ci	fflush(stdout);
5758c2ecf20Sopenharmony_ci}
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ciint os_lock_file(int fd, int excl)
5788c2ecf20Sopenharmony_ci{
5798c2ecf20Sopenharmony_ci	int type = excl ? F_WRLCK : F_RDLCK;
5808c2ecf20Sopenharmony_ci	struct flock lock = ((struct flock) { .l_type	= type,
5818c2ecf20Sopenharmony_ci					      .l_whence	= SEEK_SET,
5828c2ecf20Sopenharmony_ci					      .l_start	= 0,
5838c2ecf20Sopenharmony_ci					      .l_len	= 0 } );
5848c2ecf20Sopenharmony_ci	int err, save;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	err = fcntl(fd, F_SETLK, &lock);
5878c2ecf20Sopenharmony_ci	if (!err)
5888c2ecf20Sopenharmony_ci		goto out;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	save = -errno;
5918c2ecf20Sopenharmony_ci	err = fcntl(fd, F_GETLK, &lock);
5928c2ecf20Sopenharmony_ci	if (err) {
5938c2ecf20Sopenharmony_ci		err = -errno;
5948c2ecf20Sopenharmony_ci		goto out;
5958c2ecf20Sopenharmony_ci	}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
5988c2ecf20Sopenharmony_ci	       lock.l_pid);
5998c2ecf20Sopenharmony_ci	err = save;
6008c2ecf20Sopenharmony_ci out:
6018c2ecf20Sopenharmony_ci	return err;
6028c2ecf20Sopenharmony_ci}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ciunsigned os_major(unsigned long long dev)
6058c2ecf20Sopenharmony_ci{
6068c2ecf20Sopenharmony_ci	return major(dev);
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ciunsigned os_minor(unsigned long long dev)
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	return minor(dev);
6128c2ecf20Sopenharmony_ci}
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ciunsigned long long os_makedev(unsigned major, unsigned minor)
6158c2ecf20Sopenharmony_ci{
6168c2ecf20Sopenharmony_ci	return makedev(major, minor);
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ciint os_falloc_punch(int fd, unsigned long long offset, int len)
6208c2ecf20Sopenharmony_ci{
6218c2ecf20Sopenharmony_ci	int n = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, len);
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	if (n < 0)
6248c2ecf20Sopenharmony_ci		return -errno;
6258c2ecf20Sopenharmony_ci	return n;
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ciint os_eventfd(unsigned int initval, int flags)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	int fd = eventfd(initval, flags);
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	if (fd < 0)
6338c2ecf20Sopenharmony_ci		return -errno;
6348c2ecf20Sopenharmony_ci	return fd;
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ciint os_sendmsg_fds(int fd, const void *buf, unsigned int len, const int *fds,
6388c2ecf20Sopenharmony_ci		   unsigned int fds_num)
6398c2ecf20Sopenharmony_ci{
6408c2ecf20Sopenharmony_ci	struct iovec iov = {
6418c2ecf20Sopenharmony_ci		.iov_base = (void *) buf,
6428c2ecf20Sopenharmony_ci		.iov_len = len,
6438c2ecf20Sopenharmony_ci	};
6448c2ecf20Sopenharmony_ci	union {
6458c2ecf20Sopenharmony_ci		char control[CMSG_SPACE(sizeof(*fds) * OS_SENDMSG_MAX_FDS)];
6468c2ecf20Sopenharmony_ci		struct cmsghdr align;
6478c2ecf20Sopenharmony_ci	} u;
6488c2ecf20Sopenharmony_ci	unsigned int fds_size = sizeof(*fds) * fds_num;
6498c2ecf20Sopenharmony_ci	struct msghdr msg = {
6508c2ecf20Sopenharmony_ci		.msg_iov = &iov,
6518c2ecf20Sopenharmony_ci		.msg_iovlen = 1,
6528c2ecf20Sopenharmony_ci		.msg_control = u.control,
6538c2ecf20Sopenharmony_ci		.msg_controllen = CMSG_SPACE(fds_size),
6548c2ecf20Sopenharmony_ci	};
6558c2ecf20Sopenharmony_ci	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
6568c2ecf20Sopenharmony_ci	int err;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	if (fds_num > OS_SENDMSG_MAX_FDS)
6598c2ecf20Sopenharmony_ci		return -EINVAL;
6608c2ecf20Sopenharmony_ci	memset(u.control, 0, sizeof(u.control));
6618c2ecf20Sopenharmony_ci	cmsg->cmsg_level = SOL_SOCKET;
6628c2ecf20Sopenharmony_ci	cmsg->cmsg_type = SCM_RIGHTS;
6638c2ecf20Sopenharmony_ci	cmsg->cmsg_len = CMSG_LEN(fds_size);
6648c2ecf20Sopenharmony_ci	memcpy(CMSG_DATA(cmsg), fds, fds_size);
6658c2ecf20Sopenharmony_ci	err = sendmsg(fd, &msg, 0);
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	if (err < 0)
6688c2ecf20Sopenharmony_ci		return -errno;
6698c2ecf20Sopenharmony_ci	return err;
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ciint os_poll(unsigned int n, const int *fds)
6738c2ecf20Sopenharmony_ci{
6748c2ecf20Sopenharmony_ci	/* currently need 2 FDs at most so avoid dynamic allocation */
6758c2ecf20Sopenharmony_ci	struct pollfd pollfds[2] = {};
6768c2ecf20Sopenharmony_ci	unsigned int i;
6778c2ecf20Sopenharmony_ci	int ret;
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	if (n > ARRAY_SIZE(pollfds))
6808c2ecf20Sopenharmony_ci		return -EINVAL;
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci	for (i = 0; i < n; i++) {
6838c2ecf20Sopenharmony_ci		pollfds[i].fd = fds[i];
6848c2ecf20Sopenharmony_ci		pollfds[i].events = POLLIN;
6858c2ecf20Sopenharmony_ci	}
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	ret = poll(pollfds, n, -1);
6888c2ecf20Sopenharmony_ci	if (ret < 0)
6898c2ecf20Sopenharmony_ci		return -errno;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	/* Return the index of the available FD */
6928c2ecf20Sopenharmony_ci	for (i = 0; i < n; i++) {
6938c2ecf20Sopenharmony_ci		if (pollfds[i].revents)
6948c2ecf20Sopenharmony_ci			return i;
6958c2ecf20Sopenharmony_ci	}
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	return -EIO;
6988c2ecf20Sopenharmony_ci}
699