| 1 | |
| 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,
|
| 30 | .ust_ino = src->st_ino,
|
| 31 | .ust_mode = src->st_mode,
|
| 32 | .ust_nlink = src->st_nlink,
|
| 33 | .ust_uid = src->st_uid,
|
| 34 | .ust_gid = src->st_gid,
|
| 35 | .ust_size = src->st_size,
|
| 36 | .ust_blksize = src->st_blksize,
|
| 37 | .ust_blocks = src->st_blocks,
|
| 38 | .ust_atime = src->st_atime,
|
| 39 | .ust_mtime = src->st_mtime,
|
| 40 | .ust_ctime = src->st_ctime,
|
| 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 |
|
| 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 |
|
| 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_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 |
|
| 120 | int 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 |
|
| 144 | int 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 |
|
| 165 | int 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 |
|
| 201 | int 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 |
|
| 223 | out_close:
|
| 224 | close(fd);
|
| 225 | out:
|
| 226 | return err;
|
| 227 | }
|
| 228 |
|
| 229 | int 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 |
|
| 239 | void os_close_file(int fd)
|
| 240 | {
|
| 241 | close(fd);
|
| 242 | }
|
| 243 |
|
| 244 | int 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 |
|
| 254 | int 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 |
|
| 263 | int 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 |
|
| 272 | int 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 |
|
| 281 | int os_sync_file(int fd)
|
| 282 | {
|
| 283 | int n = fdatasync(fd);
|
| 284 |
|
| 285 | if (n < 0)
|
| 286 | return -errno;
|
| 287 | return n;
|
| 288 | }
|
| 289 |
|
| 290 | int 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 |
|
| 300 | int 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 |
|
| 338 | int 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 |
|
| 354 | int 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 |
|
| 365 | int 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 |
|
| 394 | int 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 |
|
| 421 | int 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 |
|
| 435 | int 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 |
|
| 454 | int 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 |
|
| 476 | int 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 |
|
| 507 | ssize_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 |
|
| 542 | int 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 |
|
| 569 | void os_flush_stdout(void)
|
| 570 | {
|
| 571 | fflush(stdout);
|
| 572 | }
|
| 573 |
|
| 574 | int 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 |
|
| 601 | unsigned os_major(unsigned long long dev)
|
| 602 | {
|
| 603 | return major(dev);
|
| 604 | }
|
| 605 |
|
| 606 | unsigned os_minor(unsigned long long dev)
|
| 607 | {
|
| 608 | return minor(dev);
|
| 609 | }
|
| 610 |
|
| 611 | unsigned long long os_makedev(unsigned major, unsigned minor)
|
| 612 | {
|
| 613 | return makedev(major, minor);
|
| 614 | }
|
| 615 |
|
| 616 | int 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 |
|
| 625 | int 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 |
|
| 634 | int 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 |
|
| 643 | int 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 |
|
| 678 | int os_poll(unsigned int n, const int *fds)
|
| 679 | {
|
| 680 |
|
| 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 |
|
| 698 | for (i = 0; i < n; i++) {
|
| 699 | if (pollfds[i].revents)
|
| 700 | return i;
|
| 701 | }
|
| 702 |
|
| 703 | return -EIO;
|
| 704 | }
|
| 705 |
|
| 706 | void *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 |
|
| 716 | void *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 | }
|