• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4   */
5  
6  #include <stdio.h>
7  #include <unistd.h>
8  #include <stdlib.h>
9  #include <string.h>
10  #include <errno.h>
11  #include <fcntl.h>
12  #include <signal.h>
13  #include <linux/falloc.h>
14  #include <sys/ioctl.h>
15  #include <sys/mount.h>
16  #include <sys/socket.h>
17  #include <sys/stat.h>
18  #include <sys/sysmacros.h>
19  #include <sys/un.h>
20  #include <sys/types.h>
21  #include <sys/eventfd.h>
22  #include <poll.h>
23  #include <os.h>
24  
copy_stat(struct uml_stat * dst,const struct stat64 * src)25  static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
26  {
27  	*dst = ((struct uml_stat) {
28  		.ust_dev     = src->st_dev,     /* device */
29  		.ust_ino     = src->st_ino,     /* inode */
30  		.ust_mode    = src->st_mode,    /* protection */
31  		.ust_nlink   = src->st_nlink,   /* number of hard links */
32  		.ust_uid     = src->st_uid,     /* user ID of owner */
33  		.ust_gid     = src->st_gid,     /* group ID of owner */
34  		.ust_size    = src->st_size,    /* total size, in bytes */
35  		.ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
36  		.ust_blocks  = src->st_blocks,  /* number of blocks allocated */
37  		.ust_atime   = src->st_atime,   /* time of last access */
38  		.ust_mtime   = src->st_mtime,   /* time of last modification */
39  		.ust_ctime   = src->st_ctime,   /* time of last change */
40  	});
41  }
42  
os_stat_fd(const int fd,struct uml_stat * ubuf)43  int os_stat_fd(const int fd, struct uml_stat *ubuf)
44  {
45  	struct stat64 sbuf;
46  	int err;
47  
48  	CATCH_EINTR(err = fstat64(fd, &sbuf));
49  	if (err < 0)
50  		return -errno;
51  
52  	if (ubuf != NULL)
53  		copy_stat(ubuf, &sbuf);
54  	return err;
55  }
56  
os_stat_file(const char * file_name,struct uml_stat * ubuf)57  int os_stat_file(const char *file_name, struct uml_stat *ubuf)
58  {
59  	struct stat64 sbuf;
60  	int err;
61  
62  	CATCH_EINTR(err = stat64(file_name, &sbuf));
63  	if (err < 0)
64  		return -errno;
65  
66  	if (ubuf != NULL)
67  		copy_stat(ubuf, &sbuf);
68  	return err;
69  }
70  
os_access(const char * file,int mode)71  int os_access(const char *file, int mode)
72  {
73  	int amode, err;
74  
75  	amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
76  		(mode & OS_ACC_W_OK ? W_OK : 0) |
77  		(mode & OS_ACC_X_OK ? X_OK : 0) |
78  		(mode & OS_ACC_F_OK ? F_OK : 0);
79  
80  	err = access(file, amode);
81  	if (err < 0)
82  		return -errno;
83  
84  	return 0;
85  }
86  
87  /* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
os_ioctl_generic(int fd,unsigned int cmd,unsigned long arg)88  int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
89  {
90  	int err;
91  
92  	err = ioctl(fd, cmd, arg);
93  	if (err < 0)
94  		return -errno;
95  
96  	return err;
97  }
98  
99  /* FIXME: ensure namebuf in os_get_if_name is big enough */
os_get_ifname(int fd,char * namebuf)100  int os_get_ifname(int fd, char* namebuf)
101  {
102  	if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
103  		return -errno;
104  
105  	return 0;
106  }
107  
os_set_slip(int fd)108  int os_set_slip(int fd)
109  {
110  	int disc, sencap;
111  
112  	disc = N_SLIP;
113  	if (ioctl(fd, TIOCSETD, &disc) < 0)
114  		return -errno;
115  
116  	sencap = 0;
117  	if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
118  		return -errno;
119  
120  	return 0;
121  }
122  
os_mode_fd(int fd,int mode)123  int os_mode_fd(int fd, int mode)
124  {
125  	int err;
126  
127  	CATCH_EINTR(err = fchmod(fd, mode));
128  	if (err < 0)
129  		return -errno;
130  
131  	return 0;
132  }
133  
os_file_type(char * file)134  int os_file_type(char *file)
135  {
136  	struct uml_stat buf;
137  	int err;
138  
139  	err = os_stat_file(file, &buf);
140  	if (err < 0)
141  		return err;
142  
143  	if (S_ISDIR(buf.ust_mode))
144  		return OS_TYPE_DIR;
145  	else if (S_ISLNK(buf.ust_mode))
146  		return OS_TYPE_SYMLINK;
147  	else if (S_ISCHR(buf.ust_mode))
148  		return OS_TYPE_CHARDEV;
149  	else if (S_ISBLK(buf.ust_mode))
150  		return OS_TYPE_BLOCKDEV;
151  	else if (S_ISFIFO(buf.ust_mode))
152  		return OS_TYPE_FIFO;
153  	else if (S_ISSOCK(buf.ust_mode))
154  		return OS_TYPE_SOCK;
155  	else return OS_TYPE_FILE;
156  }
157  
os_file_mode(const char * file,struct openflags * mode_out)158  int os_file_mode(const char *file, struct openflags *mode_out)
159  {
160  	int err;
161  
162  	*mode_out = OPENFLAGS();
163  
164  	err = access(file, W_OK);
165  	if (err && (errno != EACCES))
166  		return -errno;
167  	else if (!err)
168  		*mode_out = of_write(*mode_out);
169  
170  	err = access(file, R_OK);
171  	if (err && (errno != EACCES))
172  		return -errno;
173  	else if (!err)
174  		*mode_out = of_read(*mode_out);
175  
176  	return err;
177  }
178  
os_open_file(const char * file,struct openflags flags,int mode)179  int os_open_file(const char *file, struct openflags flags, int mode)
180  {
181  	int fd, err, f = 0;
182  
183  	if (flags.r && flags.w)
184  		f = O_RDWR;
185  	else if (flags.r)
186  		f = O_RDONLY;
187  	else if (flags.w)
188  		f = O_WRONLY;
189  	else f = 0;
190  
191  	if (flags.s)
192  		f |= O_SYNC;
193  	if (flags.c)
194  		f |= O_CREAT;
195  	if (flags.t)
196  		f |= O_TRUNC;
197  	if (flags.e)
198  		f |= O_EXCL;
199  	if (flags.a)
200  		f |= O_APPEND;
201  
202  	fd = open64(file, f, mode);
203  	if (fd < 0)
204  		return -errno;
205  
206  	if (flags.cl && fcntl(fd, F_SETFD, 1)) {
207  		err = -errno;
208  		close(fd);
209  		return err;
210  	}
211  
212  	return fd;
213  }
214  
os_connect_socket(const char * name)215  int os_connect_socket(const char *name)
216  {
217  	struct sockaddr_un sock;
218  	int fd, err;
219  
220  	sock.sun_family = AF_UNIX;
221  	snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
222  
223  	fd = socket(AF_UNIX, SOCK_STREAM, 0);
224  	if (fd < 0) {
225  		err = -errno;
226  		goto out;
227  	}
228  
229  	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
230  	if (err) {
231  		err = -errno;
232  		goto out_close;
233  	}
234  
235  	return fd;
236  
237  out_close:
238  	close(fd);
239  out:
240  	return err;
241  }
242  
os_close_file(int fd)243  void os_close_file(int fd)
244  {
245  	close(fd);
246  }
os_fsync_file(int fd)247  int os_fsync_file(int fd)
248  {
249  	if (fsync(fd) < 0)
250  	    return -errno;
251  	return 0;
252  }
253  
os_seek_file(int fd,unsigned long long offset)254  int os_seek_file(int fd, unsigned long long offset)
255  {
256  	unsigned long long actual;
257  
258  	actual = lseek64(fd, offset, SEEK_SET);
259  	if (actual != offset)
260  		return -errno;
261  	return 0;
262  }
263  
os_read_file(int fd,void * buf,int len)264  int os_read_file(int fd, void *buf, int len)
265  {
266  	int n = read(fd, buf, len);
267  
268  	if (n < 0)
269  		return -errno;
270  	return n;
271  }
272  
os_pread_file(int fd,void * buf,int len,unsigned long long offset)273  int os_pread_file(int fd, void *buf, int len, unsigned long long offset)
274  {
275  	int n = pread(fd, buf, len, offset);
276  
277  	if (n < 0)
278  		return -errno;
279  	return n;
280  }
281  
os_write_file(int fd,const void * buf,int len)282  int os_write_file(int fd, const void *buf, int len)
283  {
284  	int n = write(fd, (void *) buf, len);
285  
286  	if (n < 0)
287  		return -errno;
288  	return n;
289  }
290  
os_sync_file(int fd)291  int os_sync_file(int fd)
292  {
293  	int n = fdatasync(fd);
294  
295  	if (n < 0)
296  		return -errno;
297  	return n;
298  }
299  
os_pwrite_file(int fd,const void * buf,int len,unsigned long long offset)300  int os_pwrite_file(int fd, const void *buf, int len, unsigned long long offset)
301  {
302  	int n = pwrite(fd, (void *) buf, len, offset);
303  
304  	if (n < 0)
305  		return -errno;
306  	return n;
307  }
308  
309  
os_file_size(const char * file,unsigned long long * size_out)310  int os_file_size(const char *file, unsigned long long *size_out)
311  {
312  	struct uml_stat buf;
313  	int err;
314  
315  	err = os_stat_file(file, &buf);
316  	if (err < 0) {
317  		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
318  		       -err);
319  		return err;
320  	}
321  
322  	if (S_ISBLK(buf.ust_mode)) {
323  		int fd;
324  		long blocks;
325  
326  		fd = open(file, O_RDONLY, 0);
327  		if (fd < 0) {
328  			err = -errno;
329  			printk(UM_KERN_ERR "Couldn't open \"%s\", "
330  			       "errno = %d\n", file, errno);
331  			return err;
332  		}
333  		if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
334  			err = -errno;
335  			printk(UM_KERN_ERR "Couldn't get the block size of "
336  			       "\"%s\", errno = %d\n", file, errno);
337  			close(fd);
338  			return err;
339  		}
340  		*size_out = ((long long) blocks) * 512;
341  		close(fd);
342  	}
343  	else *size_out = buf.ust_size;
344  
345  	return 0;
346  }
347  
os_file_modtime(const char * file,long long * modtime)348  int os_file_modtime(const char *file, long long *modtime)
349  {
350  	struct uml_stat buf;
351  	int err;
352  
353  	err = os_stat_file(file, &buf);
354  	if (err < 0) {
355  		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
356  		       -err);
357  		return err;
358  	}
359  
360  	*modtime = buf.ust_mtime;
361  	return 0;
362  }
363  
os_set_exec_close(int fd)364  int os_set_exec_close(int fd)
365  {
366  	int err;
367  
368  	CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
369  
370  	if (err < 0)
371  		return -errno;
372  	return err;
373  }
374  
os_pipe(int * fds,int stream,int close_on_exec)375  int os_pipe(int *fds, int stream, int close_on_exec)
376  {
377  	int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
378  
379  	err = socketpair(AF_UNIX, type, 0, fds);
380  	if (err < 0)
381  		return -errno;
382  
383  	if (!close_on_exec)
384  		return 0;
385  
386  	err = os_set_exec_close(fds[0]);
387  	if (err < 0)
388  		goto error;
389  
390  	err = os_set_exec_close(fds[1]);
391  	if (err < 0)
392  		goto error;
393  
394  	return 0;
395  
396   error:
397  	printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
398  	       -err);
399  	close(fds[1]);
400  	close(fds[0]);
401  	return err;
402  }
403  
os_set_fd_async(int fd)404  int os_set_fd_async(int fd)
405  {
406  	int err, flags;
407  
408  	flags = fcntl(fd, F_GETFL);
409  	if (flags < 0)
410  		return -errno;
411  
412  	flags |= O_ASYNC | O_NONBLOCK;
413  	if (fcntl(fd, F_SETFL, flags) < 0) {
414  		err = -errno;
415  		printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
416  		       "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
417  		return err;
418  	}
419  
420  	if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
421  	    (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
422  		err = -errno;
423  		printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
424  		       "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
425  		return err;
426  	}
427  
428  	return 0;
429  }
430  
os_clear_fd_async(int fd)431  int os_clear_fd_async(int fd)
432  {
433  	int flags;
434  
435  	flags = fcntl(fd, F_GETFL);
436  	if (flags < 0)
437  		return -errno;
438  
439  	flags &= ~(O_ASYNC | O_NONBLOCK);
440  	if (fcntl(fd, F_SETFL, flags) < 0)
441  		return -errno;
442  	return 0;
443  }
444  
os_set_fd_block(int fd,int blocking)445  int os_set_fd_block(int fd, int blocking)
446  {
447  	int flags;
448  
449  	flags = fcntl(fd, F_GETFL);
450  	if (flags < 0)
451  		return -errno;
452  
453  	if (blocking)
454  		flags &= ~O_NONBLOCK;
455  	else
456  		flags |= O_NONBLOCK;
457  
458  	if (fcntl(fd, F_SETFL, flags) < 0)
459  		return -errno;
460  
461  	return 0;
462  }
463  
os_accept_connection(int fd)464  int os_accept_connection(int fd)
465  {
466  	int new;
467  
468  	new = accept(fd, NULL, 0);
469  	if (new < 0)
470  		return -errno;
471  	return new;
472  }
473  
474  #ifndef SHUT_RD
475  #define SHUT_RD 0
476  #endif
477  
478  #ifndef SHUT_WR
479  #define SHUT_WR 1
480  #endif
481  
482  #ifndef SHUT_RDWR
483  #define SHUT_RDWR 2
484  #endif
485  
os_shutdown_socket(int fd,int r,int w)486  int os_shutdown_socket(int fd, int r, int w)
487  {
488  	int what, err;
489  
490  	if (r && w)
491  		what = SHUT_RDWR;
492  	else if (r)
493  		what = SHUT_RD;
494  	else if (w)
495  		what = SHUT_WR;
496  	else
497  		return -EINVAL;
498  
499  	err = shutdown(fd, what);
500  	if (err < 0)
501  		return -errno;
502  	return 0;
503  }
504  
os_rcv_fd(int fd,int * helper_pid_out)505  int os_rcv_fd(int fd, int *helper_pid_out)
506  {
507  	int new, n;
508  	char buf[CMSG_SPACE(sizeof(new))];
509  	struct msghdr msg;
510  	struct cmsghdr *cmsg;
511  	struct iovec iov;
512  
513  	msg.msg_name = NULL;
514  	msg.msg_namelen = 0;
515  	iov = ((struct iovec) { .iov_base  = helper_pid_out,
516  				.iov_len   = sizeof(*helper_pid_out) });
517  	msg.msg_iov = &iov;
518  	msg.msg_iovlen = 1;
519  	msg.msg_control = buf;
520  	msg.msg_controllen = sizeof(buf);
521  	msg.msg_flags = 0;
522  
523  	n = recvmsg(fd, &msg, 0);
524  	if (n < 0)
525  		return -errno;
526  	else if (n != iov.iov_len)
527  		*helper_pid_out = -1;
528  
529  	cmsg = CMSG_FIRSTHDR(&msg);
530  	if (cmsg == NULL) {
531  		printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
532  		       "error = %d\n", errno);
533  		return -1;
534  	}
535  	if ((cmsg->cmsg_level != SOL_SOCKET) ||
536  	    (cmsg->cmsg_type != SCM_RIGHTS)) {
537  		printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
538  		return -1;
539  	}
540  
541  	new = ((int *) CMSG_DATA(cmsg))[0];
542  	return new;
543  }
544  
os_create_unix_socket(const char * file,int len,int close_on_exec)545  int os_create_unix_socket(const char *file, int len, int close_on_exec)
546  {
547  	struct sockaddr_un addr;
548  	int sock, err;
549  
550  	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
551  	if (sock < 0)
552  		return -errno;
553  
554  	if (close_on_exec) {
555  		err = os_set_exec_close(sock);
556  		if (err < 0)
557  			printk(UM_KERN_ERR "create_unix_socket : "
558  			       "close_on_exec failed, err = %d", -err);
559  	}
560  
561  	addr.sun_family = AF_UNIX;
562  
563  	snprintf(addr.sun_path, len, "%s", file);
564  
565  	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
566  	if (err < 0)
567  		return -errno;
568  
569  	return sock;
570  }
571  
os_flush_stdout(void)572  void os_flush_stdout(void)
573  {
574  	fflush(stdout);
575  }
576  
os_lock_file(int fd,int excl)577  int os_lock_file(int fd, int excl)
578  {
579  	int type = excl ? F_WRLCK : F_RDLCK;
580  	struct flock lock = ((struct flock) { .l_type	= type,
581  					      .l_whence	= SEEK_SET,
582  					      .l_start	= 0,
583  					      .l_len	= 0 } );
584  	int err, save;
585  
586  	err = fcntl(fd, F_SETLK, &lock);
587  	if (!err)
588  		goto out;
589  
590  	save = -errno;
591  	err = fcntl(fd, F_GETLK, &lock);
592  	if (err) {
593  		err = -errno;
594  		goto out;
595  	}
596  
597  	printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
598  	       lock.l_pid);
599  	err = save;
600   out:
601  	return err;
602  }
603  
os_major(unsigned long long dev)604  unsigned os_major(unsigned long long dev)
605  {
606  	return major(dev);
607  }
608  
os_minor(unsigned long long dev)609  unsigned os_minor(unsigned long long dev)
610  {
611  	return minor(dev);
612  }
613  
os_makedev(unsigned major,unsigned minor)614  unsigned long long os_makedev(unsigned major, unsigned minor)
615  {
616  	return makedev(major, minor);
617  }
618  
os_falloc_punch(int fd,unsigned long long offset,int len)619  int os_falloc_punch(int fd, unsigned long long offset, int len)
620  {
621  	int n = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, len);
622  
623  	if (n < 0)
624  		return -errno;
625  	return n;
626  }
627  
os_eventfd(unsigned int initval,int flags)628  int os_eventfd(unsigned int initval, int flags)
629  {
630  	int fd = eventfd(initval, flags);
631  
632  	if (fd < 0)
633  		return -errno;
634  	return fd;
635  }
636  
os_sendmsg_fds(int fd,const void * buf,unsigned int len,const int * fds,unsigned int fds_num)637  int os_sendmsg_fds(int fd, const void *buf, unsigned int len, const int *fds,
638  		   unsigned int fds_num)
639  {
640  	struct iovec iov = {
641  		.iov_base = (void *) buf,
642  		.iov_len = len,
643  	};
644  	union {
645  		char control[CMSG_SPACE(sizeof(*fds) * OS_SENDMSG_MAX_FDS)];
646  		struct cmsghdr align;
647  	} u;
648  	unsigned int fds_size = sizeof(*fds) * fds_num;
649  	struct msghdr msg = {
650  		.msg_iov = &iov,
651  		.msg_iovlen = 1,
652  		.msg_control = u.control,
653  		.msg_controllen = CMSG_SPACE(fds_size),
654  	};
655  	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
656  	int err;
657  
658  	if (fds_num > OS_SENDMSG_MAX_FDS)
659  		return -EINVAL;
660  	memset(u.control, 0, sizeof(u.control));
661  	cmsg->cmsg_level = SOL_SOCKET;
662  	cmsg->cmsg_type = SCM_RIGHTS;
663  	cmsg->cmsg_len = CMSG_LEN(fds_size);
664  	memcpy(CMSG_DATA(cmsg), fds, fds_size);
665  	err = sendmsg(fd, &msg, 0);
666  
667  	if (err < 0)
668  		return -errno;
669  	return err;
670  }
671  
os_poll(unsigned int n,const int * fds)672  int os_poll(unsigned int n, const int *fds)
673  {
674  	/* currently need 2 FDs at most so avoid dynamic allocation */
675  	struct pollfd pollfds[2] = {};
676  	unsigned int i;
677  	int ret;
678  
679  	if (n > ARRAY_SIZE(pollfds))
680  		return -EINVAL;
681  
682  	for (i = 0; i < n; i++) {
683  		pollfds[i].fd = fds[i];
684  		pollfds[i].events = POLLIN;
685  	}
686  
687  	ret = poll(pollfds, n, -1);
688  	if (ret < 0)
689  		return -errno;
690  
691  	/* Return the index of the available FD */
692  	for (i = 0; i < n; i++) {
693  		if (pollfds[i].revents)
694  			return i;
695  	}
696  
697  	return -EIO;
698  }
699