LCOV - code coverage report
Current view: top level - shared - cgroup-show.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 163 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 8 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 156 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <dirent.h>
       4                 :            : #include <errno.h>
       5                 :            : #include <stddef.h>
       6                 :            : #include <stdio.h>
       7                 :            : #include <stdlib.h>
       8                 :            : #include <string.h>
       9                 :            : 
      10                 :            : #include "alloc-util.h"
      11                 :            : #include "bus-error.h"
      12                 :            : #include "bus-util.h"
      13                 :            : #include "cgroup-show.h"
      14                 :            : #include "cgroup-util.h"
      15                 :            : #include "env-file.h"
      16                 :            : #include "fd-util.h"
      17                 :            : #include "format-util.h"
      18                 :            : #include "locale-util.h"
      19                 :            : #include "macro.h"
      20                 :            : #include "output-mode.h"
      21                 :            : #include "path-util.h"
      22                 :            : #include "process-util.h"
      23                 :            : #include "sort-util.h"
      24                 :            : #include "string-util.h"
      25                 :            : #include "terminal-util.h"
      26                 :            : #include "unit-name.h"
      27                 :            : 
      28                 :          0 : static void show_pid_array(
      29                 :            :                 pid_t pids[],
      30                 :            :                 unsigned n_pids,
      31                 :            :                 const char *prefix,
      32                 :            :                 size_t n_columns,
      33                 :            :                 bool extra,
      34                 :            :                 bool more,
      35                 :            :                 OutputFlags flags) {
      36                 :            : 
      37                 :            :         unsigned i, j, pid_width;
      38                 :            : 
      39         [ #  # ]:          0 :         if (n_pids == 0)
      40                 :          0 :                 return;
      41                 :            : 
      42                 :          0 :         typesafe_qsort(pids, n_pids, pid_compare_func);
      43                 :            : 
      44                 :            :         /* Filter duplicates */
      45         [ #  # ]:          0 :         for (j = 0, i = 1; i < n_pids; i++) {
      46         [ #  # ]:          0 :                 if (pids[i] == pids[j])
      47                 :          0 :                         continue;
      48                 :          0 :                 pids[++j] = pids[i];
      49                 :            :         }
      50                 :          0 :         n_pids = j + 1;
      51         [ #  # ]:          0 :         pid_width = DECIMAL_STR_WIDTH(pids[j]);
      52                 :            : 
      53         [ #  # ]:          0 :         if (flags & OUTPUT_FULL_WIDTH)
      54                 :          0 :                 n_columns = SIZE_MAX;
      55                 :            :         else {
      56         [ #  # ]:          0 :                 if (n_columns > pid_width + 3) /* something like "├─1114784 " */
      57                 :          0 :                         n_columns -= pid_width + 3;
      58                 :            :                 else
      59                 :          0 :                         n_columns = 20;
      60                 :            :         }
      61         [ #  # ]:          0 :         for (i = 0; i < n_pids; i++) {
      62                 :          0 :                 _cleanup_free_ char *t = NULL;
      63                 :            : 
      64                 :          0 :                 (void) get_process_cmdline(pids[i], n_columns,
      65                 :            :                                            PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_USE_LOCALE,
      66                 :            :                                            &t);
      67                 :            : 
      68         [ #  # ]:          0 :                 if (extra)
      69                 :          0 :                         printf("%s%s ", prefix, special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET));
      70                 :            :                 else
      71   [ #  #  #  # ]:          0 :                         printf("%s%s", prefix, special_glyph(((more || i < n_pids-1) ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT)));
      72                 :            : 
      73                 :          0 :                 printf("%*"PID_PRI" %s\n", pid_width, pids[i], strna(t));
      74                 :            :         }
      75                 :            : }
      76                 :            : 
      77                 :          0 : static int show_cgroup_one_by_path(
      78                 :            :                 const char *path,
      79                 :            :                 const char *prefix,
      80                 :            :                 size_t n_columns,
      81                 :            :                 bool more,
      82                 :            :                 OutputFlags flags) {
      83                 :            : 
      84                 :            :         char *fn;
      85                 :          0 :         _cleanup_fclose_ FILE *f = NULL;
      86                 :          0 :         size_t n = 0, n_allocated = 0;
      87                 :          0 :         _cleanup_free_ pid_t *pids = NULL;
      88                 :          0 :         _cleanup_free_ char *p = NULL;
      89                 :            :         pid_t pid;
      90                 :            :         int r;
      91                 :            : 
      92                 :          0 :         r = cg_mangle_path(path, &p);
      93         [ #  # ]:          0 :         if (r < 0)
      94                 :          0 :                 return r;
      95                 :            : 
      96   [ #  #  #  #  :          0 :         fn = strjoina(p, "/cgroup.procs");
          #  #  #  #  #  
                #  #  # ]
      97                 :          0 :         f = fopen(fn, "re");
      98         [ #  # ]:          0 :         if (!f)
      99                 :          0 :                 return -errno;
     100                 :            : 
     101         [ #  # ]:          0 :         while ((r = cg_read_pid(f, &pid)) > 0) {
     102                 :            : 
     103   [ #  #  #  # ]:          0 :                 if (!(flags & OUTPUT_KERNEL_THREADS) && is_kernel_thread(pid) > 0)
     104                 :          0 :                         continue;
     105                 :            : 
     106         [ #  # ]:          0 :                 if (!GREEDY_REALLOC(pids, n_allocated, n + 1))
     107                 :          0 :                         return -ENOMEM;
     108                 :            : 
     109         [ #  # ]:          0 :                 assert(n < n_allocated);
     110                 :          0 :                 pids[n++] = pid;
     111                 :            :         }
     112                 :            : 
     113         [ #  # ]:          0 :         if (r < 0)
     114                 :          0 :                 return r;
     115                 :            : 
     116                 :          0 :         show_pid_array(pids, n, prefix, n_columns, false, more, flags);
     117                 :            : 
     118                 :          0 :         return 0;
     119                 :            : }
     120                 :            : 
     121                 :          0 : int show_cgroup_by_path(
     122                 :            :                 const char *path,
     123                 :            :                 const char *prefix,
     124                 :            :                 size_t n_columns,
     125                 :            :                 OutputFlags flags) {
     126                 :            : 
     127                 :          0 :         _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL;
     128                 :          0 :         _cleanup_closedir_ DIR *d = NULL;
     129                 :          0 :         char *gn = NULL;
     130                 :          0 :         bool shown_pids = false;
     131                 :            :         int r;
     132                 :            : 
     133         [ #  # ]:          0 :         assert(path);
     134                 :            : 
     135         [ #  # ]:          0 :         if (n_columns <= 0)
     136                 :          0 :                 n_columns = columns();
     137                 :            : 
     138                 :          0 :         prefix = strempty(prefix);
     139                 :            : 
     140                 :          0 :         r = cg_mangle_path(path, &fn);
     141         [ #  # ]:          0 :         if (r < 0)
     142                 :          0 :                 return r;
     143                 :            : 
     144                 :          0 :         d = opendir(fn);
     145         [ #  # ]:          0 :         if (!d)
     146                 :          0 :                 return -errno;
     147                 :            : 
     148         [ #  # ]:          0 :         while ((r = cg_read_subgroup(d, &gn)) > 0) {
     149      [ #  #  # ]:          0 :                 _cleanup_free_ char *k = NULL;
     150                 :            : 
     151                 :          0 :                 k = path_join(fn, gn);
     152                 :          0 :                 free(gn);
     153         [ #  # ]:          0 :                 if (!k)
     154                 :          0 :                         return -ENOMEM;
     155                 :            : 
     156   [ #  #  #  # ]:          0 :                 if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k) > 0)
     157                 :          0 :                         continue;
     158                 :            : 
     159         [ #  # ]:          0 :                 if (!shown_pids) {
     160                 :          0 :                         show_cgroup_one_by_path(path, prefix, n_columns, true, flags);
     161                 :          0 :                         shown_pids = true;
     162                 :            :                 }
     163                 :            : 
     164         [ #  # ]:          0 :                 if (last) {
     165                 :          0 :                         printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_BRANCH), cg_unescape(basename(last)));
     166                 :            : 
     167         [ #  # ]:          0 :                         if (!p1) {
     168                 :          0 :                                 p1 = strjoin(prefix, special_glyph(SPECIAL_GLYPH_TREE_VERTICAL));
     169         [ #  # ]:          0 :                                 if (!p1)
     170                 :          0 :                                         return -ENOMEM;
     171                 :            :                         }
     172                 :            : 
     173                 :          0 :                         show_cgroup_by_path(last, p1, n_columns-2, flags);
     174                 :          0 :                         free(last);
     175                 :            :                 }
     176                 :            : 
     177                 :          0 :                 last = TAKE_PTR(k);
     178                 :            :         }
     179                 :            : 
     180         [ #  # ]:          0 :         if (r < 0)
     181                 :          0 :                 return r;
     182                 :            : 
     183         [ #  # ]:          0 :         if (!shown_pids)
     184                 :          0 :                 show_cgroup_one_by_path(path, prefix, n_columns, !!last, flags);
     185                 :            : 
     186         [ #  # ]:          0 :         if (last) {
     187                 :          0 :                 printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT), cg_unescape(basename(last)));
     188                 :            : 
     189         [ #  # ]:          0 :                 if (!p2) {
     190                 :          0 :                         p2 = strjoin(prefix, "  ");
     191         [ #  # ]:          0 :                         if (!p2)
     192                 :          0 :                                 return -ENOMEM;
     193                 :            :                 }
     194                 :            : 
     195                 :          0 :                 show_cgroup_by_path(last, p2, n_columns-2, flags);
     196                 :            :         }
     197                 :            : 
     198                 :          0 :         return 0;
     199                 :            : }
     200                 :            : 
     201                 :          0 : int show_cgroup(const char *controller,
     202                 :            :                 const char *path,
     203                 :            :                 const char *prefix,
     204                 :            :                 size_t n_columns,
     205                 :            :                 OutputFlags flags) {
     206                 :          0 :         _cleanup_free_ char *p = NULL;
     207                 :            :         int r;
     208                 :            : 
     209         [ #  # ]:          0 :         assert(path);
     210                 :            : 
     211                 :          0 :         r = cg_get_path(controller, path, NULL, &p);
     212         [ #  # ]:          0 :         if (r < 0)
     213                 :          0 :                 return r;
     214                 :            : 
     215                 :          0 :         return show_cgroup_by_path(p, prefix, n_columns, flags);
     216                 :            : }
     217                 :            : 
     218                 :          0 : static int show_extra_pids(
     219                 :            :                 const char *controller,
     220                 :            :                 const char *path,
     221                 :            :                 const char *prefix,
     222                 :            :                 size_t n_columns,
     223                 :            :                 const pid_t pids[],
     224                 :            :                 unsigned n_pids,
     225                 :            :                 OutputFlags flags) {
     226                 :            : 
     227                 :          0 :         _cleanup_free_ pid_t *copy = NULL;
     228                 :            :         unsigned i, j;
     229                 :            :         int r;
     230                 :            : 
     231         [ #  # ]:          0 :         assert(path);
     232                 :            : 
     233         [ #  # ]:          0 :         if (n_pids <= 0)
     234                 :          0 :                 return 0;
     235                 :            : 
     236         [ #  # ]:          0 :         if (n_columns <= 0)
     237                 :          0 :                 n_columns = columns();
     238                 :            : 
     239                 :          0 :         prefix = strempty(prefix);
     240                 :            : 
     241                 :          0 :         copy = new(pid_t, n_pids);
     242         [ #  # ]:          0 :         if (!copy)
     243                 :          0 :                 return -ENOMEM;
     244                 :            : 
     245         [ #  # ]:          0 :         for (i = 0, j = 0; i < n_pids; i++) {
     246      [ #  #  # ]:          0 :                 _cleanup_free_ char *k = NULL;
     247                 :            : 
     248                 :          0 :                 r = cg_pid_get_path(controller, pids[i], &k);
     249         [ #  # ]:          0 :                 if (r < 0)
     250                 :          0 :                         return r;
     251                 :            : 
     252         [ #  # ]:          0 :                 if (path_startswith(k, path))
     253                 :          0 :                         continue;
     254                 :            : 
     255                 :          0 :                 copy[j++] = pids[i];
     256                 :            :         }
     257                 :            : 
     258                 :          0 :         show_pid_array(copy, j, prefix, n_columns, true, false, flags);
     259                 :            : 
     260                 :          0 :         return 0;
     261                 :            : }
     262                 :            : 
     263                 :          0 : int show_cgroup_and_extra(
     264                 :            :                 const char *controller,
     265                 :            :                 const char *path,
     266                 :            :                 const char *prefix,
     267                 :            :                 size_t n_columns,
     268                 :            :                 const pid_t extra_pids[],
     269                 :            :                 unsigned n_extra_pids,
     270                 :            :                 OutputFlags flags) {
     271                 :            : 
     272                 :            :         int r;
     273                 :            : 
     274         [ #  # ]:          0 :         assert(path);
     275                 :            : 
     276                 :          0 :         r = show_cgroup(controller, path, prefix, n_columns, flags);
     277         [ #  # ]:          0 :         if (r < 0)
     278                 :          0 :                 return r;
     279                 :            : 
     280                 :          0 :         return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags);
     281                 :            : }
     282                 :            : 
     283                 :          0 : int show_cgroup_get_unit_path_and_warn(
     284                 :            :                 sd_bus *bus,
     285                 :            :                 const char *unit,
     286                 :            :                 char **ret) {
     287                 :            : 
     288                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     289                 :          0 :         _cleanup_free_ char *path = NULL;
     290                 :            :         int r;
     291                 :            : 
     292                 :          0 :         path = unit_dbus_path_from_name(unit);
     293         [ #  # ]:          0 :         if (!path)
     294                 :          0 :                 return log_oom();
     295                 :            : 
     296                 :          0 :         r = sd_bus_get_property_string(
     297                 :            :                         bus,
     298                 :            :                         "org.freedesktop.systemd1",
     299                 :            :                         path,
     300                 :            :                         unit_dbus_interface_from_name(unit),
     301                 :            :                         "ControlGroup",
     302                 :            :                         &error,
     303                 :            :                         ret);
     304         [ #  # ]:          0 :         if (r < 0)
     305         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to query unit control group path: %s",
     306                 :            :                                        bus_error_message(&error, r));
     307                 :            : 
     308                 :          0 :         return 0;
     309                 :            : }
     310                 :            : 
     311                 :          0 : int show_cgroup_get_path_and_warn(
     312                 :            :                 const char *machine,
     313                 :            :                 const char *prefix,
     314                 :            :                 char **ret) {
     315                 :            : 
     316                 :            :         int r;
     317                 :          0 :         _cleanup_free_ char *root = NULL;
     318                 :            : 
     319         [ #  # ]:          0 :         if (machine) {
     320         [ #  # ]:          0 :                 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
     321         [ #  # ]:          0 :                 _cleanup_free_ char *unit = NULL;
     322                 :            :                 const char *m;
     323                 :            : 
     324   [ #  #  #  #  :          0 :                 m = strjoina("/run/systemd/machines/", machine);
          #  #  #  #  #  
                #  #  # ]
     325                 :          0 :                 r = parse_env_file(NULL, m, "SCOPE", &unit);
     326         [ #  # ]:          0 :                 if (r < 0)
     327         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to load machine data: %m");
     328                 :            : 
     329                 :          0 :                 r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus);
     330         [ #  # ]:          0 :                 if (r < 0)
     331         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to create bus connection: %m");
     332                 :            : 
     333                 :          0 :                 r = show_cgroup_get_unit_path_and_warn(bus, unit, &root);
     334         [ #  # ]:          0 :                 if (r < 0)
     335                 :          0 :                         return r;
     336                 :            :         } else {
     337                 :          0 :                 r = cg_get_root_path(&root);
     338         [ #  # ]:          0 :                 if (r == -ENOMEDIUM)
     339         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to get root control group path.\n"
     340                 :            :                                                   "No cgroup filesystem mounted on /sys/fs/cgroup");
     341         [ #  # ]:          0 :                 else if (r < 0)
     342         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to get root control group path: %m");
     343                 :            :         }
     344                 :            : 
     345         [ #  # ]:          0 :         if (prefix) {
     346                 :            :                 char *t;
     347                 :            : 
     348                 :          0 :                 t = strjoin(root, prefix);
     349         [ #  # ]:          0 :                 if (!t)
     350                 :          0 :                         return log_oom();
     351                 :            : 
     352                 :          0 :                 *ret = t;
     353                 :            :         } else
     354                 :          0 :                 *ret = TAKE_PTR(root);
     355                 :            : 
     356                 :          0 :         return 0;
     357                 :            : }

Generated by: LCOV version 1.14