File Index
Files and directories
Sign in
FILE

file.c

File preview with syntax highlighting.

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