LCOV - code coverage report
Current view: top level - shared - fdset.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 92 122 75.4 %
Date: 2019-08-23 13:36:53 Functions: 15 16 93.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 48 86 55.8 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <alloca.h>
       4                 :            : #include <errno.h>
       5                 :            : #include <fcntl.h>
       6                 :            : #include <stddef.h>
       7                 :            : 
       8                 :            : #include "sd-daemon.h"
       9                 :            : 
      10                 :            : #include "alloc-util.h"
      11                 :            : #include "dirent-util.h"
      12                 :            : #include "fd-util.h"
      13                 :            : #include "fdset.h"
      14                 :            : #include "log.h"
      15                 :            : #include "macro.h"
      16                 :            : #include "parse-util.h"
      17                 :            : #include "path-util.h"
      18                 :            : #include "set.h"
      19                 :            : 
      20                 :            : #define MAKE_SET(s) ((Set*) s)
      21                 :            : #define MAKE_FDSET(s) ((FDSet*) s)
      22                 :            : 
      23                 :         36 : FDSet *fdset_new(void) {
      24                 :         36 :         return MAKE_FDSET(set_new(NULL));
      25                 :            : }
      26                 :            : 
      27                 :          4 : int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds) {
      28                 :            :         size_t i;
      29                 :            :         FDSet *s;
      30                 :            :         int r;
      31                 :            : 
      32         [ -  + ]:          4 :         assert(ret);
      33                 :            : 
      34                 :          4 :         s = fdset_new();
      35         [ -  + ]:          4 :         if (!s)
      36                 :          0 :                 return -ENOMEM;
      37                 :            : 
      38         [ +  + ]:         20 :         for (i = 0; i < n_fds; i++) {
      39                 :            : 
      40                 :         16 :                 r = fdset_put(s, fds[i]);
      41         [ -  + ]:         16 :                 if (r < 0) {
      42                 :          0 :                         set_free(MAKE_SET(s));
      43                 :          0 :                         return r;
      44                 :            :                 }
      45                 :            :         }
      46                 :            : 
      47                 :          4 :         *ret = s;
      48                 :          4 :         return 0;
      49                 :            : }
      50                 :            : 
      51                 :         36 : void fdset_close(FDSet *s) {
      52                 :            :         void *p;
      53                 :            : 
      54         [ +  + ]:         80 :         while ((p = set_steal_first(MAKE_SET(s)))) {
      55                 :            :                 /* Valgrind's fd might have ended up in this set here, due to fdset_new_fill(). We'll ignore
      56                 :            :                  * all failures here, so that the EBADFD that valgrind will return us on close() doesn't
      57                 :            :                  * influence us */
      58                 :            : 
      59                 :            :                 /* When reloading duplicates of the private bus connection fds and suchlike are closed here,
      60                 :            :                  * which has no effect at all, since they are only duplicates. So don't be surprised about
      61                 :            :                  * these log messages. */
      62                 :            : 
      63         [ -  + ]:         44 :                 log_debug("Closing set fd %i", PTR_TO_FD(p));
      64                 :         44 :                 (void) close_nointr(PTR_TO_FD(p));
      65                 :            :         }
      66                 :         36 : }
      67                 :            : 
      68                 :         36 : FDSet* fdset_free(FDSet *s) {
      69                 :         36 :         fdset_close(s);
      70                 :         36 :         set_free(MAKE_SET(s));
      71                 :         36 :         return NULL;
      72                 :            : }
      73                 :            : 
      74                 :         60 : int fdset_put(FDSet *s, int fd) {
      75         [ -  + ]:         60 :         assert(s);
      76         [ -  + ]:         60 :         assert(fd >= 0);
      77                 :            : 
      78                 :         60 :         return set_put(MAKE_SET(s), FD_TO_PTR(fd));
      79                 :            : }
      80                 :            : 
      81                 :          8 : int fdset_put_dup(FDSet *s, int fd) {
      82                 :            :         int copy, r;
      83                 :            : 
      84         [ -  + ]:          8 :         assert(s);
      85         [ -  + ]:          8 :         assert(fd >= 0);
      86                 :            : 
      87                 :          8 :         copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
      88         [ -  + ]:          8 :         if (copy < 0)
      89                 :          0 :                 return -errno;
      90                 :            : 
      91                 :          8 :         r = fdset_put(s, copy);
      92         [ -  + ]:          8 :         if (r < 0) {
      93                 :          0 :                 safe_close(copy);
      94                 :          0 :                 return r;
      95                 :            :         }
      96                 :            : 
      97                 :          8 :         return copy;
      98                 :            : }
      99                 :            : 
     100                 :         32 : bool fdset_contains(FDSet *s, int fd) {
     101         [ -  + ]:         32 :         assert(s);
     102         [ -  + ]:         32 :         assert(fd >= 0);
     103                 :            : 
     104                 :         32 :         return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
     105                 :            : }
     106                 :            : 
     107                 :          4 : int fdset_remove(FDSet *s, int fd) {
     108         [ -  + ]:          4 :         assert(s);
     109         [ -  + ]:          4 :         assert(fd >= 0);
     110                 :            : 
     111         [ +  - ]:          4 :         return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
     112                 :            : }
     113                 :            : 
     114                 :          4 : int fdset_new_fill(FDSet **_s) {
     115                 :          4 :         _cleanup_closedir_ DIR *d = NULL;
     116                 :            :         struct dirent *de;
     117                 :          4 :         int r = 0;
     118                 :            :         FDSet *s;
     119                 :            : 
     120         [ -  + ]:          4 :         assert(_s);
     121                 :            : 
     122                 :            :         /* Creates an fdset and fills in all currently open file
     123                 :            :          * descriptors. */
     124                 :            : 
     125                 :          4 :         d = opendir("/proc/self/fd");
     126         [ -  + ]:          4 :         if (!d)
     127                 :          0 :                 return -errno;
     128                 :            : 
     129                 :          4 :         s = fdset_new();
     130         [ -  + ]:          4 :         if (!s) {
     131                 :          0 :                 r = -ENOMEM;
     132                 :          0 :                 goto finish;
     133                 :            :         }
     134                 :            : 
     135   [ +  +  -  +  :         32 :         FOREACH_DIRENT(de, d, return -errno) {
                   +  + ]
     136                 :         20 :                 int fd = -1;
     137                 :            : 
     138                 :         20 :                 r = safe_atoi(de->d_name, &fd);
     139         [ -  + ]:         20 :                 if (r < 0)
     140                 :          0 :                         goto finish;
     141                 :            : 
     142         [ +  + ]:         20 :                 if (fd < 3)
     143                 :         16 :                         continue;
     144                 :            : 
     145         [ +  + ]:          8 :                 if (fd == dirfd(d))
     146                 :          4 :                         continue;
     147                 :            : 
     148                 :          4 :                 r = fdset_put(s, fd);
     149         [ -  + ]:          4 :                 if (r < 0)
     150                 :          0 :                         goto finish;
     151                 :            :         }
     152                 :            : 
     153                 :          4 :         r = 0;
     154                 :          4 :         *_s = TAKE_PTR(s);
     155                 :            : 
     156                 :          4 : finish:
     157                 :            :         /* We won't close the fds here! */
     158         [ -  + ]:          4 :         if (s)
     159                 :          0 :                 set_free(MAKE_SET(s));
     160                 :            : 
     161                 :          4 :         return r;
     162                 :            : }
     163                 :            : 
     164                 :          8 : int fdset_cloexec(FDSet *fds, bool b) {
     165                 :            :         Iterator i;
     166                 :            :         void *p;
     167                 :            :         int r;
     168                 :            : 
     169         [ -  + ]:          8 :         assert(fds);
     170                 :            : 
     171         [ +  + ]:         16 :         SET_FOREACH(p, MAKE_SET(fds), i) {
     172                 :          8 :                 r = fd_cloexec(PTR_TO_FD(p), b);
     173         [ -  + ]:          8 :                 if (r < 0)
     174                 :          0 :                         return r;
     175                 :            :         }
     176                 :            : 
     177                 :          8 :         return 0;
     178                 :            : }
     179                 :            : 
     180                 :          0 : int fdset_new_listen_fds(FDSet **_s, bool unset) {
     181                 :            :         int n, fd, r;
     182                 :            :         FDSet *s;
     183                 :            : 
     184         [ #  # ]:          0 :         assert(_s);
     185                 :            : 
     186                 :            :         /* Creates an fdset and fills in all passed file descriptors */
     187                 :            : 
     188                 :          0 :         s = fdset_new();
     189         [ #  # ]:          0 :         if (!s) {
     190                 :          0 :                 r = -ENOMEM;
     191                 :          0 :                 goto fail;
     192                 :            :         }
     193                 :            : 
     194                 :          0 :         n = sd_listen_fds(unset);
     195         [ #  # ]:          0 :         for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
     196                 :          0 :                 r = fdset_put(s, fd);
     197         [ #  # ]:          0 :                 if (r < 0)
     198                 :          0 :                         goto fail;
     199                 :            :         }
     200                 :            : 
     201                 :          0 :         *_s = s;
     202                 :          0 :         return 0;
     203                 :            : 
     204                 :          0 : fail:
     205         [ #  # ]:          0 :         if (s)
     206                 :          0 :                 set_free(MAKE_SET(s));
     207                 :            : 
     208                 :          0 :         return r;
     209                 :            : }
     210                 :            : 
     211                 :          4 : int fdset_close_others(FDSet *fds) {
     212                 :            :         void *e;
     213                 :            :         Iterator i;
     214                 :          4 :         int *a = NULL;
     215                 :          4 :         size_t j = 0, m;
     216                 :            : 
     217                 :          4 :         m = fdset_size(fds);
     218                 :            : 
     219         [ +  - ]:          4 :         if (m > 0) {
     220   [ -  +  -  + ]:          4 :                 a = newa(int, m);
     221         [ +  + ]:          8 :                 SET_FOREACH(e, MAKE_SET(fds), i)
     222                 :          4 :                         a[j++] = PTR_TO_FD(e);
     223                 :            :         }
     224                 :            : 
     225         [ -  + ]:          4 :         assert(j == m);
     226                 :            : 
     227                 :          4 :         return close_all_fds(a, j);
     228                 :            : }
     229                 :            : 
     230                 :         52 : unsigned fdset_size(FDSet *fds) {
     231                 :         52 :         return set_size(MAKE_SET(fds));
     232                 :            : }
     233                 :            : 
     234                 :          8 : bool fdset_isempty(FDSet *fds) {
     235                 :          8 :         return set_isempty(MAKE_SET(fds));
     236                 :            : }
     237                 :            : 
     238                 :          8 : int fdset_iterate(FDSet *s, Iterator *i) {
     239                 :            :         void *p;
     240                 :            : 
     241         [ +  + ]:          8 :         if (!set_iterate(MAKE_SET(s), i, &p))
     242                 :          4 :                 return -ENOENT;
     243                 :            : 
     244                 :          4 :         return PTR_TO_FD(p);
     245                 :            : }
     246                 :            : 
     247                 :         12 : int fdset_steal_first(FDSet *fds) {
     248                 :            :         void *p;
     249                 :            : 
     250                 :         12 :         p = set_steal_first(MAKE_SET(fds));
     251         [ +  + ]:         12 :         if (!p)
     252                 :          8 :                 return -ENOENT;
     253                 :            : 
     254                 :          4 :         return PTR_TO_FD(p);
     255                 :            : }

Generated by: LCOV version 1.14