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