mirror of git://sourceware.org/git/glibc.git
				
				
				
			
		
			
				
	
	
		
			144 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
| /* Smoke test for the closefrom.
 | |
|    Copyright (C) 2021-2025 Free Software Foundation, Inc.
 | |
|    This file is part of the GNU C Library.
 | |
| 
 | |
|    The GNU C Library is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU Lesser General Public
 | |
|    License as published by the Free Software Foundation; either
 | |
|    version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|    The GNU C Library is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|    Lesser General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU Lesser General Public
 | |
|    License along with the GNU C Library; if not, see
 | |
|    <https://www.gnu.org/licenses/>.  */
 | |
| 
 | |
| #include <errno.h>
 | |
| #include <fcntl.h>
 | |
| #include <sys/resource.h>
 | |
| #include <unistd.h>
 | |
| 
 | |
| #include <support/check.h>
 | |
| #include <support/descriptors.h>
 | |
| #include <support/xunistd.h>
 | |
| #include <support/support.h>
 | |
| 
 | |
| #include <array_length.h>
 | |
| 
 | |
| #define NFDS 100
 | |
| 
 | |
| static int
 | |
| closefrom_test (void)
 | |
| {
 | |
|   struct support_descriptors *descrs = support_descriptors_list ();
 | |
| 
 | |
|   int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
 | |
| 
 | |
|   const int maximum_fd = lowfd + NFDS - 1;
 | |
|   const int half_fd = lowfd + NFDS / 2;
 | |
|   const int gap = lowfd + NFDS / 4;
 | |
| 
 | |
|   /* Close half of the descriptors and check result.  */
 | |
|   closefrom (half_fd);
 | |
| 
 | |
|   for (int i = half_fd; i <= maximum_fd; i++)
 | |
|     {
 | |
|       TEST_COMPARE (fcntl (i, F_GETFL), -1);
 | |
|       TEST_COMPARE (errno, EBADF);
 | |
|     }
 | |
|   for (int i = lowfd; i < half_fd; i++)
 | |
|     TEST_VERIFY (fcntl (i, F_GETFL) > -1);
 | |
| 
 | |
|   /* Create some gaps, close up to a threshold, and check result.  */
 | |
|   xclose (lowfd + 35);
 | |
|   xclose (lowfd + 38);
 | |
|   xclose (lowfd + 42);
 | |
|   xclose (lowfd + 46);
 | |
| 
 | |
|   /* Close half of the descriptors and check result.  */
 | |
|   closefrom (gap);
 | |
|   for (int i = gap + 1; i < maximum_fd; i++)
 | |
|     {
 | |
|       TEST_COMPARE (fcntl (i, F_GETFL), -1);
 | |
|       TEST_COMPARE (errno, EBADF);
 | |
|     }
 | |
|   for (int i = lowfd; i < gap; i++)
 | |
|     TEST_VERIFY (fcntl (i, F_GETFL) > -1);
 | |
| 
 | |
|   /* Close the remmaining but the last one.  */
 | |
|   closefrom (lowfd + 1);
 | |
|   for (int i = lowfd + 1; i <= maximum_fd; i++)
 | |
|     {
 | |
|       TEST_COMPARE (fcntl (i, F_GETFL), -1);
 | |
|       TEST_COMPARE (errno, EBADF);
 | |
|     }
 | |
|   TEST_VERIFY (fcntl (lowfd, F_GETFL) > -1);
 | |
| 
 | |
|   /* Close the last one.  */
 | |
|   closefrom (lowfd);
 | |
|   TEST_COMPARE (fcntl (lowfd, F_GETFL), -1);
 | |
|   TEST_COMPARE (errno, EBADF);
 | |
| 
 | |
|   /* Double check by check the /proc.  */
 | |
|   support_descriptors_check (descrs);
 | |
|   support_descriptors_free (descrs);
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /* Check if closefrom works even when no new file descriptors can be
 | |
|    created.  */
 | |
| static int
 | |
| closefrom_test_file_desc_limit (void)
 | |
| {
 | |
|   int max_fd = NFDS;
 | |
|   {
 | |
|     struct rlimit rl;
 | |
|     if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
 | |
|       FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
 | |
| 
 | |
|     max_fd = (rl.rlim_cur < max_fd ? rl.rlim_cur : max_fd);
 | |
|     rl.rlim_cur = max_fd;
 | |
| 
 | |
|     if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
 | |
|       FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
 | |
|   }
 | |
| 
 | |
|   /* Exhauste the file descriptor limit.  */
 | |
|   int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
 | |
|   for (;;)
 | |
|     {
 | |
|       int fd = open ("/dev/null", O_RDONLY, 0600);
 | |
|       if (fd == -1)
 | |
| 	{
 | |
| 	  if (errno != EMFILE)
 | |
| 	    FAIL_EXIT1 ("open: %m");
 | |
| 	  break;
 | |
| 	}
 | |
|       TEST_VERIFY_EXIT (fd < max_fd);
 | |
|     }
 | |
| 
 | |
|   closefrom (lowfd);
 | |
|   for (int i = lowfd; i < NFDS; i++)
 | |
|     {
 | |
|       TEST_COMPARE (fcntl (i, F_GETFL), -1);
 | |
|       TEST_COMPARE (errno, EBADF);
 | |
|     }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static int
 | |
| do_test (void)
 | |
| {
 | |
|   closefrom_test ();
 | |
|   closefrom_test_file_desc_limit ();
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| #include <support/test-driver.c>
 |