xref: /openbmc/linux/arch/um/os-Linux/file.c (revision 005a59ec)
11da177e4SLinus Torvalds /*
21adfd609SJeff Dike  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
31da177e4SLinus Torvalds  * Licensed under the GPL
41da177e4SLinus Torvalds  */
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <stdio.h>
71da177e4SLinus Torvalds #include <unistd.h>
81da177e4SLinus Torvalds #include <errno.h>
91da177e4SLinus Torvalds #include <fcntl.h>
101da177e4SLinus Torvalds #include <signal.h>
111da177e4SLinus Torvalds #include <sys/ioctl.h>
121da177e4SLinus Torvalds #include <sys/mount.h>
131adfd609SJeff Dike #include <sys/socket.h>
141adfd609SJeff Dike #include <sys/stat.h>
151adfd609SJeff Dike #include <sys/un.h>
161adfd609SJeff Dike #include "kern_constants.h"
171da177e4SLinus Torvalds #include "os.h"
181da177e4SLinus Torvalds #include "user.h"
191da177e4SLinus Torvalds 
20c9a3072dSWANG Cong static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
211da177e4SLinus Torvalds {
221da177e4SLinus Torvalds 	*dst = ((struct uml_stat) {
231da177e4SLinus Torvalds 		.ust_dev     = src->st_dev,     /* device */
241da177e4SLinus Torvalds 		.ust_ino     = src->st_ino,     /* inode */
251da177e4SLinus Torvalds 		.ust_mode    = src->st_mode,    /* protection */
261da177e4SLinus Torvalds 		.ust_nlink   = src->st_nlink,   /* number of hard links */
271da177e4SLinus Torvalds 		.ust_uid     = src->st_uid,     /* user ID of owner */
281da177e4SLinus Torvalds 		.ust_gid     = src->st_gid,     /* group ID of owner */
291da177e4SLinus Torvalds 		.ust_size    = src->st_size,    /* total size, in bytes */
301da177e4SLinus Torvalds 		.ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
311da177e4SLinus Torvalds 		.ust_blocks  = src->st_blocks,  /* number of blocks allocated */
321da177e4SLinus Torvalds 		.ust_atime   = src->st_atime,   /* time of last access */
331da177e4SLinus Torvalds 		.ust_mtime   = src->st_mtime,   /* time of last modification */
341da177e4SLinus Torvalds 		.ust_ctime   = src->st_ctime,   /* time of last change */
351da177e4SLinus Torvalds 	});
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds int os_stat_fd(const int fd, struct uml_stat *ubuf)
391da177e4SLinus Torvalds {
401da177e4SLinus Torvalds 	struct stat64 sbuf;
411da177e4SLinus Torvalds 	int err;
421da177e4SLinus Torvalds 
439ead6feeSJeff Dike 	CATCH_EINTR(err = fstat64(fd, &sbuf));
441da177e4SLinus Torvalds 	if (err < 0)
45108ffa8cSJeff Dike 		return -errno;
461da177e4SLinus Torvalds 
471da177e4SLinus Torvalds 	if (ubuf != NULL)
481da177e4SLinus Torvalds 		copy_stat(ubuf, &sbuf);
49108ffa8cSJeff Dike 	return err;
501da177e4SLinus Torvalds }
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds int os_stat_file(const char *file_name, struct uml_stat *ubuf)
531da177e4SLinus Torvalds {
541da177e4SLinus Torvalds 	struct stat64 sbuf;
551da177e4SLinus Torvalds 	int err;
561da177e4SLinus Torvalds 
571adfd609SJeff Dike 	CATCH_EINTR(err = stat64(file_name, &sbuf));
581da177e4SLinus Torvalds 	if (err < 0)
59108ffa8cSJeff Dike 		return -errno;
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds 	if (ubuf != NULL)
621da177e4SLinus Torvalds 		copy_stat(ubuf, &sbuf);
63108ffa8cSJeff Dike 	return err;
641da177e4SLinus Torvalds }
651da177e4SLinus Torvalds 
661da177e4SLinus Torvalds int os_access(const char *file, int mode)
671da177e4SLinus Torvalds {
681da177e4SLinus Torvalds 	int amode, err;
691da177e4SLinus Torvalds 
701adfd609SJeff Dike 	amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
711adfd609SJeff Dike 		(mode & OS_ACC_W_OK ? W_OK : 0) |
721adfd609SJeff Dike 		(mode & OS_ACC_X_OK ? X_OK : 0) |
731adfd609SJeff Dike 		(mode & OS_ACC_F_OK ? F_OK : 0);
741da177e4SLinus Torvalds 
751da177e4SLinus Torvalds 	err = access(file, amode);
761da177e4SLinus Torvalds 	if (err < 0)
77108ffa8cSJeff Dike 		return -errno;
781da177e4SLinus Torvalds 
79108ffa8cSJeff Dike 	return 0;
801da177e4SLinus Torvalds }
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
831da177e4SLinus Torvalds int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
841da177e4SLinus Torvalds {
851da177e4SLinus Torvalds 	int err;
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds 	err = ioctl(fd, cmd, arg);
881da177e4SLinus Torvalds 	if (err < 0)
89108ffa8cSJeff Dike 		return -errno;
901da177e4SLinus Torvalds 
91108ffa8cSJeff Dike 	return err;
921da177e4SLinus Torvalds }
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds /* FIXME: ensure namebuf in os_get_if_name is big enough */
951da177e4SLinus Torvalds int os_get_ifname(int fd, char* namebuf)
961da177e4SLinus Torvalds {
971da177e4SLinus Torvalds 	if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
98108ffa8cSJeff Dike 		return -errno;
991da177e4SLinus Torvalds 
100108ffa8cSJeff Dike 	return 0;
1011da177e4SLinus Torvalds }
1021da177e4SLinus Torvalds 
1031da177e4SLinus Torvalds int os_set_slip(int fd)
1041da177e4SLinus Torvalds {
1051da177e4SLinus Torvalds 	int disc, sencap;
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds 	disc = N_SLIP;
108b4fd310eSJeff Dike 	if (ioctl(fd, TIOCSETD, &disc) < 0)
109b4fd310eSJeff Dike 		return -errno;
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 	sencap = 0;
112b4fd310eSJeff Dike 	if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
113b4fd310eSJeff Dike 		return -errno;
1141da177e4SLinus Torvalds 
115108ffa8cSJeff Dike 	return 0;
1161da177e4SLinus Torvalds }
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds int os_mode_fd(int fd, int mode)
1191da177e4SLinus Torvalds {
1201da177e4SLinus Torvalds 	int err;
1211da177e4SLinus Torvalds 
1221adfd609SJeff Dike 	CATCH_EINTR(err = fchmod(fd, mode));
1231da177e4SLinus Torvalds 	if (err < 0)
124108ffa8cSJeff Dike 		return -errno;
1251da177e4SLinus Torvalds 
126108ffa8cSJeff Dike 	return 0;
1271da177e4SLinus Torvalds }
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds int os_file_type(char *file)
1301da177e4SLinus Torvalds {
1311da177e4SLinus Torvalds 	struct uml_stat buf;
1321da177e4SLinus Torvalds 	int err;
1331da177e4SLinus Torvalds 
1341da177e4SLinus Torvalds 	err = os_stat_file(file, &buf);
1351da177e4SLinus Torvalds 	if (err < 0)
136108ffa8cSJeff Dike 		return err;
1371da177e4SLinus Torvalds 
138108ffa8cSJeff Dike 	if (S_ISDIR(buf.ust_mode))
139108ffa8cSJeff Dike 		return OS_TYPE_DIR;
140108ffa8cSJeff Dike 	else if (S_ISLNK(buf.ust_mode))
141108ffa8cSJeff Dike 		return OS_TYPE_SYMLINK;
142108ffa8cSJeff Dike 	else if (S_ISCHR(buf.ust_mode))
143108ffa8cSJeff Dike 		return OS_TYPE_CHARDEV;
144108ffa8cSJeff Dike 	else if (S_ISBLK(buf.ust_mode))
145108ffa8cSJeff Dike 		return OS_TYPE_BLOCKDEV;
146108ffa8cSJeff Dike 	else if (S_ISFIFO(buf.ust_mode))
147108ffa8cSJeff Dike 		return OS_TYPE_FIFO;
148108ffa8cSJeff Dike 	else if (S_ISSOCK(buf.ust_mode))
149108ffa8cSJeff Dike 		return OS_TYPE_SOCK;
150108ffa8cSJeff Dike 	else return OS_TYPE_FILE;
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds 
153c9a3072dSWANG Cong int os_file_mode(const char *file, struct openflags *mode_out)
1541da177e4SLinus Torvalds {
1551da177e4SLinus Torvalds 	int err;
1561da177e4SLinus Torvalds 
1571da177e4SLinus Torvalds 	*mode_out = OPENFLAGS();
1581da177e4SLinus Torvalds 
159512b6fb1SJeff Dike 	err = access(file, W_OK);
160512b6fb1SJeff Dike 	if (err && (errno != EACCES))
161512b6fb1SJeff Dike 		return -errno;
162512b6fb1SJeff Dike 	else if (!err)
1631da177e4SLinus Torvalds 		*mode_out = of_write(*mode_out);
1641da177e4SLinus Torvalds 
165512b6fb1SJeff Dike 	err = access(file, R_OK);
166512b6fb1SJeff Dike 	if (err && (errno != EACCES))
167512b6fb1SJeff Dike 		return -errno;
168512b6fb1SJeff Dike 	else if (!err)
1691da177e4SLinus Torvalds 		*mode_out = of_read(*mode_out);
1701da177e4SLinus Torvalds 
171512b6fb1SJeff Dike 	return err;
1721da177e4SLinus Torvalds }
1731da177e4SLinus Torvalds 
174c9a3072dSWANG Cong int os_open_file(const char *file, struct openflags flags, int mode)
1751da177e4SLinus Torvalds {
176b4fd310eSJeff Dike 	int fd, err, f = 0;
1771da177e4SLinus Torvalds 
1781adfd609SJeff Dike 	if (flags.r && flags.w)
1791adfd609SJeff Dike 		f = O_RDWR;
1801adfd609SJeff Dike 	else if (flags.r)
1811adfd609SJeff Dike 		f = O_RDONLY;
1821adfd609SJeff Dike 	else if (flags.w)
1831adfd609SJeff Dike 		f = O_WRONLY;
1841da177e4SLinus Torvalds 	else f = 0;
1851da177e4SLinus Torvalds 
1861adfd609SJeff Dike 	if (flags.s)
1871adfd609SJeff Dike 		f |= O_SYNC;
1881adfd609SJeff Dike 	if (flags.c)
1891adfd609SJeff Dike 		f |= O_CREAT;
1901adfd609SJeff Dike 	if (flags.t)
1911adfd609SJeff Dike 		f |= O_TRUNC;
1921adfd609SJeff Dike 	if (flags.e)
1931adfd609SJeff Dike 		f |= O_EXCL;
194bf53d85eSJeff Dike 	if (flags.a)
195bf53d85eSJeff Dike 		f |= O_APPEND;
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds 	fd = open64(file, f, mode);
1981da177e4SLinus Torvalds 	if (fd < 0)
199512b6fb1SJeff Dike 		return -errno;
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	if (flags.cl && fcntl(fd, F_SETFD, 1)) {
202b4fd310eSJeff Dike 		err = -errno;
203512b6fb1SJeff Dike 		close(fd);
204b4fd310eSJeff Dike 		return err;
2051da177e4SLinus Torvalds 	}
2061da177e4SLinus Torvalds 
207512b6fb1SJeff Dike 	return fd;
2081da177e4SLinus Torvalds }
2091da177e4SLinus Torvalds 
210c9a3072dSWANG Cong int os_connect_socket(const char *name)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds 	struct sockaddr_un sock;
2131da177e4SLinus Torvalds 	int fd, err;
2141da177e4SLinus Torvalds 
2151da177e4SLinus Torvalds 	sock.sun_family = AF_UNIX;
2161da177e4SLinus Torvalds 	snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
2171da177e4SLinus Torvalds 
2181da177e4SLinus Torvalds 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
219dc1561acSPaolo 'Blaisorblade' Giarrusso 	if (fd < 0) {
220dc1561acSPaolo 'Blaisorblade' Giarrusso 		err = -errno;
221dc1561acSPaolo 'Blaisorblade' Giarrusso 		goto out;
222dc1561acSPaolo 'Blaisorblade' Giarrusso 	}
2231da177e4SLinus Torvalds 
2241da177e4SLinus Torvalds 	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
225dc1561acSPaolo 'Blaisorblade' Giarrusso 	if (err) {
226dc1561acSPaolo 'Blaisorblade' Giarrusso 		err = -errno;
227dc1561acSPaolo 'Blaisorblade' Giarrusso 		goto out_close;
228dc1561acSPaolo 'Blaisorblade' Giarrusso 	}
2291da177e4SLinus Torvalds 
230dc1561acSPaolo 'Blaisorblade' Giarrusso 	return fd;
231dc1561acSPaolo 'Blaisorblade' Giarrusso 
232dc1561acSPaolo 'Blaisorblade' Giarrusso out_close:
233dc1561acSPaolo 'Blaisorblade' Giarrusso 	close(fd);
234dc1561acSPaolo 'Blaisorblade' Giarrusso out:
235dc1561acSPaolo 'Blaisorblade' Giarrusso 	return err;
2361da177e4SLinus Torvalds }
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds void os_close_file(int fd)
2391da177e4SLinus Torvalds {
2401da177e4SLinus Torvalds 	close(fd);
2411da177e4SLinus Torvalds }
2421da177e4SLinus Torvalds 
243ba180fd4SJeff Dike int os_seek_file(int fd, unsigned long long offset)
2441da177e4SLinus Torvalds {
245ba180fd4SJeff Dike 	unsigned long long actual;
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds 	actual = lseek64(fd, offset, SEEK_SET);
2481da177e4SLinus Torvalds 	if (actual != offset)
249108ffa8cSJeff Dike 		return -errno;
250108ffa8cSJeff Dike 	return 0;
2511da177e4SLinus Torvalds }
2521da177e4SLinus Torvalds 
2531da177e4SLinus Torvalds int os_read_file(int fd, void *buf, int len)
2541da177e4SLinus Torvalds {
2553d564047SJeff Dike 	int n = read(fd, buf, len);
2563d564047SJeff Dike 
2573d564047SJeff Dike 	if (n < 0)
2583d564047SJeff Dike 		return -errno;
2593d564047SJeff Dike 	return n;
2603d564047SJeff Dike }
2613d564047SJeff Dike 
2621da177e4SLinus Torvalds int os_write_file(int fd, const void *buf, int len)
2631da177e4SLinus Torvalds {
2643d564047SJeff Dike 	int n = write(fd, (void *) buf, len);
2653d564047SJeff Dike 
2663d564047SJeff Dike 	if (n < 0)
2673d564047SJeff Dike 		return -errno;
2683d564047SJeff Dike 	return n;
2693d564047SJeff Dike }
2703d564047SJeff Dike 
271c9a3072dSWANG Cong int os_file_size(const char *file, unsigned long long *size_out)
2721da177e4SLinus Torvalds {
2731da177e4SLinus Torvalds 	struct uml_stat buf;
2741da177e4SLinus Torvalds 	int err;
2751da177e4SLinus Torvalds 
2761da177e4SLinus Torvalds 	err = os_stat_file(file, &buf);
2771da177e4SLinus Torvalds 	if (err < 0) {
2781adfd609SJeff Dike 		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
2791adfd609SJeff Dike 		       -err);
280512b6fb1SJeff Dike 		return err;
2811da177e4SLinus Torvalds 	}
2821da177e4SLinus Torvalds 
2831da177e4SLinus Torvalds 	if (S_ISBLK(buf.ust_mode)) {
2842c392a4fSNicolas George 		int fd;
2852c392a4fSNicolas George 		long blocks;
2861da177e4SLinus Torvalds 
287512b6fb1SJeff Dike 		fd = open(file, O_RDONLY, 0);
2881da177e4SLinus Torvalds 		if (fd < 0) {
289512b6fb1SJeff Dike 			err = -errno;
2901adfd609SJeff Dike 			printk(UM_KERN_ERR "Couldn't open \"%s\", "
2911adfd609SJeff Dike 			       "errno = %d\n", file, errno);
292512b6fb1SJeff Dike 			return err;
2931da177e4SLinus Torvalds 		}
2941da177e4SLinus Torvalds 		if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
295b4fd310eSJeff Dike 			err = -errno;
2961adfd609SJeff Dike 			printk(UM_KERN_ERR "Couldn't get the block size of "
2971adfd609SJeff Dike 			       "\"%s\", errno = %d\n", file, errno);
298512b6fb1SJeff Dike 			close(fd);
299512b6fb1SJeff Dike 			return err;
3001da177e4SLinus Torvalds 		}
3011da177e4SLinus Torvalds 		*size_out = ((long long) blocks) * 512;
302512b6fb1SJeff Dike 		close(fd);
3031da177e4SLinus Torvalds 	}
304512b6fb1SJeff Dike 	else *size_out = buf.ust_size;
305512b6fb1SJeff Dike 
306512b6fb1SJeff Dike 	return 0;
3071da177e4SLinus Torvalds }
3081da177e4SLinus Torvalds 
309c9a3072dSWANG Cong int os_file_modtime(const char *file, unsigned long *modtime)
3101da177e4SLinus Torvalds {
3111da177e4SLinus Torvalds 	struct uml_stat buf;
3121da177e4SLinus Torvalds 	int err;
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds 	err = os_stat_file(file, &buf);
3151da177e4SLinus Torvalds 	if (err < 0) {
3161adfd609SJeff Dike 		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
3171adfd609SJeff Dike 		       -err);
318108ffa8cSJeff Dike 		return err;
3191da177e4SLinus Torvalds 	}
3201da177e4SLinus Torvalds 
3211da177e4SLinus Torvalds 	*modtime = buf.ust_mtime;
322108ffa8cSJeff Dike 	return 0;
3231da177e4SLinus Torvalds }
3241da177e4SLinus Torvalds 
325512b6fb1SJeff Dike int os_set_exec_close(int fd)
3261da177e4SLinus Torvalds {
327512b6fb1SJeff Dike 	int err;
3281da177e4SLinus Torvalds 
329512b6fb1SJeff Dike 	CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
3301da177e4SLinus Torvalds 
3311da177e4SLinus Torvalds 	if (err < 0)
332512b6fb1SJeff Dike 		return -errno;
333512b6fb1SJeff Dike 	return err;
3341da177e4SLinus Torvalds }
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds int os_pipe(int *fds, int stream, int close_on_exec)
3371da177e4SLinus Torvalds {
3381da177e4SLinus Torvalds 	int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
3391da177e4SLinus Torvalds 
3401da177e4SLinus Torvalds 	err = socketpair(AF_UNIX, type, 0, fds);
3411da177e4SLinus Torvalds 	if (err < 0)
342512b6fb1SJeff Dike 		return -errno;
3431da177e4SLinus Torvalds 
3441da177e4SLinus Torvalds 	if (!close_on_exec)
345512b6fb1SJeff Dike 		return 0;
3461da177e4SLinus Torvalds 
347512b6fb1SJeff Dike 	err = os_set_exec_close(fds[0]);
3481da177e4SLinus Torvalds 	if (err < 0)
3491da177e4SLinus Torvalds 		goto error;
3501da177e4SLinus Torvalds 
351512b6fb1SJeff Dike 	err = os_set_exec_close(fds[1]);
3521da177e4SLinus Torvalds 	if (err < 0)
3531da177e4SLinus Torvalds 		goto error;
3541da177e4SLinus Torvalds 
355108ffa8cSJeff Dike 	return 0;
3561da177e4SLinus Torvalds 
3571da177e4SLinus Torvalds  error:
3581adfd609SJeff Dike 	printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
3591adfd609SJeff Dike 	       -err);
360512b6fb1SJeff Dike 	close(fds[1]);
361512b6fb1SJeff Dike 	close(fds[0]);
362512b6fb1SJeff Dike 	return err;
3631da177e4SLinus Torvalds }
3641da177e4SLinus Torvalds 
365bf8fde78SJeff Dike int os_set_fd_async(int fd)
3661da177e4SLinus Torvalds {
367bf8fde78SJeff Dike 	int err, flags;
368b4fd310eSJeff Dike 
369bf8fde78SJeff Dike 	flags = fcntl(fd, F_GETFL);
370bf8fde78SJeff Dike 	if (flags < 0)
371bf8fde78SJeff Dike 		return -errno;
372bf8fde78SJeff Dike 
373bf8fde78SJeff Dike 	flags |= O_ASYNC | O_NONBLOCK;
374bf8fde78SJeff Dike 	if (fcntl(fd, F_SETFL, flags) < 0) {
375b4fd310eSJeff Dike 		err = -errno;
3761adfd609SJeff Dike 		printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
3771adfd609SJeff Dike 		       "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
378b4fd310eSJeff Dike 		return err;
3791da177e4SLinus Torvalds 	}
3801da177e4SLinus Torvalds 
3811da177e4SLinus Torvalds 	if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
382bf8fde78SJeff Dike 	    (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
383b4fd310eSJeff Dike 		err = -errno;
3841adfd609SJeff Dike 		printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
385bf8fde78SJeff Dike 		       "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
386b4fd310eSJeff Dike 		return err;
3871da177e4SLinus Torvalds 	}
3881da177e4SLinus Torvalds 
389108ffa8cSJeff Dike 	return 0;
3901da177e4SLinus Torvalds }
3911da177e4SLinus Torvalds 
3921da177e4SLinus Torvalds int os_clear_fd_async(int fd)
3931da177e4SLinus Torvalds {
3941adfd609SJeff Dike 	int flags;
3951adfd609SJeff Dike 
3961adfd609SJeff Dike 	flags = fcntl(fd, F_GETFL);
3971adfd609SJeff Dike 	if (flags < 0)
3981adfd609SJeff Dike 		return -errno;
3991da177e4SLinus Torvalds 
4001da177e4SLinus Torvalds 	flags &= ~(O_ASYNC | O_NONBLOCK);
4011da177e4SLinus Torvalds 	if (fcntl(fd, F_SETFL, flags) < 0)
402108ffa8cSJeff Dike 		return -errno;
403108ffa8cSJeff Dike 	return 0;
4041da177e4SLinus Torvalds }
4051da177e4SLinus Torvalds 
4061da177e4SLinus Torvalds int os_set_fd_block(int fd, int blocking)
4071da177e4SLinus Torvalds {
4081da177e4SLinus Torvalds 	int flags;
4091da177e4SLinus Torvalds 
4101da177e4SLinus Torvalds 	flags = fcntl(fd, F_GETFL);
4111adfd609SJeff Dike 	if (flags < 0)
4121adfd609SJeff Dike 		return -errno;
4131da177e4SLinus Torvalds 
4141adfd609SJeff Dike 	if (blocking)
4151adfd609SJeff Dike 		flags &= ~O_NONBLOCK;
4161adfd609SJeff Dike 	else
4171adfd609SJeff Dike 		flags |= O_NONBLOCK;
4181da177e4SLinus Torvalds 
419b4fd310eSJeff Dike 	if (fcntl(fd, F_SETFL, flags) < 0)
420b4fd310eSJeff Dike 		return -errno;
421b4fd310eSJeff Dike 
422108ffa8cSJeff Dike 	return 0;
4231da177e4SLinus Torvalds }
4241da177e4SLinus Torvalds 
4251da177e4SLinus Torvalds int os_accept_connection(int fd)
4261da177e4SLinus Torvalds {
4271da177e4SLinus Torvalds 	int new;
4281da177e4SLinus Torvalds 
4291da177e4SLinus Torvalds 	new = accept(fd, NULL, 0);
4301da177e4SLinus Torvalds 	if (new < 0)
431108ffa8cSJeff Dike 		return -errno;
432108ffa8cSJeff Dike 	return new;
4331da177e4SLinus Torvalds }
4341da177e4SLinus Torvalds 
4351da177e4SLinus Torvalds #ifndef SHUT_RD
4361da177e4SLinus Torvalds #define SHUT_RD 0
4371da177e4SLinus Torvalds #endif
4381da177e4SLinus Torvalds 
4391da177e4SLinus Torvalds #ifndef SHUT_WR
4401da177e4SLinus Torvalds #define SHUT_WR 1
4411da177e4SLinus Torvalds #endif
4421da177e4SLinus Torvalds 
4431da177e4SLinus Torvalds #ifndef SHUT_RDWR
4441da177e4SLinus Torvalds #define SHUT_RDWR 2
4451da177e4SLinus Torvalds #endif
4461da177e4SLinus Torvalds 
4471da177e4SLinus Torvalds int os_shutdown_socket(int fd, int r, int w)
4481da177e4SLinus Torvalds {
4491da177e4SLinus Torvalds 	int what, err;
4501da177e4SLinus Torvalds 
4511adfd609SJeff Dike 	if (r && w)
4521adfd609SJeff Dike 		what = SHUT_RDWR;
4531adfd609SJeff Dike 	else if (r)
4541adfd609SJeff Dike 		what = SHUT_RD;
4551adfd609SJeff Dike 	else if (w)
4561adfd609SJeff Dike 		what = SHUT_WR;
4571adfd609SJeff Dike 	else
458108ffa8cSJeff Dike 		return -EINVAL;
4591adfd609SJeff Dike 
4601da177e4SLinus Torvalds 	err = shutdown(fd, what);
4611da177e4SLinus Torvalds 	if (err < 0)
462108ffa8cSJeff Dike 		return -errno;
463108ffa8cSJeff Dike 	return 0;
4641da177e4SLinus Torvalds }
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds int os_rcv_fd(int fd, int *helper_pid_out)
4671da177e4SLinus Torvalds {
4681da177e4SLinus Torvalds 	int new, n;
4691da177e4SLinus Torvalds 	char buf[CMSG_SPACE(sizeof(new))];
4701da177e4SLinus Torvalds 	struct msghdr msg;
4711da177e4SLinus Torvalds 	struct cmsghdr *cmsg;
4721da177e4SLinus Torvalds 	struct iovec iov;
4731da177e4SLinus Torvalds 
4741da177e4SLinus Torvalds 	msg.msg_name = NULL;
4751da177e4SLinus Torvalds 	msg.msg_namelen = 0;
4761da177e4SLinus Torvalds 	iov = ((struct iovec) { .iov_base  = helper_pid_out,
4771da177e4SLinus Torvalds 				.iov_len   = sizeof(*helper_pid_out) });
4781da177e4SLinus Torvalds 	msg.msg_iov = &iov;
4791da177e4SLinus Torvalds 	msg.msg_iovlen = 1;
4801da177e4SLinus Torvalds 	msg.msg_control = buf;
4811da177e4SLinus Torvalds 	msg.msg_controllen = sizeof(buf);
4821da177e4SLinus Torvalds 	msg.msg_flags = 0;
4831da177e4SLinus Torvalds 
4841da177e4SLinus Torvalds 	n = recvmsg(fd, &msg, 0);
4851da177e4SLinus Torvalds 	if (n < 0)
486108ffa8cSJeff Dike 		return -errno;
487d4d5d205SJeff Dike 	else if (n != iov.iov_len)
4881da177e4SLinus Torvalds 		*helper_pid_out = -1;
4891da177e4SLinus Torvalds 
4901da177e4SLinus Torvalds 	cmsg = CMSG_FIRSTHDR(&msg);
4911da177e4SLinus Torvalds 	if (cmsg == NULL) {
4921adfd609SJeff Dike 		printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
4931adfd609SJeff Dike 		       "error = %d\n", errno);
494108ffa8cSJeff Dike 		return -1;
4951da177e4SLinus Torvalds 	}
4961da177e4SLinus Torvalds 	if ((cmsg->cmsg_level != SOL_SOCKET) ||
4971da177e4SLinus Torvalds 	    (cmsg->cmsg_type != SCM_RIGHTS)) {
4981adfd609SJeff Dike 		printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
499108ffa8cSJeff Dike 		return -1;
5001da177e4SLinus Torvalds 	}
5011da177e4SLinus Torvalds 
5021da177e4SLinus Torvalds 	new = ((int *) CMSG_DATA(cmsg))[0];
503108ffa8cSJeff Dike 	return new;
5041da177e4SLinus Torvalds }
5051da177e4SLinus Torvalds 
506c9a3072dSWANG Cong int os_create_unix_socket(const char *file, int len, int close_on_exec)
5071da177e4SLinus Torvalds {
5081da177e4SLinus Torvalds 	struct sockaddr_un addr;
5091da177e4SLinus Torvalds 	int sock, err;
5101da177e4SLinus Torvalds 
5111da177e4SLinus Torvalds 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
512b4fd310eSJeff Dike 	if (sock < 0)
513b4fd310eSJeff Dike 		return -errno;
5141da177e4SLinus Torvalds 
5151da177e4SLinus Torvalds 	if (close_on_exec) {
516512b6fb1SJeff Dike 		err = os_set_exec_close(sock);
5171da177e4SLinus Torvalds 		if (err < 0)
5181adfd609SJeff Dike 			printk(UM_KERN_ERR "create_unix_socket : "
5191adfd609SJeff Dike 			       "close_on_exec failed, err = %d", -err);
5201da177e4SLinus Torvalds 	}
5211da177e4SLinus Torvalds 
5221da177e4SLinus Torvalds 	addr.sun_family = AF_UNIX;
5231da177e4SLinus Torvalds 
5241da177e4SLinus Torvalds 	snprintf(addr.sun_path, len, "%s", file);
5251da177e4SLinus Torvalds 
5261da177e4SLinus Torvalds 	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
527b4fd310eSJeff Dike 	if (err < 0)
528b4fd310eSJeff Dike 		return -errno;
5291da177e4SLinus Torvalds 
530108ffa8cSJeff Dike 	return sock;
5311da177e4SLinus Torvalds }
5321da177e4SLinus Torvalds 
5331da177e4SLinus Torvalds void os_flush_stdout(void)
5341da177e4SLinus Torvalds {
5351da177e4SLinus Torvalds 	fflush(stdout);
5361da177e4SLinus Torvalds }
5371da177e4SLinus Torvalds 
5381da177e4SLinus Torvalds int os_lock_file(int fd, int excl)
5391da177e4SLinus Torvalds {
5401da177e4SLinus Torvalds 	int type = excl ? F_WRLCK : F_RDLCK;
5411da177e4SLinus Torvalds 	struct flock lock = ((struct flock) { .l_type	= type,
5421da177e4SLinus Torvalds 					      .l_whence	= SEEK_SET,
5431da177e4SLinus Torvalds 					      .l_start	= 0,
5441da177e4SLinus Torvalds 					      .l_len	= 0 } );
5451da177e4SLinus Torvalds 	int err, save;
5461da177e4SLinus Torvalds 
5471da177e4SLinus Torvalds 	err = fcntl(fd, F_SETLK, &lock);
5481da177e4SLinus Torvalds 	if (!err)
5491da177e4SLinus Torvalds 		goto out;
5501da177e4SLinus Torvalds 
5511da177e4SLinus Torvalds 	save = -errno;
5521da177e4SLinus Torvalds 	err = fcntl(fd, F_GETLK, &lock);
5531da177e4SLinus Torvalds 	if (err) {
5541da177e4SLinus Torvalds 		err = -errno;
5551da177e4SLinus Torvalds 		goto out;
5561da177e4SLinus Torvalds 	}
5571da177e4SLinus Torvalds 
5581adfd609SJeff Dike 	printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
5591adfd609SJeff Dike 	       lock.l_pid);
5601da177e4SLinus Torvalds 	err = save;
5611da177e4SLinus Torvalds  out:
562108ffa8cSJeff Dike 	return err;
5631da177e4SLinus Torvalds }
564005a59ecSAl Viro 
565005a59ecSAl Viro unsigned os_major(unsigned long long dev)
566005a59ecSAl Viro {
567005a59ecSAl Viro 	return major(dev);
568005a59ecSAl Viro }
569005a59ecSAl Viro 
570005a59ecSAl Viro unsigned os_minor(unsigned long long dev)
571005a59ecSAl Viro {
572005a59ecSAl Viro 	return minor(dev);
573005a59ecSAl Viro }
574005a59ecSAl Viro 
575005a59ecSAl Viro unsigned long long os_makedev(unsigned major, unsigned minor)
576005a59ecSAl Viro {
577005a59ecSAl Viro 	return makedev(major, minor);
578005a59ecSAl Viro }
579