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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.