LCOV - code coverage report
Current view: top level - test - test-fd-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 167 209 79.9 %
Date: 2019-08-23 13:36:53 Functions: 12 12 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75 208 36.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <fcntl.h>
       4                 :            : #include <unistd.h>
       5                 :            : 
       6                 :            : #include "alloc-util.h"
       7                 :            : #include "fd-util.h"
       8                 :            : #include "fileio.h"
       9                 :            : #include "macro.h"
      10                 :            : #include "memory-util.h"
      11                 :            : #include "path-util.h"
      12                 :            : #include "process-util.h"
      13                 :            : #include "random-util.h"
      14                 :            : #include "serialize.h"
      15                 :            : #include "string-util.h"
      16                 :            : #include "tests.h"
      17                 :            : #include "tmpfile-util.h"
      18                 :            : 
      19                 :          4 : static void test_close_many(void) {
      20                 :            :         int fds[3];
      21                 :          4 :         char name0[] = "/tmp/test-close-many.XXXXXX";
      22                 :          4 :         char name1[] = "/tmp/test-close-many.XXXXXX";
      23                 :          4 :         char name2[] = "/tmp/test-close-many.XXXXXX";
      24                 :            : 
      25                 :          4 :         fds[0] = mkostemp_safe(name0);
      26                 :          4 :         fds[1] = mkostemp_safe(name1);
      27                 :          4 :         fds[2] = mkostemp_safe(name2);
      28                 :            : 
      29                 :          4 :         close_many(fds, 2);
      30                 :            : 
      31         [ -  + ]:          4 :         assert_se(fcntl(fds[0], F_GETFD) == -1);
      32         [ -  + ]:          4 :         assert_se(fcntl(fds[1], F_GETFD) == -1);
      33         [ -  + ]:          4 :         assert_se(fcntl(fds[2], F_GETFD) >= 0);
      34                 :            : 
      35                 :          4 :         safe_close(fds[2]);
      36                 :            : 
      37                 :          4 :         unlink(name0);
      38                 :          4 :         unlink(name1);
      39                 :          4 :         unlink(name2);
      40                 :          4 : }
      41                 :            : 
      42                 :          4 : static void test_close_nointr(void) {
      43                 :          4 :         char name[] = "/tmp/test-test-close_nointr.XXXXXX";
      44                 :            :         int fd;
      45                 :            : 
      46                 :          4 :         fd = mkostemp_safe(name);
      47         [ -  + ]:          4 :         assert_se(fd >= 0);
      48         [ -  + ]:          4 :         assert_se(close_nointr(fd) >= 0);
      49         [ -  + ]:          4 :         assert_se(close_nointr(fd) < 0);
      50                 :            : 
      51                 :          4 :         unlink(name);
      52                 :          4 : }
      53                 :            : 
      54                 :          4 : static void test_same_fd(void) {
      55                 :          4 :         _cleanup_close_pair_ int p[2] = { -1, -1 };
      56                 :          4 :         _cleanup_close_ int a = -1, b = -1, c = -1;
      57                 :            : 
      58         [ -  + ]:          4 :         assert_se(pipe2(p, O_CLOEXEC) >= 0);
      59         [ -  + ]:          4 :         assert_se((a = fcntl(p[0], F_DUPFD, 3)) >= 0);
      60         [ -  + ]:          4 :         assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0);
      61         [ -  + ]:          4 :         assert_se((c = fcntl(a, F_DUPFD, 3)) >= 0);
      62                 :            : 
      63         [ -  + ]:          4 :         assert_se(same_fd(p[0], p[0]) > 0);
      64         [ -  + ]:          4 :         assert_se(same_fd(p[1], p[1]) > 0);
      65         [ -  + ]:          4 :         assert_se(same_fd(a, a) > 0);
      66         [ -  + ]:          4 :         assert_se(same_fd(b, b) > 0);
      67                 :            : 
      68         [ -  + ]:          4 :         assert_se(same_fd(a, p[0]) > 0);
      69         [ -  + ]:          4 :         assert_se(same_fd(p[0], a) > 0);
      70         [ -  + ]:          4 :         assert_se(same_fd(c, p[0]) > 0);
      71         [ -  + ]:          4 :         assert_se(same_fd(p[0], c) > 0);
      72         [ -  + ]:          4 :         assert_se(same_fd(a, c) > 0);
      73         [ -  + ]:          4 :         assert_se(same_fd(c, a) > 0);
      74                 :            : 
      75         [ -  + ]:          4 :         assert_se(same_fd(p[0], p[1]) == 0);
      76         [ -  + ]:          4 :         assert_se(same_fd(p[1], p[0]) == 0);
      77         [ -  + ]:          4 :         assert_se(same_fd(p[0], b) == 0);
      78         [ -  + ]:          4 :         assert_se(same_fd(b, p[0]) == 0);
      79         [ -  + ]:          4 :         assert_se(same_fd(p[1], a) == 0);
      80         [ -  + ]:          4 :         assert_se(same_fd(a, p[1]) == 0);
      81         [ -  + ]:          4 :         assert_se(same_fd(p[1], b) == 0);
      82         [ -  + ]:          4 :         assert_se(same_fd(b, p[1]) == 0);
      83                 :            : 
      84         [ -  + ]:          4 :         assert_se(same_fd(a, b) == 0);
      85         [ -  + ]:          4 :         assert_se(same_fd(b, a) == 0);
      86                 :          4 : }
      87                 :            : 
      88                 :          4 : static void test_open_serialization_fd(void) {
      89                 :          4 :         _cleanup_close_ int fd = -1;
      90                 :            : 
      91                 :          4 :         fd = open_serialization_fd("test");
      92         [ -  + ]:          4 :         assert_se(fd >= 0);
      93                 :            : 
      94         [ -  + ]:          4 :         assert_se(write(fd, "test\n", 5) == 5);
      95                 :          4 : }
      96                 :            : 
      97                 :         36 : static void test_acquire_data_fd_one(unsigned flags) {
      98                 :            :         char wbuffer[196*1024 - 7];
      99                 :            :         char rbuffer[sizeof(wbuffer)];
     100                 :            :         int fd;
     101                 :            : 
     102                 :         36 :         fd = acquire_data_fd("foo", 3, flags);
     103         [ -  + ]:         36 :         assert_se(fd >= 0);
     104                 :            : 
     105         [ +  - ]:         36 :         zero(rbuffer);
     106         [ -  + ]:         36 :         assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 3);
     107         [ -  + ]:         36 :         assert_se(streq(rbuffer, "foo"));
     108                 :            : 
     109                 :         36 :         fd = safe_close(fd);
     110                 :            : 
     111                 :         36 :         fd = acquire_data_fd("", 0, flags);
     112         [ -  + ]:         36 :         assert_se(fd >= 0);
     113                 :            : 
     114         [ +  - ]:         36 :         zero(rbuffer);
     115         [ -  + ]:         36 :         assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 0);
     116         [ -  + ]:         36 :         assert_se(streq(rbuffer, ""));
     117                 :            : 
     118                 :         36 :         fd = safe_close(fd);
     119                 :            : 
     120                 :         36 :         random_bytes(wbuffer, sizeof(wbuffer));
     121                 :            : 
     122                 :         36 :         fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags);
     123         [ -  + ]:         36 :         assert_se(fd >= 0);
     124                 :            : 
     125         [ +  - ]:         36 :         zero(rbuffer);
     126         [ -  + ]:         36 :         assert_se(read(fd, rbuffer, sizeof(rbuffer)) == sizeof(rbuffer));
     127         [ -  + ]:         36 :         assert_se(memcmp(rbuffer, wbuffer, sizeof(rbuffer)) == 0);
     128                 :            : 
     129                 :         36 :         fd = safe_close(fd);
     130                 :         36 : }
     131                 :            : 
     132                 :          4 : static void test_acquire_data_fd(void) {
     133                 :            : 
     134                 :          4 :         test_acquire_data_fd_one(0);
     135                 :          4 :         test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL);
     136                 :          4 :         test_acquire_data_fd_one(ACQUIRE_NO_MEMFD);
     137                 :          4 :         test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD);
     138                 :          4 :         test_acquire_data_fd_one(ACQUIRE_NO_PIPE);
     139                 :          4 :         test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_PIPE);
     140                 :          4 :         test_acquire_data_fd_one(ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
     141                 :          4 :         test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE);
     142                 :          4 :         test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE|ACQUIRE_NO_TMPFILE);
     143                 :          4 : }
     144                 :            : 
     145                 :          4 : static void test_fd_move_above_stdio(void) {
     146                 :            :         int original_stdin, new_fd;
     147                 :            : 
     148                 :          4 :         original_stdin = fcntl(0, F_DUPFD, 3);
     149         [ -  + ]:          4 :         assert_se(original_stdin >= 3);
     150         [ -  + ]:          4 :         assert_se(close_nointr(0) != EBADF);
     151                 :            : 
     152                 :          4 :         new_fd = open("/dev/null", O_RDONLY);
     153         [ -  + ]:          4 :         assert_se(new_fd == 0);
     154                 :            : 
     155                 :          4 :         new_fd = fd_move_above_stdio(new_fd);
     156         [ -  + ]:          4 :         assert_se(new_fd >= 3);
     157                 :            : 
     158         [ -  + ]:          4 :         assert_se(dup(original_stdin) == 0);
     159         [ -  + ]:          4 :         assert_se(close_nointr(original_stdin) != EBADF);
     160         [ -  + ]:          4 :         assert_se(close_nointr(new_fd) != EBADF);
     161                 :          4 : }
     162                 :            : 
     163                 :          4 : static void test_rearrange_stdio(void) {
     164                 :            :         pid_t pid;
     165                 :            :         int r;
     166                 :            : 
     167                 :          4 :         r = safe_fork("rearrange", FORK_WAIT|FORK_LOG, &pid);
     168         [ -  + ]:          4 :         assert_se(r >= 0);
     169                 :            : 
     170         [ -  + ]:          4 :         if (r == 0) {
     171                 :          0 :                 _cleanup_free_ char *path = NULL;
     172                 :            :                 char buffer[10];
     173                 :            : 
     174                 :            :                 /* Child */
     175                 :            : 
     176                 :          0 :                 safe_close(STDERR_FILENO); /* Let's close an fd < 2, to make it more interesting */
     177                 :            : 
     178         [ #  # ]:          0 :                 assert_se(rearrange_stdio(-1, -1, -1) >= 0);
     179                 :            : 
     180         [ #  # ]:          0 :                 assert_se(fd_get_path(STDIN_FILENO, &path) >= 0);
     181         [ #  # ]:          0 :                 assert_se(path_equal(path, "/dev/null"));
     182                 :          0 :                 path = mfree(path);
     183                 :            : 
     184         [ #  # ]:          0 :                 assert_se(fd_get_path(STDOUT_FILENO, &path) >= 0);
     185         [ #  # ]:          0 :                 assert_se(path_equal(path, "/dev/null"));
     186                 :          0 :                 path = mfree(path);
     187                 :            : 
     188         [ #  # ]:          0 :                 assert_se(fd_get_path(STDOUT_FILENO, &path) >= 0);
     189         [ #  # ]:          0 :                 assert_se(path_equal(path, "/dev/null"));
     190                 :          0 :                 path = mfree(path);
     191                 :            : 
     192                 :          0 :                 safe_close(STDIN_FILENO);
     193                 :          0 :                 safe_close(STDOUT_FILENO);
     194                 :          0 :                 safe_close(STDERR_FILENO);
     195                 :            : 
     196                 :            :                 {
     197                 :            :                         int pair[2];
     198         [ #  # ]:          0 :                         assert_se(pipe(pair) >= 0);
     199         [ #  # ]:          0 :                         assert_se(pair[0] == 0);
     200         [ #  # ]:          0 :                         assert_se(pair[1] == 1);
     201         [ #  # ]:          0 :                         assert_se(fd_move_above_stdio(0) == 3);
     202                 :            :                 }
     203         [ #  # ]:          0 :                 assert_se(open("/dev/full", O_WRONLY|O_CLOEXEC) == 0);
     204         [ #  # ]:          0 :                 assert_se(acquire_data_fd("foobar", 6, 0) == 2);
     205                 :            : 
     206         [ #  # ]:          0 :                 assert_se(rearrange_stdio(2, 0, 1) >= 0);
     207                 :            : 
     208   [ #  #  #  # ]:          0 :                 assert_se(write(1, "x", 1) < 0 && errno == ENOSPC);
     209         [ #  # ]:          0 :                 assert_se(write(2, "z", 1) == 1);
     210         [ #  # ]:          0 :                 assert_se(read(3, buffer, sizeof(buffer)) == 1);
     211         [ #  # ]:          0 :                 assert_se(buffer[0] == 'z');
     212         [ #  # ]:          0 :                 assert_se(read(0, buffer, sizeof(buffer)) == 6);
     213         [ #  # ]:          0 :                 assert_se(memcmp(buffer, "foobar", 6) == 0);
     214                 :            : 
     215         [ #  # ]:          0 :                 assert_se(rearrange_stdio(-1, 1, 2) >= 0);
     216   [ #  #  #  # ]:          0 :                 assert_se(write(1, "a", 1) < 0 && errno == ENOSPC);
     217         [ #  # ]:          0 :                 assert_se(write(2, "y", 1) == 1);
     218         [ #  # ]:          0 :                 assert_se(read(3, buffer, sizeof(buffer)) == 1);
     219         [ #  # ]:          0 :                 assert_se(buffer[0] == 'y');
     220                 :            : 
     221         [ #  # ]:          0 :                 assert_se(fd_get_path(0, &path) >= 0);
     222         [ #  # ]:          0 :                 assert_se(path_equal(path, "/dev/null"));
     223                 :          0 :                 path = mfree(path);
     224                 :            : 
     225                 :          0 :                 _exit(EXIT_SUCCESS);
     226                 :            :         }
     227                 :          4 : }
     228                 :            : 
     229                 :         16 : static void assert_equal_fd(int fd1, int fd2) {
     230                 :            : 
     231                 :          8 :         for (;;) {
     232                 :            :                 uint8_t a[4096], b[4096];
     233                 :            :                 ssize_t x, y;
     234                 :            : 
     235                 :         16 :                 x = read(fd1, a, sizeof(a));
     236         [ -  + ]:         16 :                 assert(x >= 0);
     237                 :            : 
     238                 :         16 :                 y = read(fd2, b, sizeof(b));
     239         [ -  + ]:         16 :                 assert(y >= 0);
     240                 :            : 
     241         [ -  + ]:         16 :                 assert(x == y);
     242                 :            : 
     243         [ +  + ]:         16 :                 if (x == 0)
     244                 :          8 :                         break;
     245                 :            : 
     246         [ -  + ]:          8 :                 assert(memcmp(a, b, x) == 0);
     247                 :            :         }
     248                 :          8 : }
     249                 :            : 
     250                 :          4 : static void test_fd_duplicate_data_fd(void) {
     251                 :          4 :         _cleanup_close_ int fd1 = -1, fd2 = -1;
     252                 :          4 :         _cleanup_(close_pairp) int sfd[2] = { -1, -1 };
     253                 :          4 :         _cleanup_(sigkill_waitp) pid_t pid = -1;
     254                 :            :         uint64_t i, j;
     255                 :            :         int r;
     256                 :            : 
     257                 :          4 :         fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC);
     258         [ +  - ]:          4 :         if (fd1 >= 0) {
     259                 :            : 
     260                 :          4 :                 fd2 = fd_duplicate_data_fd(fd1);
     261         [ -  + ]:          4 :                 assert_se(fd2 >= 0);
     262                 :            : 
     263         [ -  + ]:          4 :                 assert_se(lseek(fd1, 0, SEEK_SET) == 0);
     264                 :          4 :                 assert_equal_fd(fd1, fd2);
     265                 :            :         }
     266                 :            : 
     267                 :          4 :         fd1 = safe_close(fd1);
     268                 :          4 :         fd2 = safe_close(fd2);
     269                 :            : 
     270                 :          4 :         fd1 = acquire_data_fd("hallo", 6,  0);
     271         [ -  + ]:          4 :         assert_se(fd1 >= 0);
     272                 :            : 
     273                 :          4 :         fd2 = fd_duplicate_data_fd(fd1);
     274         [ -  + ]:          4 :         assert_se(fd2 >= 0);
     275                 :            : 
     276                 :          4 :         safe_close(fd1);
     277                 :          4 :         fd1 = acquire_data_fd("hallo", 6,  0);
     278         [ -  + ]:          4 :         assert_se(fd1 >= 0);
     279                 :            : 
     280                 :          4 :         assert_equal_fd(fd1, fd2);
     281                 :            : 
     282                 :          4 :         fd1 = safe_close(fd1);
     283                 :          4 :         fd2 = safe_close(fd2);
     284                 :            : 
     285         [ -  + ]:          4 :         assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
     286                 :            : 
     287                 :          4 :         r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
     288         [ -  + ]:          4 :         assert_se(r >= 0);
     289                 :            : 
     290         [ -  + ]:          4 :         if (r == 0) {
     291                 :            :                 /* child */
     292                 :            : 
     293                 :          0 :                 sfd[0] = safe_close(sfd[0]);
     294                 :            : 
     295         [ #  # ]:          0 :                 for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++)
     296         [ #  # ]:          0 :                         assert_se(write(sfd[1], &i, sizeof(i)) == sizeof(i));
     297                 :            : 
     298                 :          0 :                 sfd[1] = safe_close(sfd[1]);
     299                 :            : 
     300                 :          0 :                 _exit(EXIT_SUCCESS);
     301                 :            :         }
     302                 :            : 
     303                 :          4 :         sfd[1] = safe_close(sfd[1]);
     304                 :            : 
     305                 :          4 :         fd2 = fd_duplicate_data_fd(sfd[0]);
     306         [ -  + ]:          4 :         assert_se(fd2 >= 0);
     307                 :            : 
     308         [ +  + ]:     786436 :         for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++) {
     309         [ -  + ]:     786432 :                 assert_se(read(fd2, &j, sizeof(j)) == sizeof(j));
     310         [ -  + ]:     786432 :                 assert_se(i == j);
     311                 :            :         }
     312                 :            : 
     313         [ -  + ]:          4 :         assert_se(read(fd2, &j, sizeof(j)) == 0);
     314                 :          4 : }
     315                 :            : 
     316                 :          4 : static void test_read_nr_open(void) {
     317         [ +  - ]:          4 :         log_info("nr-open: %i", read_nr_open());
     318                 :          4 : }
     319                 :            : 
     320                 :          4 : int main(int argc, char *argv[]) {
     321                 :            : 
     322                 :          4 :         test_setup_logging(LOG_DEBUG);
     323                 :            : 
     324                 :          4 :         test_close_many();
     325                 :          4 :         test_close_nointr();
     326                 :          4 :         test_same_fd();
     327                 :          4 :         test_open_serialization_fd();
     328                 :          4 :         test_acquire_data_fd();
     329                 :          4 :         test_fd_move_above_stdio();
     330                 :          4 :         test_rearrange_stdio();
     331                 :          4 :         test_fd_duplicate_data_fd();
     332                 :          4 :         test_read_nr_open();
     333                 :            : 
     334                 :          4 :         return 0;
     335                 :            : }

Generated by: LCOV version 1.14