~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/um/os-Linux/file.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 int os_fsync_file(int fd)
259 {
260         if (fsync(fd) < 0)
261             return -errno;
262         return 0;
263 }
264 
265 int os_seek_file(int fd, unsigned long long offset)
266 {
267         unsigned long long actual;
268 
269         actual = lseek64(fd, offset, SEEK_SET);
270         if (actual != offset)
271                 return -errno;
272         return 0;
273 }
274 
275 int os_read_file(int fd, void *buf, int len)
276 {
277         int n = read(fd, buf, len);
278 
279         if (n < 0)
280                 return -errno;
281         return n;
282 }
283 
284 int os_pread_file(int fd, void *buf, int len, unsigned long long offset)
285 {
286         int n = pread(fd, buf, len, offset);
287 
288         if (n < 0)
289                 return -errno;
290         return n;
291 }
292 
293 int os_write_file(int fd, const void *buf, int len)
294 {
295         int n = write(fd, (void *) buf, len);
296 
297         if (n < 0)
298                 return -errno;
299         return n;
300 }
301 
302 int os_sync_file(int fd)
303 {
304         int n = fdatasync(fd);
305 
306         if (n < 0)
307                 return -errno;
308         return n;
309 }
310 
311 int os_pwrite_file(int fd, const void *buf, int len, unsigned long long offset)
312 {
313         int n = pwrite(fd, (void *) buf, len, offset);
314 
315         if (n < 0)
316                 return -errno;
317         return n;
318 }
319 
320 
321 int os_file_size(const char *file, unsigned long long *size_out)
322 {
323         struct uml_stat buf;
324         int err;
325 
326         err = os_stat_file(file, &buf);
327         if (err < 0) {
328                 printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
329                        -err);
330                 return err;
331         }
332 
333         if (S_ISBLK(buf.ust_mode)) {
334                 int fd;
335                 long blocks;
336 
337                 fd = open(file, O_RDONLY, 0);
338                 if (fd < 0) {
339                         err = -errno;
340                         printk(UM_KERN_ERR "Couldn't open \"%s\", "
341                                "errno = %d\n", file, errno);
342                         return err;
343                 }
344                 if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
345                         err = -errno;
346                         printk(UM_KERN_ERR "Couldn't get the block size of "
347                                "\"%s\", errno = %d\n", file, errno);
348                         close(fd);
349                         return err;
350                 }
351                 *size_out = ((long long) blocks) * 512;
352                 close(fd);
353         }
354         else *size_out = buf.ust_size;
355 
356         return 0;
357 }
358 
359 int os_file_modtime(const char *file, long long *modtime)
360 {
361         struct uml_stat buf;
362         int err;
363 
364         err = os_stat_file(file, &buf);
365         if (err < 0) {
366                 printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
367                        -err);
368                 return err;
369         }
370 
371         *modtime = buf.ust_mtime;
372         return 0;
373 }
374 
375 int os_set_exec_close(int fd)
376 {
377         int err;
378 
379         CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
380 
381         if (err < 0)
382                 return -errno;
383         return err;
384 }
385 
386 int os_pipe(int *fds, int stream, int close_on_exec)
387 {
388         int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
389 
390         err = socketpair(AF_UNIX, type, 0, fds);
391         if (err < 0)
392                 return -errno;
393 
394         if (!close_on_exec)
395                 return 0;
396 
397         err = os_set_exec_close(fds[0]);
398         if (err < 0)
399                 goto error;
400 
401         err = os_set_exec_close(fds[1]);
402         if (err < 0)
403                 goto error;
404 
405         return 0;
406 
407  error:
408         printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
409                -err);
410         close(fds[1]);
411         close(fds[0]);
412         return err;
413 }
414 
415 int os_set_fd_async(int fd)
416 {
417         int err, flags;
418 
419         flags = fcntl(fd, F_GETFL);
420         if (flags < 0)
421                 return -errno;
422 
423         flags |= O_ASYNC | O_NONBLOCK;
424         if (fcntl(fd, F_SETFL, flags) < 0) {
425                 err = -errno;
426                 printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
427                        "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
428                 return err;
429         }
430 
431         if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
432             (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
433                 err = -errno;
434                 printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
435                        "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
436                 return err;
437         }
438 
439         return 0;
440 }
441 
442 int os_clear_fd_async(int fd)
443 {
444         int flags;
445 
446         flags = fcntl(fd, F_GETFL);
447         if (flags < 0)
448                 return -errno;
449 
450         flags &= ~(O_ASYNC | O_NONBLOCK);
451         if (fcntl(fd, F_SETFL, flags) < 0)
452                 return -errno;
453         return 0;
454 }
455 
456 int os_set_fd_block(int fd, int blocking)
457 {
458         int flags;
459 
460         flags = fcntl(fd, F_GETFL);
461         if (flags < 0)
462                 return -errno;
463 
464         if (blocking)
465                 flags &= ~O_NONBLOCK;
466         else
467                 flags |= O_NONBLOCK;
468 
469         if (fcntl(fd, F_SETFL, flags) < 0)
470                 return -errno;
471 
472         return 0;
473 }
474 
475 int os_accept_connection(int fd)
476 {
477         int new;
478 
479         new = accept(fd, NULL, 0);
480         if (new < 0)
481                 return -errno;
482         return new;
483 }
484 
485 #ifndef SHUT_RD
486 #define SHUT_RD 0
487 #endif
488 
489 #ifndef SHUT_WR
490 #define SHUT_WR 1
491 #endif
492 
493 #ifndef SHUT_RDWR
494 #define SHUT_RDWR 2
495 #endif
496 
497 int os_shutdown_socket(int fd, int r, int w)
498 {
499         int what, err;
500 
501         if (r && w)
502                 what = SHUT_RDWR;
503         else if (r)
504                 what = SHUT_RD;
505         else if (w)
506                 what = SHUT_WR;
507         else
508                 return -EINVAL;
509 
510         err = shutdown(fd, what);
511         if (err < 0)
512                 return -errno;
513         return 0;
514 }
515 
516 /**
517  * os_rcv_fd_msg - receive message with (optional) FDs
518  * @fd: the FD to receive from
519  * @fds: the array for FDs to write to
520  * @n_fds: number of FDs to receive (@fds array size)
521  * @data: the message buffer
522  * @data_len: the size of the message to receive
523  *
524  * Receive a message with FDs.
525  *
526  * Returns: the size of the received message, or an error code
527  */
528 ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds,
529                       void *data, size_t data_len)
530 {
531         char buf[CMSG_SPACE(sizeof(*fds) * n_fds)];
532         struct cmsghdr *cmsg;
533         struct iovec iov = {
534                 .iov_base = data,
535                 .iov_len = data_len,
536         };
537         struct msghdr msg = {
538                 .msg_iov = &iov,
539                 .msg_iovlen = 1,
540                 .msg_control = buf,
541                 .msg_controllen = sizeof(buf),
542         };
543         int n;
544 
545         n = recvmsg(fd, &msg, 0);
546         if (n < 0)
547                 return -errno;
548 
549         cmsg = CMSG_FIRSTHDR(&msg);
550         if (!cmsg ||
551             cmsg->cmsg_level != SOL_SOCKET ||
552             cmsg->cmsg_type != SCM_RIGHTS)
553                 return n;
554 
555         memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len);
556         return n;
557 }
558 
559 int os_create_unix_socket(const char *file, int len, int close_on_exec)
560 {
561         struct sockaddr_un addr;
562         int sock, err;
563 
564         sock = socket(PF_UNIX, SOCK_DGRAM, 0);
565         if (sock < 0)
566                 return -errno;
567 
568         if (close_on_exec) {
569                 err = os_set_exec_close(sock);
570                 if (err < 0)
571                         printk(UM_KERN_ERR "create_unix_socket : "
572                                "close_on_exec failed, err = %d", -err);
573         }
574 
575         addr.sun_family = AF_UNIX;
576 
577         snprintf(addr.sun_path, len, "%s", file);
578 
579         err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
580         if (err < 0)
581                 return -errno;
582 
583         return sock;
584 }
585 
586 void os_flush_stdout(void)
587 {
588         fflush(stdout);
589 }
590 
591 int os_lock_file(int fd, int excl)
592 {
593         int type = excl ? F_WRLCK : F_RDLCK;
594         struct flock lock = ((struct flock) { .l_type   = type,
595                                               .l_whence = SEEK_SET,
596                                               .l_start  = 0,
597                                               .l_len    = 0 } );
598         int err, save;
599 
600         err = fcntl(fd, F_SETLK, &lock);
601         if (!err)
602                 goto out;
603 
604         save = -errno;
605         err = fcntl(fd, F_GETLK, &lock);
606         if (err) {
607                 err = -errno;
608                 goto out;
609         }
610 
611         printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
612                lock.l_pid);
613         err = save;
614  out:
615         return err;
616 }
617 
618 unsigned os_major(unsigned long long dev)
619 {
620         return major(dev);
621 }
622 
623 unsigned os_minor(unsigned long long dev)
624 {
625         return minor(dev);
626 }
627 
628 unsigned long long os_makedev(unsigned major, unsigned minor)
629 {
630         return makedev(major, minor);
631 }
632 
633 int os_falloc_punch(int fd, unsigned long long offset, int len)
634 {
635         int n = fallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, offset, len);
636 
637         if (n < 0)
638                 return -errno;
639         return n;
640 }
641 
642 int os_falloc_zeroes(int fd, unsigned long long offset, int len)
643 {
644         int n = fallocate(fd, FALLOC_FL_ZERO_RANGE|FALLOC_FL_KEEP_SIZE, offset, len);
645 
646         if (n < 0)
647                 return -errno;
648         return n;
649 }
650 
651 int os_eventfd(unsigned int initval, int flags)
652 {
653         int fd = eventfd(initval, flags);
654 
655         if (fd < 0)
656                 return -errno;
657         return fd;
658 }
659 
660 int os_sendmsg_fds(int fd, const void *buf, unsigned int len, const int *fds,
661                    unsigned int fds_num)
662 {
663         struct iovec iov = {
664                 .iov_base = (void *) buf,
665                 .iov_len = len,
666         };
667         union {
668                 char control[CMSG_SPACE(sizeof(*fds) * OS_SENDMSG_MAX_FDS)];
669                 struct cmsghdr align;
670         } u;
671         unsigned int fds_size = sizeof(*fds) * fds_num;
672         struct msghdr msg = {
673                 .msg_iov = &iov,
674                 .msg_iovlen = 1,
675                 .msg_control = u.control,
676                 .msg_controllen = CMSG_SPACE(fds_size),
677         };
678         struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
679         int err;
680 
681         if (fds_num > OS_SENDMSG_MAX_FDS)
682                 return -EINVAL;
683         memset(u.control, 0, sizeof(u.control));
684         cmsg->cmsg_level = SOL_SOCKET;
685         cmsg->cmsg_type = SCM_RIGHTS;
686         cmsg->cmsg_len = CMSG_LEN(fds_size);
687         memcpy(CMSG_DATA(cmsg), fds, fds_size);
688         err = sendmsg(fd, &msg, 0);
689 
690         if (err < 0)
691                 return -errno;
692         return err;
693 }
694 
695 int os_poll(unsigned int n, const int *fds)
696 {
697         /* currently need 2 FDs at most so avoid dynamic allocation */
698         struct pollfd pollfds[2] = {};
699         unsigned int i;
700         int ret;
701 
702         if (n > ARRAY_SIZE(pollfds))
703                 return -EINVAL;
704 
705         for (i = 0; i < n; i++) {
706                 pollfds[i].fd = fds[i];
707                 pollfds[i].events = POLLIN;
708         }
709 
710         ret = poll(pollfds, n, -1);
711         if (ret < 0)
712                 return -errno;
713 
714         /* Return the index of the available FD */
715         for (i = 0; i < n; i++) {
716                 if (pollfds[i].revents)
717                         return i;
718         }
719 
720         return -EIO;
721 }
722 
723 void *os_mmap_rw_shared(int fd, size_t size)
724 {
725         void *res = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
726 
727         if (res == MAP_FAILED)
728                 return NULL;
729 
730         return res;
731 }
732 
733 void *os_mremap_rw_shared(void *old_addr, size_t old_size, size_t new_size)
734 {
735         void *res;
736 
737         res = mremap(old_addr, old_size, new_size, MREMAP_MAYMOVE, NULL);
738 
739         if (res == MAP_FAILED)
740                 return NULL;
741 
742         return res;
743 }
744 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php