gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/images/basic/integrationtest/host_fd.c (about) 1 // Copyright 2021 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <err.h> 16 #include <errno.h> 17 #include <getopt.h> 18 #include <stddef.h> 19 #include <stdio.h> 20 #include <sys/epoll.h> 21 #include <sys/ioctl.h> 22 #include <sys/select.h> 23 #include <unistd.h> 24 25 // Flag to indicate that TTY is being used in the container. 26 static int tty = 0; 27 28 // Tests that FIONREAD is supported with host FD. 29 void testFionread() { 30 int size = 0; 31 if (ioctl(STDOUT_FILENO, FIONREAD, &size) < 0) { 32 err(1, "ioctl(stdin, FIONREAD)"); 33 } 34 if (size != 0) { 35 err(1, "FIONREAD wrong size, want: 0, got: %d", size); 36 } 37 } 38 39 // Docker maps stdin to /dev/null which doesn't support epoll. Check that error 40 // is correctly propagated. 41 void testEpoll() { 42 if (tty) { 43 // stdin is not /dev/null when TTY is used for the container. 44 return; 45 } 46 int fd = epoll_create(1); 47 if (fd < 0) { 48 err(1, "epoll_create"); 49 } 50 51 struct epoll_event event; 52 event.events = EPOLLIN; 53 event.data.u64 = 123; 54 int res = epoll_ctl(fd, EPOLL_CTL_ADD, 0, &event); 55 if (res != -1) { 56 err(1, "epoll_ctl(EPOLL_CTL_ADD, stdin) should have failed"); 57 } 58 if (errno != EPERM) { 59 err(1, "epoll_ctl(EPOLL_CTL_ADD, stdin) should have returned EPERM"); 60 } 61 } 62 63 // Docker maps stdin to /dev/null. Check that select(2) works with stdin. 64 void testSelect() { 65 fd_set rfds; 66 struct timeval tv; 67 int res; 68 FD_ZERO(&rfds); 69 FD_SET(0, &rfds); 70 tv.tv_sec = 0; 71 tv.tv_usec = 1; 72 res = select(1, &rfds, NULL, NULL, &tv); 73 if (res == -1) { 74 err(1, "select(1, [STDIN], NULL, NULL) returned error"); 75 } 76 } 77 78 int main(int argc, char** argv) { 79 int opt; 80 while ((opt = getopt(argc, argv, "t")) != -1) { 81 switch (opt) { 82 case 't': 83 tty = 1; 84 break; 85 default: 86 fprintf(stderr, "Usage: %s [-t]\n", argv[0]); 87 return 1; 88 } 89 } 90 91 testFionread(); 92 testEpoll(); 93 testSelect(); 94 return 0; 95 }