Imported Upstream version 0.8.9
[platform/upstream/multipath-tools.git] / libmultipath / print.c
1 /*
2  * Copyright (c) 2005 Christophe Varoqui
3  */
4 #include <stdio.h>
5 #include <string.h>
6 #include <libdevmapper.h>
7 #include <stdarg.h>
8 #include <sys/stat.h>
9 #include <dirent.h>
10 #include <unistd.h>
11 #include <errno.h>
12 #include <assert.h>
13 #include <libudev.h>
14
15 #include "checkers.h"
16 #include "vector.h"
17 #include "structs.h"
18 #include "structs_vec.h"
19 #include "dmparser.h"
20 #include "config.h"
21 #include "configure.h"
22 #include "pgpolicies.h"
23 #include "print.h"
24 #include "defaults.h"
25 #include "parser.h"
26 #include "blacklist.h"
27 #include "switchgroup.h"
28 #include "devmapper.h"
29 #include "uevent.h"
30 #include "debug.h"
31 #include "discovery.h"
32 #include "util.h"
33 #include "foreign.h"
34 #include "strbuf.h"
35
36 #define PRINT_PATH_LONG      "%w %i %d %D %p %t %T %s %o"
37 #define PRINT_PATH_INDENT    "%i %d %D %t %T %o"
38 #define PRINT_MAP_PROPS      "size=%S features='%f' hwhandler='%h' wp=%r"
39 #define PRINT_PG_INDENT      "policy='%s' prio=%p status=%t"
40
41 #define PRINT_JSON_MULTIPLIER     5
42 #define PRINT_JSON_MAJOR_VERSION  0
43 #define PRINT_JSON_MINOR_VERSION  1
44 #define PRINT_JSON_START_VERSION  "   \"major_version\": %d,\n" \
45                                   "   \"minor_version\": %d,\n"
46 #define PRINT_JSON_START_ELEM     "{\n"
47 #define PRINT_JSON_START_MAP      "   \"map\":"
48 #define PRINT_JSON_START_MAPS     "\"maps\": ["
49 #define PRINT_JSON_START_PATHS    "\"paths\": ["
50 #define PRINT_JSON_START_GROUPS   "\"path_groups\": ["
51 #define PRINT_JSON_END_ELEM       "},"
52 #define PRINT_JSON_END_LAST_ELEM  "}"
53 #define PRINT_JSON_END_LAST       "}\n"
54 #define PRINT_JSON_END_ARRAY      "]\n"
55 #define PRINT_JSON_INDENT_N    3
56 #define PRINT_JSON_MAP       "{\n" \
57                              "      \"name\" : \"%n\",\n" \
58                              "      \"uuid\" : \"%w\",\n" \
59                              "      \"sysfs\" : \"%d\",\n" \
60                              "      \"failback\" : \"%F\",\n" \
61                              "      \"queueing\" : \"%Q\",\n" \
62                              "      \"paths\" : %N,\n" \
63                              "      \"write_prot\" : \"%r\",\n" \
64                              "      \"dm_st\" : \"%t\",\n" \
65                              "      \"features\" : \"%f\",\n" \
66                              "      \"hwhandler\" : \"%h\",\n" \
67                              "      \"action\" : \"%A\",\n" \
68                              "      \"path_faults\" : %0,\n" \
69                              "      \"vend\" : \"%v\",\n" \
70                              "      \"prod\" : \"%p\",\n" \
71                              "      \"rev\" : \"%e\",\n" \
72                              "      \"switch_grp\" : %1,\n" \
73                              "      \"map_loads\" : %2,\n" \
74                              "      \"total_q_time\" : %3,\n" \
75                              "      \"q_timeouts\" : %4,"
76
77 #define PRINT_JSON_GROUP     "{\n" \
78                              "         \"selector\" : \"%s\",\n" \
79                              "         \"pri\" : %p,\n" \
80                              "         \"dm_st\" : \"%t\",\n" \
81                              "         \"marginal_st\" : \"%M\","
82
83 #define PRINT_JSON_GROUP_NUM "         \"group\" : %d,\n"
84
85 #define PRINT_JSON_PATH      "{\n" \
86                              "            \"dev\" : \"%d\",\n"\
87                              "            \"dev_t\" : \"%D\",\n" \
88                              "            \"dm_st\" : \"%t\",\n" \
89                              "            \"dev_st\" : \"%o\",\n" \
90                              "            \"chk_st\" : \"%T\",\n" \
91                              "            \"checker\" : \"%c\",\n" \
92                              "            \"pri\" : %p,\n" \
93                              "            \"host_wwnn\" : \"%N\",\n" \
94                              "            \"target_wwnn\" : \"%n\",\n" \
95                              "            \"host_wwpn\" : \"%R\",\n" \
96                              "            \"target_wwpn\" : \"%r\",\n" \
97                              "            \"host_adapter\" : \"%a\",\n" \
98                              "            \"lun_hex\" : \"%L\",\n" \
99                              "            \"marginal_st\" : \"%M\""
100
101 #define PROGRESS_LEN  10
102
103 struct path_data {
104         char wildcard;
105         char * header;
106         int (*snprint)(struct strbuf *, const struct path * pp);
107 };
108
109 struct multipath_data {
110         char wildcard;
111         char * header;
112         int (*snprint)(struct strbuf *, const struct multipath * mpp);
113 };
114
115 struct pathgroup_data {
116         char wildcard;
117         char * header;
118         int (*snprint)(struct strbuf *, const struct pathgroup * pgp);
119 };
120
121 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
122 #define MIN(x,y) (((x) > (y)) ? (y) : (x))
123 /*
124  * information printing helpers
125  */
126 static int
127 snprint_str(struct strbuf *buff, const char *str)
128 {
129         return append_strbuf_str(buff, str);
130 }
131
132 static int
133 snprint_int (struct strbuf *buff, int val)
134 {
135         return print_strbuf(buff, "%i", val);
136 }
137
138 static int
139 snprint_uint (struct strbuf *buff, unsigned int val)
140 {
141         return print_strbuf(buff, "%u", val);
142 }
143
144 static int
145 snprint_size (struct strbuf *buff, unsigned long long size)
146 {
147         float s = (float)(size >> 1); /* start with KB */
148         char units[] = {'K','M','G','T','P'};
149         char *u = units;
150
151         while (s >= 1024 && *u != 'P') {
152                 s = s / 1024;
153                 u++;
154         }
155
156         return print_strbuf(buff, "%.*f%c", s < 10, s, *u);
157 }
158
159 /*
160  * multipath info printing functions
161  */
162 static int
163 snprint_name (struct strbuf *buff, const struct multipath * mpp)
164 {
165         if (mpp->alias)
166                 return append_strbuf_str(buff, mpp->alias);
167         else
168                 return append_strbuf_str(buff, mpp->wwid);
169 }
170
171 static int
172 snprint_sysfs (struct strbuf *buff, const struct multipath * mpp)
173 {
174         if (has_dm_info(mpp))
175                 return print_strbuf(buff, "dm-%i", mpp->dmi.minor);
176         else
177                 return append_strbuf_str(buff, "undef");
178 }
179
180 static int
181 snprint_ro (struct strbuf *buff, const struct multipath * mpp)
182 {
183         if (!has_dm_info(mpp))
184                 return append_strbuf_str(buff, "undef");
185         if (mpp->dmi.read_only)
186                 return append_strbuf_str(buff, "ro");
187         else
188                 return append_strbuf_str(buff, "rw");
189 }
190
191 static int
192 snprint_progress (struct strbuf *buff, int cur, int total)
193 {
194         size_t initial_len = get_strbuf_len(buff);
195         int rc;
196
197         if (total > 0) {
198                 int i = PROGRESS_LEN * cur / total;
199                 int j = PROGRESS_LEN - i;
200
201                 if ((rc = fill_strbuf(buff, 'X', i)) < 0 ||
202                     (rc = fill_strbuf(buff, '.', j) < 0)) {
203                         truncate_strbuf(buff, initial_len);
204                         return rc;
205                 }
206         }
207
208         if ((rc = print_strbuf(buff, " %i/%i", cur, total)) < 0)
209                 return rc;
210         return get_strbuf_len(buff) - initial_len;
211 }
212
213 static int
214 snprint_failback (struct strbuf *buff, const struct multipath * mpp)
215 {
216         if (mpp->pgfailback == -FAILBACK_IMMEDIATE)
217                 return append_strbuf_str(buff, "immediate");
218         if (mpp->pgfailback == -FAILBACK_FOLLOWOVER)
219                 return append_strbuf_str(buff, "followover");
220
221         if (!mpp->failback_tick)
222                 return append_strbuf_str(buff, "-");
223         else
224                 return snprint_progress(buff, mpp->failback_tick,
225                                         mpp->pgfailback);
226 }
227
228 static int
229 snprint_queueing (struct strbuf *buff, const struct multipath * mpp)
230 {
231         if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
232                 return append_strbuf_str(buff, "off");
233         else if (mpp->no_path_retry == NO_PATH_RETRY_QUEUE)
234                 return append_strbuf_str(buff, "on");
235         else if (mpp->no_path_retry == NO_PATH_RETRY_UNDEF)
236                 return append_strbuf_str(buff, "-");
237         else if (mpp->no_path_retry > 0) {
238                 if (mpp->retry_tick > 0)
239
240                         return print_strbuf(buff, "%i sec", mpp->retry_tick);
241                 else if (mpp->retry_tick == 0 && count_active_paths(mpp) > 0)
242                         return print_strbuf(buff, "%i chk",
243                                             mpp->no_path_retry);
244                 else
245                         return append_strbuf_str(buff, "off");
246         }
247         return 0;
248 }
249
250 static int
251 snprint_nb_paths (struct strbuf *buff, const struct multipath * mpp)
252 {
253         return snprint_int(buff, count_active_paths(mpp));
254 }
255
256 static int
257 snprint_dm_map_state (struct strbuf *buff, const struct multipath * mpp)
258 {
259         if (!has_dm_info(mpp))
260                 return append_strbuf_str(buff, "undef");
261         else if (mpp->dmi.suspended)
262                 return append_strbuf_str(buff, "suspend");
263         else
264                 return append_strbuf_str(buff, "active");
265 }
266
267 static int
268 snprint_multipath_size (struct strbuf *buff, const struct multipath * mpp)
269 {
270         return snprint_size(buff, mpp->size);
271 }
272
273 static int
274 snprint_features (struct strbuf *buff, const struct multipath * mpp)
275 {
276         return snprint_str(buff, mpp->features);
277 }
278
279 static int
280 snprint_hwhandler (struct strbuf *buff, const struct multipath * mpp)
281 {
282         return snprint_str(buff, mpp->hwhandler);
283 }
284
285 static int
286 snprint_path_faults (struct strbuf *buff, const struct multipath * mpp)
287 {
288         return snprint_uint(buff, mpp->stat_path_failures);
289 }
290
291 static int
292 snprint_switch_grp (struct strbuf *buff, const struct multipath * mpp)
293 {
294         return snprint_uint(buff, mpp->stat_switchgroup);
295 }
296
297 static int
298 snprint_map_loads (struct strbuf *buff, const struct multipath * mpp)
299 {
300         return snprint_uint(buff, mpp->stat_map_loads);
301 }
302
303 static int
304 snprint_total_q_time (struct strbuf *buff, const struct multipath * mpp)
305 {
306         return snprint_uint(buff, mpp->stat_total_queueing_time);
307 }
308
309 static int
310 snprint_q_timeouts (struct strbuf *buff, const struct multipath * mpp)
311 {
312         return snprint_uint(buff, mpp->stat_queueing_timeouts);
313 }
314
315 static int
316 snprint_map_failures (struct strbuf *buff, const struct multipath * mpp)
317 {
318         return snprint_uint(buff, mpp->stat_map_failures);
319 }
320
321 static int
322 snprint_multipath_uuid (struct strbuf *buff, const struct multipath * mpp)
323 {
324         return snprint_str(buff, mpp->wwid);
325 }
326
327 static int
328 snprint_multipath_vpr (struct strbuf *buff, const struct multipath * mpp)
329 {
330         struct pathgroup * pgp;
331         struct path * pp;
332         int i, j;
333
334         vector_foreach_slot(mpp->pg, pgp, i) {
335                 vector_foreach_slot(pgp->paths, pp, j) {
336                         if (strlen(pp->vendor_id) && strlen(pp->product_id))
337                                 return print_strbuf(buff, "%s,%s",
338                                                     pp->vendor_id, pp->product_id);
339                 }
340         }
341         return append_strbuf_str(buff, "##,##");
342 }
343
344
345 static int
346 snprint_multipath_vend (struct strbuf *buff, const struct multipath * mpp)
347 {
348         struct pathgroup * pgp;
349         struct path * pp;
350         int i, j;
351
352         vector_foreach_slot(mpp->pg, pgp, i) {
353                 vector_foreach_slot(pgp->paths, pp, j) {
354                         if (strlen(pp->vendor_id))
355                                 return append_strbuf_str(buff, pp->vendor_id);
356                 }
357         }
358         return append_strbuf_str(buff, "##");
359 }
360
361 static int
362 snprint_multipath_prod (struct strbuf *buff, const struct multipath * mpp)
363 {
364         struct pathgroup * pgp;
365         struct path * pp;
366         int i, j;
367
368         vector_foreach_slot(mpp->pg, pgp, i) {
369                 vector_foreach_slot(pgp->paths, pp, j) {
370                         if (strlen(pp->product_id))
371                                 return append_strbuf_str(buff, pp->product_id);
372                 }
373         }
374         return append_strbuf_str(buff, "##");
375 }
376
377 static int
378 snprint_multipath_rev (struct strbuf *buff, const struct multipath * mpp)
379 {
380         struct pathgroup * pgp;
381         struct path * pp;
382         int i, j;
383
384         vector_foreach_slot(mpp->pg, pgp, i) {
385                 vector_foreach_slot(pgp->paths, pp, j) {
386                         if (strlen(pp->rev))
387                                 return append_strbuf_str(buff, pp->rev);
388                 }
389         }
390         return append_strbuf_str(buff, "##");
391 }
392
393 static int
394 snprint_multipath_foreign (struct strbuf *buff,
395                            __attribute__((unused)) const struct multipath * pp)
396 {
397         return append_strbuf_str(buff, "--");
398 }
399
400 static int
401 snprint_action (struct strbuf *buff, const struct multipath * mpp)
402 {
403         switch (mpp->action) {
404         case ACT_REJECT:
405                 return snprint_str(buff, ACT_REJECT_STR);
406         case ACT_RENAME:
407                 return snprint_str(buff, ACT_RENAME_STR);
408         case ACT_RELOAD:
409                 return snprint_str(buff, ACT_RELOAD_STR);
410         case ACT_CREATE:
411                 return snprint_str(buff, ACT_CREATE_STR);
412         case ACT_SWITCHPG:
413                 return snprint_str(buff, ACT_SWITCHPG_STR);
414         default:
415                 return 0;
416         }
417 }
418
419 static int
420 snprint_multipath_vpd_data(struct strbuf *buff,
421                            const struct multipath * mpp)
422 {
423         struct pathgroup * pgp;
424         struct path * pp;
425         int i, j;
426
427         vector_foreach_slot(mpp->pg, pgp, i)
428                 vector_foreach_slot(pgp->paths, pp, j)
429                         if (pp->vpd_data)
430                                 return append_strbuf_str(buff, pp->vpd_data);
431         return append_strbuf_str(buff, "[undef]");
432 }
433
434 /*
435  * path info printing functions
436  */
437 static int
438 snprint_path_uuid (struct strbuf *buff, const struct path * pp)
439 {
440         return snprint_str(buff, pp->wwid);
441 }
442
443 static int
444 snprint_hcil (struct strbuf *buff, const struct path * pp)
445 {
446         if (!pp || pp->sg_id.host_no < 0)
447                 return append_strbuf_str(buff, "#:#:#:#");
448
449         return print_strbuf(buff, "%i:%i:%i:%" PRIu64,
450                         pp->sg_id.host_no,
451                         pp->sg_id.channel,
452                         pp->sg_id.scsi_id,
453                         pp->sg_id.lun);
454 }
455
456
457 static int
458 snprint_path_lunhex (struct strbuf *buff, const struct path * pp)
459 {
460         uint64_t lunhex = SCSI_INVALID_LUN, scsilun;
461
462         if (!pp || pp->sg_id.host_no < 0)
463                 return print_strbuf(buff, "0x%016" PRIx64, lunhex);
464
465         scsilun = pp->sg_id.lun;
466         /* cf. Linux kernel function int_to_scsilun() */
467         lunhex = ((scsilun & 0x000000000000ffffULL) << 48) |
468                 ((scsilun & 0x00000000ffff0000ULL) << 16) |
469                 ((scsilun & 0x0000ffff00000000ULL) >> 16) |
470                 ((scsilun & 0xffff000000000000ULL) >> 48);
471         return print_strbuf(buff, "0x%016" PRIx64, lunhex);
472 }
473
474 static int
475 snprint_dev (struct strbuf *buff, const struct path * pp)
476 {
477         if (!pp || !strlen(pp->dev))
478                 return append_strbuf_str(buff, "-");
479         else
480                 return snprint_str(buff, pp->dev);
481 }
482
483 static int
484 snprint_dev_t (struct strbuf *buff, const struct path * pp)
485 {
486         if (!pp || !strlen(pp->dev))
487                 return append_strbuf_str(buff, "#:#");
488         else
489                 return snprint_str(buff, pp->dev_t);
490 }
491
492 static int
493 snprint_offline (struct strbuf *buff, const struct path * pp)
494 {
495         if (!pp || !pp->mpp)
496                 return append_strbuf_str(buff, "unknown");
497         else if (pp->offline)
498                 return append_strbuf_str(buff, "offline");
499         else
500                 return append_strbuf_str(buff, "running");
501 }
502
503 static int
504 snprint_chk_state (struct strbuf *buff, const struct path * pp)
505 {
506         if (!pp || !pp->mpp)
507                 return append_strbuf_str(buff, "undef");
508
509         switch (pp->state) {
510         case PATH_UP:
511                 return append_strbuf_str(buff, "ready");
512         case PATH_DOWN:
513                 return append_strbuf_str(buff, "faulty");
514         case PATH_SHAKY:
515                 return append_strbuf_str(buff, "shaky");
516         case PATH_GHOST:
517                 return append_strbuf_str(buff, "ghost");
518         case PATH_PENDING:
519                 return append_strbuf_str(buff, "i/o pending");
520         case PATH_TIMEOUT:
521                 return append_strbuf_str(buff, "i/o timeout");
522         case PATH_DELAYED:
523                 return append_strbuf_str(buff, "delayed");
524         default:
525                 return append_strbuf_str(buff, "undef");
526         }
527 }
528
529 static int
530 snprint_dm_path_state (struct strbuf *buff, const struct path * pp)
531 {
532         if (!pp)
533                 return append_strbuf_str(buff, "undef");
534
535         switch (pp->dmstate) {
536         case PSTATE_ACTIVE:
537                 return append_strbuf_str(buff, "active");
538         case PSTATE_FAILED:
539                 return append_strbuf_str(buff, "failed");
540         default:
541                 return append_strbuf_str(buff, "undef");
542         }
543 }
544
545 static int snprint_initialized(struct strbuf *buff, const struct path * pp)
546 {
547         static const char *init_state_name[] = {
548                 [INIT_NEW] = "new",
549                 [INIT_FAILED] = "failed",
550                 [INIT_MISSING_UDEV] = "udev-missing",
551                 [INIT_REQUESTED_UDEV] = "udev-requested",
552                 [INIT_OK] = "ok",
553                 [INIT_REMOVED] = "removed",
554                 [INIT_PARTIAL] = "partial",
555         };
556         const char *str;
557
558         if (pp->initialized < INIT_NEW || pp->initialized >= __INIT_LAST)
559                 str = "undef";
560         else
561                 str = init_state_name[pp->initialized];
562         return append_strbuf_str(buff, str);
563 }
564
565 static int
566 snprint_vpr (struct strbuf *buff, const struct path * pp)
567 {
568         return print_strbuf(buff, "%s,%s", pp->vendor_id, pp->product_id);
569 }
570
571 static int
572 snprint_next_check (struct strbuf *buff, const struct path * pp)
573 {
574         if (!pp || !pp->mpp)
575                 return append_strbuf_str(buff, "orphan");
576
577         return snprint_progress(buff, pp->tick, pp->checkint);
578 }
579
580 static int
581 snprint_pri (struct strbuf *buff, const struct path * pp)
582 {
583         return snprint_int(buff, pp ? pp->priority : -1);
584 }
585
586 static int
587 snprint_pg_selector (struct strbuf *buff, const struct pathgroup * pgp)
588 {
589         const char *s = pgp->mpp->selector;
590
591         return snprint_str(buff, s ? s : "");
592 }
593
594 static int
595 snprint_pg_pri (struct strbuf *buff, const struct pathgroup * pgp)
596 {
597         return snprint_int(buff, pgp->priority);
598 }
599
600 static int
601 snprint_pg_state (struct strbuf *buff, const struct pathgroup * pgp)
602 {
603         switch (pgp->status) {
604         case PGSTATE_ENABLED:
605                 return append_strbuf_str(buff, "enabled");
606         case PGSTATE_DISABLED:
607                 return append_strbuf_str(buff, "disabled");
608         case PGSTATE_ACTIVE:
609                 return append_strbuf_str(buff, "active");
610         default:
611                 return append_strbuf_str(buff, "undef");
612         }
613 }
614
615 static int
616 snprint_pg_marginal (struct strbuf *buff, const struct pathgroup * pgp)
617 {
618         if (pgp->marginal)
619                 return append_strbuf_str(buff, "marginal");
620         return append_strbuf_str(buff, "normal");
621 }
622
623 static int
624 snprint_path_size (struct strbuf *buff, const struct path * pp)
625 {
626         return snprint_size(buff, pp->size);
627 }
628
629 int
630 snprint_path_serial (struct strbuf *buff, const struct path * pp)
631 {
632         return snprint_str(buff, pp->serial);
633 }
634
635 static int
636 snprint_path_mpp (struct strbuf *buff, const struct path * pp)
637 {
638         if (!pp->mpp)
639                 return append_strbuf_str(buff, "[orphan]");
640         if (!pp->mpp->alias)
641                 return append_strbuf_str(buff, "[unknown]");
642         return snprint_str(buff, pp->mpp->alias);
643 }
644
645 static int
646 snprint_host_attr (struct strbuf *buff, const struct path * pp, char *attr)
647 {
648         struct udev_device *host_dev = NULL;
649         char host_id[32];
650         const char *value = NULL;
651         int ret;
652
653         if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
654                 return append_strbuf_str(buff, "[undef]");
655         sprintf(host_id, "host%d", pp->sg_id.host_no);
656         host_dev = udev_device_new_from_subsystem_sysname(udev, "fc_host",
657                                                           host_id);
658         if (!host_dev) {
659                 condlog(1, "%s: No fc_host device for '%s'", pp->dev, host_id);
660                 goto out;
661         }
662         value = udev_device_get_sysattr_value(host_dev, attr);
663         if (value)
664                 ret = snprint_str(buff, value);
665         udev_device_unref(host_dev);
666 out:
667         if (!value)
668                 ret = append_strbuf_str(buff, "[unknown]");
669         return ret;
670 }
671
672 int
673 snprint_host_wwnn (struct strbuf *buff, const struct path * pp)
674 {
675         return snprint_host_attr(buff, pp, "node_name");
676 }
677
678 int
679 snprint_host_wwpn (struct strbuf *buff, const struct path * pp)
680 {
681         return snprint_host_attr(buff, pp, "port_name");
682 }
683
684 int
685 snprint_tgt_wwpn (struct strbuf *buff, const struct path * pp)
686 {
687         struct udev_device *rport_dev = NULL;
688         char rport_id[42];
689         const char *value = NULL;
690         int ret;
691
692         if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
693                 return append_strbuf_str(buff, "[undef]");
694         sprintf(rport_id, "rport-%d:%d-%d",
695                 pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
696         rport_dev = udev_device_new_from_subsystem_sysname(udev,
697                                 "fc_remote_ports", rport_id);
698         if (!rport_dev) {
699                 condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev,
700                         rport_id);
701                 goto out;
702         }
703         value = udev_device_get_sysattr_value(rport_dev, "port_name");
704         if (value)
705                 ret = snprint_str(buff, value);
706         udev_device_unref(rport_dev);
707 out:
708         if (!value)
709                 ret = append_strbuf_str(buff, "[unknown]");
710         return ret;
711 }
712
713
714 int
715 snprint_tgt_wwnn (struct strbuf *buff, const struct path * pp)
716 {
717         if (pp->tgt_node_name[0] == '\0')
718                 return append_strbuf_str(buff, "[undef]");
719         return snprint_str(buff, pp->tgt_node_name);
720 }
721
722 static int
723 snprint_host_adapter (struct strbuf *buff, const struct path * pp)
724 {
725         char adapter[SLOT_NAME_SIZE];
726
727         if (sysfs_get_host_adapter_name(pp, adapter))
728                 return append_strbuf_str(buff, "[undef]");
729         return snprint_str(buff, adapter);
730 }
731
732 static int
733 snprint_path_checker (struct strbuf *buff, const struct path * pp)
734 {
735         const struct checker * c = &pp->checker;
736         return snprint_str(buff, checker_name(c));
737 }
738
739 static int
740 snprint_path_foreign (struct strbuf *buff,
741                       __attribute__((unused)) const struct path * pp)
742 {
743         return append_strbuf_str(buff, "--");
744 }
745
746 static int
747 snprint_path_failures(struct strbuf *buff, const struct path * pp)
748 {
749         return snprint_int(buff, pp->failcount);
750 }
751
752 /* if you add a protocol string bigger than "scsi:unspec" you must
753  * also change PROTOCOL_BUF_SIZE */
754 int
755 snprint_path_protocol(struct strbuf *buff, const struct path * pp)
756 {
757         static const char * const protocol_name[LAST_BUS_PROTOCOL_ID + 1] = {
758                 [SYSFS_BUS_UNDEF] = "undef",
759                 [SYSFS_BUS_CCW] = "ccw",
760                 [SYSFS_BUS_CCISS] = "cciss",
761                 [SYSFS_BUS_NVME] = "nvme",
762                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_FCP] = "scsi:fcp",
763                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SPI] = "scsi:spi",
764                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SSA] = "scsi:ssa",
765                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SBP] = "scsi:sbp",
766                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SRP] = "scsi:srp",
767                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ISCSI] = "scsi:iscsi",
768                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_SAS] = "scsi:sas",
769                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ADT] = "scsi:adt",
770                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_ATA] = "scsi:ata",
771                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_USB] = "scsi:usb",
772                 [SYSFS_BUS_SCSI + SCSI_PROTOCOL_UNSPEC] = "scsi:unspec",
773         };
774         const char *pn = protocol_name[bus_protocol_id(pp)];
775
776         assert(pn != NULL);
777         return append_strbuf_str(buff, pn);
778 }
779
780 static int
781 snprint_path_marginal(struct strbuf *buff, const struct path * pp)
782 {
783         if (pp->marginal)
784                 return append_strbuf_str(buff, "marginal");
785         return append_strbuf_str(buff, "normal");
786 }
787
788 static int
789 snprint_path_vpd_data(struct strbuf *buff, const struct path * pp)
790 {
791         if (pp->vpd_data)
792                 return append_strbuf_str(buff, pp->vpd_data);
793         return append_strbuf_str(buff, "[undef]");
794 }
795
796 static const struct multipath_data mpd[] = {
797         {'n', "name",          snprint_name},
798         {'w', "uuid",          snprint_multipath_uuid},
799         {'d', "sysfs",         snprint_sysfs},
800         {'F', "failback",      snprint_failback},
801         {'Q', "queueing",      snprint_queueing},
802         {'N', "paths",         snprint_nb_paths},
803         {'r', "write_prot",    snprint_ro},
804         {'t', "dm-st",         snprint_dm_map_state},
805         {'S', "size",          snprint_multipath_size},
806         {'f', "features",      snprint_features},
807         {'x', "failures",      snprint_map_failures},
808         {'h', "hwhandler",     snprint_hwhandler},
809         {'A', "action",        snprint_action},
810         {'0', "path_faults",   snprint_path_faults},
811         {'1', "switch_grp",    snprint_switch_grp},
812         {'2', "map_loads",     snprint_map_loads},
813         {'3', "total_q_time",  snprint_total_q_time},
814         {'4', "q_timeouts",    snprint_q_timeouts},
815         {'s', "vend/prod/rev", snprint_multipath_vpr},
816         {'v', "vend",          snprint_multipath_vend},
817         {'p', "prod",          snprint_multipath_prod},
818         {'e', "rev",           snprint_multipath_rev},
819         {'G', "foreign",       snprint_multipath_foreign},
820         {'g', "vpd page data", snprint_multipath_vpd_data},
821 };
822
823 static const struct path_data pd[] = {
824         {'w', "uuid",          snprint_path_uuid},
825         {'i', "hcil",          snprint_hcil},
826         {'d', "dev",           snprint_dev},
827         {'D', "dev_t",         snprint_dev_t},
828         {'t', "dm_st",         snprint_dm_path_state},
829         {'o', "dev_st",        snprint_offline},
830         {'T', "chk_st",        snprint_chk_state},
831         {'s', "vend/prod/rev", snprint_vpr},
832         {'c', "checker",       snprint_path_checker},
833         {'C', "next_check",    snprint_next_check},
834         {'p', "pri",           snprint_pri},
835         {'S', "size",          snprint_path_size},
836         {'z', "serial",        snprint_path_serial},
837         {'M', "marginal_st",   snprint_path_marginal},
838         {'m', "multipath",     snprint_path_mpp},
839         {'N', "host WWNN",     snprint_host_wwnn},
840         {'n', "target WWNN",   snprint_tgt_wwnn},
841         {'R', "host WWPN",     snprint_host_wwpn},
842         {'r', "target WWPN",   snprint_tgt_wwpn},
843         {'a', "host adapter",  snprint_host_adapter},
844         {'G', "foreign",       snprint_path_foreign},
845         {'g', "vpd page data", snprint_path_vpd_data},
846         {'0', "failures",      snprint_path_failures},
847         {'P', "protocol",      snprint_path_protocol},
848         {'I', "init_st",       snprint_initialized},
849         {'L', "LUN hex",       snprint_path_lunhex},
850 };
851
852 static const struct pathgroup_data pgd[] = {
853         {'s', "selector",      snprint_pg_selector},
854         {'p', "pri",           snprint_pg_pri},
855         {'t', "dm_st",         snprint_pg_state},
856         {'M', "marginal_st",   snprint_pg_marginal},
857 };
858
859 int snprint_wildcards(struct strbuf *buff)
860 {
861         int initial_len = get_strbuf_len(buff);
862         unsigned int i;
863         int rc;
864
865         if ((rc = append_strbuf_str(buff, "multipath format wildcards:\n")) < 0)
866                 return rc;
867         for (i = 0; i < ARRAY_SIZE(mpd); i++)
868                 if ((rc = print_strbuf(buff, "%%%c  %s\n",
869                                        mpd[i].wildcard, mpd[i].header)) < 0)
870                         return rc;
871
872         if ((rc = append_strbuf_str(buff, "\npath format wildcards:\n")) < 0)
873                 return rc;
874         for (i = 0; i < ARRAY_SIZE(pd); i++)
875                 if ((rc = print_strbuf(buff, "%%%c  %s\n",
876                                        pd[i].wildcard, pd[i].header)) < 0)
877                         return rc;
878
879         if ((rc = append_strbuf_str(buff, "\npathgroup format wildcards:\n")) < 0)
880                 return rc;
881         for (i = 0; i < ARRAY_SIZE(pgd); i++)
882                 if ((rc = print_strbuf(buff, "%%%c  %s\n",
883                                        pgd[i].wildcard, pgd[i].header)) < 0)
884                         return rc;
885
886         return get_strbuf_len(buff) - initial_len;
887 }
888
889 fieldwidth_t *alloc_path_layout(void) {
890         return calloc(ARRAY_SIZE(pd), sizeof(fieldwidth_t));
891 }
892
893 void get_path_layout(vector pathvec, int header, fieldwidth_t *width)
894 {
895         vector gpvec = vector_convert(NULL, pathvec, struct path,
896                                       dm_path_to_gen);
897         _get_path_layout(gpvec,
898                          header ? LAYOUT_RESET_HEADER : LAYOUT_RESET_ZERO,
899                          width);
900         vector_free(gpvec);
901 }
902
903 static void
904 reset_width(fieldwidth_t *width, enum layout_reset reset, const char *header)
905 {
906         switch (reset) {
907         case LAYOUT_RESET_HEADER:
908                 *width = strlen(header);
909                 break;
910         case LAYOUT_RESET_ZERO:
911                 *width = 0;
912                 break;
913         default:
914                 /* don't reset */
915                 break;
916         }
917 }
918
919 void _get_path_layout (const struct _vector *gpvec, enum layout_reset reset,
920                        fieldwidth_t *width)
921 {
922         unsigned int i, j;
923         const struct gen_path *gp;
924
925         if (width == NULL)
926                 return;
927
928         for (j = 0; j < ARRAY_SIZE(pd); j++) {
929                 STRBUF_ON_STACK(buff);
930
931                 reset_width(&width[j], reset, pd[j].header);
932
933                 if (gpvec == NULL)
934                         continue;
935
936                 vector_foreach_slot (gpvec, gp, i) {
937                         gp->ops->snprint(gp, &buff, pd[j].wildcard);
938                         width[j] = MAX(width[j],
939                                        MIN(get_strbuf_len(&buff), MAX_FIELD_WIDTH));
940                         truncate_strbuf(&buff, 0);
941                 }
942         }
943 }
944
945 fieldwidth_t *alloc_multipath_layout(void) {
946
947         return calloc(ARRAY_SIZE(mpd), sizeof(fieldwidth_t));
948 }
949
950 void get_multipath_layout (vector mpvec, int header, fieldwidth_t *width) {
951         vector gmvec = vector_convert(NULL, mpvec, struct multipath,
952                                       dm_multipath_to_gen);
953         _get_multipath_layout(gmvec,
954                               header ? LAYOUT_RESET_HEADER : LAYOUT_RESET_ZERO,
955                               width);
956         vector_free(gmvec);
957 }
958
959 void
960 _get_multipath_layout (const struct _vector *gmvec, enum layout_reset reset,
961                        fieldwidth_t *width)
962 {
963         unsigned int i, j;
964         const struct gen_multipath * gm;
965
966         if (width == NULL)
967                 return;
968         for (j = 0; j < ARRAY_SIZE(mpd); j++) {
969                 STRBUF_ON_STACK(buff);
970
971                 reset_width(&width[j], reset, mpd[j].header);
972
973                 if (gmvec == NULL)
974                         continue;
975
976                 vector_foreach_slot (gmvec, gm, i) {
977                         gm->ops->snprint(gm, &buff, mpd[j].wildcard);
978                         width[j] = MAX(width[j],
979                                        MIN(get_strbuf_len(&buff), MAX_FIELD_WIDTH));
980                         truncate_strbuf(&buff, 0);
981                 }
982                 condlog(4, "%s: width %d", mpd[j].header, width[j]);
983         }
984 }
985
986 static int mpd_lookup(char wildcard)
987 {
988         unsigned int i;
989
990         for (i = 0; i < ARRAY_SIZE(mpd); i++)
991                 if (mpd[i].wildcard == wildcard)
992                         return i;
993
994         return -1;
995 }
996
997 int snprint_multipath_attr(const struct gen_multipath* gm,
998                            struct strbuf *buf, char wildcard)
999 {
1000         const struct multipath *mpp = gen_multipath_to_dm(gm);
1001         int i = mpd_lookup(wildcard);
1002
1003         if (i == -1)
1004                 return 0;
1005         return mpd[i].snprint(buf, mpp);
1006 }
1007
1008 static int pd_lookup(char wildcard)
1009 {
1010         unsigned int i;
1011
1012         for (i = 0; i < ARRAY_SIZE(pd); i++)
1013                 if (pd[i].wildcard == wildcard)
1014                         return i;
1015
1016         return -1;
1017 }
1018
1019 int snprint_path_attr(const struct gen_path* gp,
1020                       struct strbuf *buf, char wildcard)
1021 {
1022         const struct path *pp = gen_path_to_dm(gp);
1023         int i = pd_lookup(wildcard);
1024
1025         if (i == -1)
1026                 return 0;
1027         return pd[i].snprint(buf, pp);
1028 }
1029
1030 static int pgd_lookup(char wildcard)
1031 {
1032         unsigned int i;
1033
1034         for (i = 0; i < ARRAY_SIZE(pgd); i++)
1035                 if (pgd[i].wildcard == wildcard)
1036                         return i;
1037
1038         return -1;
1039 }
1040
1041 int snprint_pathgroup_attr(const struct gen_pathgroup* gpg,
1042                            struct strbuf *buf, char wildcard)
1043 {
1044         const struct pathgroup *pg = gen_pathgroup_to_dm(gpg);
1045         int i = pgd_lookup(wildcard);
1046
1047         if (i == -1)
1048                 return 0;
1049         return pgd[i].snprint(buf, pg);
1050 }
1051
1052 int snprint_multipath_header(struct strbuf *line, const char *format,
1053                              const fieldwidth_t *width)
1054 {
1055         int initial_len = get_strbuf_len(line);
1056         const char *f;
1057         const struct multipath_data * data;
1058         int rc;
1059
1060         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1061                 int iwc;
1062
1063                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1064                         return rc;
1065
1066                 format = f + 1;
1067                 if ((iwc = mpd_lookup(*format)) == -1)
1068                         continue; /* unknown wildcard */
1069                 data = &mpd[iwc];
1070
1071                 if ((rc = append_strbuf_str(line, data->header)) < 0)
1072                         return rc;
1073                 else if ((unsigned int)rc < width[iwc])
1074                         if ((rc = fill_strbuf(line, ' ', width[iwc] - rc)) < 0)
1075                                 return rc;
1076         }
1077
1078         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1079                 return rc;
1080         return get_strbuf_len(line) - initial_len;
1081 }
1082
1083 int _snprint_multipath(const struct gen_multipath *gmp,
1084                        struct strbuf *line, const char *format,
1085                        const fieldwidth_t *width)
1086 {
1087         int initial_len = get_strbuf_len(line);
1088         const char *f;
1089         int rc;
1090
1091         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1092                 int iwc;
1093
1094                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1095                         return rc;
1096
1097                 format = f + 1;
1098                 if ((iwc = mpd_lookup(*format)) == -1)
1099                         continue; /* unknown wildcard */
1100
1101                 if ((rc = gmp->ops->snprint(gmp, line, *format)) < 0)
1102                         return rc;
1103                 else if (width != NULL && (unsigned int)rc < width[iwc])
1104                         if ((rc = fill_strbuf(line, ' ', width[iwc] - rc)) < 0)
1105                                 return rc;
1106         }
1107
1108         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1109                 return rc;
1110         return get_strbuf_len(line) - initial_len;
1111 }
1112
1113 int snprint_path_header(struct strbuf *line, const char *format,
1114                         const fieldwidth_t *width)
1115 {
1116         int initial_len = get_strbuf_len(line);
1117         const char *f;
1118         const struct path_data *data;
1119         int rc;
1120
1121         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1122                 int iwc;
1123
1124                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1125                         return rc;
1126
1127                 format = f + 1;
1128                 if ((iwc = pd_lookup(*format)) == -1)
1129                         continue; /* unknown wildcard */
1130                 data = &pd[iwc];
1131
1132                 if ((rc = append_strbuf_str(line, data->header)) < 0)
1133                         return rc;
1134                 else if ((unsigned int)rc < width[iwc])
1135                         if ((rc = fill_strbuf(line, ' ', width[iwc] - rc)) < 0)
1136                                 return rc;
1137         }
1138
1139         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1140                 return rc;
1141         return get_strbuf_len(line) - initial_len;
1142 }
1143
1144 int _snprint_path(const struct gen_path *gp, struct strbuf *line,
1145                   const char *format, const fieldwidth_t *width)
1146 {
1147         int initial_len = get_strbuf_len(line);
1148         const char *f;
1149         int rc;
1150
1151         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1152                 int iwc;
1153
1154                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1155                         return rc;
1156
1157                 format = f + 1;
1158                 if ((iwc = pd_lookup(*format)) == -1)
1159                         continue; /* unknown wildcard */
1160
1161                 if ((rc = gp->ops->snprint(gp, line, *format)) < 0)
1162                         return rc;
1163                 else if (width != NULL && (unsigned int)rc < width[iwc])
1164                         if ((rc = fill_strbuf(line, ' ', width[iwc] - rc)) < 0)
1165                                 return rc;
1166         }
1167
1168         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1169                 return rc;
1170         return get_strbuf_len(line) - initial_len;
1171 }
1172
1173 int _snprint_pathgroup(const struct gen_pathgroup *ggp, struct strbuf *line,
1174                        const char *format)
1175 {
1176         int initial_len = get_strbuf_len(line);
1177         const char *f;
1178         int rc;
1179
1180         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1181                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1182                         return rc;
1183
1184                 format = f + 1;
1185
1186                 if ((rc = ggp->ops->snprint(ggp, line, *format)) < 0)
1187                         return rc;
1188         }
1189
1190         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1191                 return rc;
1192         return get_strbuf_len(line) - initial_len;
1193 }
1194
1195 #define snprint_pathgroup(line, fmt, pgp)                               \
1196         _snprint_pathgroup(dm_pathgroup_to_gen(pgp), line, fmt)
1197
1198 void _print_multipath_topology(const struct gen_multipath *gmp, int verbosity)
1199 {
1200         STRBUF_ON_STACK(buff);
1201         fieldwidth_t *p_width __attribute__((cleanup(cleanup_ucharp))) = NULL;
1202         const struct gen_pathgroup *gpg;
1203         const struct _vector *pgvec, *pathvec;
1204         int j;
1205
1206         p_width = alloc_path_layout();
1207         pgvec = gmp->ops->get_pathgroups(gmp);
1208
1209         if (pgvec != NULL) {
1210                 vector_foreach_slot (pgvec, gpg, j) {
1211                         pathvec = gpg->ops->get_paths(gpg);
1212                         if (pathvec == NULL)
1213                                 continue;
1214                         _get_path_layout(pathvec, LAYOUT_RESET_NOT, p_width);
1215                         gpg->ops->rel_paths(gpg, pathvec);
1216                 }
1217                 gmp->ops->rel_pathgroups(gmp, pgvec);
1218         }
1219
1220         _snprint_multipath_topology(gmp, &buff, verbosity, p_width);
1221         printf("%s", get_strbuf_str(&buff));
1222 }
1223
1224 int snprint_multipath_style(const struct gen_multipath *gmp,
1225                             struct strbuf *style, int verbosity)
1226 {
1227         const struct multipath *mpp = gen_multipath_to_dm(gmp);
1228         bool need_action = (verbosity > 1 &&
1229                             mpp->action != ACT_NOTHING &&
1230                             mpp->action != ACT_UNDEF &&
1231                             mpp->action != ACT_IMPOSSIBLE);
1232         bool need_wwid = (strncmp(mpp->alias, mpp->wwid, WWID_SIZE));
1233
1234         return print_strbuf(style, "%s%s%s%s",
1235                             need_action ? "%A: " : "", "%n",
1236                             need_wwid ? " (%w)" : "", " %d %s");
1237 }
1238
1239 int _snprint_multipath_topology(const struct gen_multipath *gmp,
1240                                 struct strbuf *buff, int verbosity,
1241                                 const fieldwidth_t *p_width)
1242 {
1243         int j, i, rc;
1244         const struct _vector *pgvec;
1245         const struct gen_pathgroup *gpg;
1246         STRBUF_ON_STACK(style);
1247         size_t initial_len = get_strbuf_len(buff);
1248         fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL;
1249
1250         if (verbosity <= 0)
1251                 return 0;
1252
1253         if ((width = alloc_multipath_layout()) == NULL)
1254                 return -ENOMEM;
1255
1256         if (verbosity == 1)
1257                 return _snprint_multipath(gmp, buff, "%n", width);
1258
1259         if(isatty(1) &&
1260            (rc = print_strbuf(&style, "%c[%dm", 0x1B, 1)) < 0) /* bold on */
1261                 return rc;
1262         if ((rc = gmp->ops->style(gmp, &style, verbosity)) < 0)
1263                 return rc;
1264         if(isatty(1) &&
1265            (rc = print_strbuf(&style, "%c[%dm", 0x1B, 0)) < 0) /* bold off */
1266                 return rc;
1267
1268         if ((rc = _snprint_multipath(gmp, buff, get_strbuf_str(&style), width)) < 0
1269             || (rc = _snprint_multipath(gmp, buff, PRINT_MAP_PROPS, width)) < 0)
1270                 return rc;
1271
1272         pgvec = gmp->ops->get_pathgroups(gmp);
1273         if (pgvec == NULL)
1274                 goto out;
1275
1276         vector_foreach_slot (pgvec, gpg, j) {
1277                 const struct _vector *pathvec;
1278                 struct gen_path *gp;
1279                 bool last_group = j + 1 == VECTOR_SIZE(pgvec);
1280
1281                 if ((rc = print_strbuf(buff, "%c-+- ",
1282                                        last_group ? '`' : '|')) < 0 ||
1283                     (rc = _snprint_pathgroup(gpg, buff, PRINT_PG_INDENT)) < 0)
1284                         return rc;
1285
1286                 pathvec = gpg->ops->get_paths(gpg);
1287                 if (pathvec == NULL)
1288                         continue;
1289
1290                 vector_foreach_slot (pathvec, gp, i) {
1291                         if ((rc = print_strbuf(buff, "%c %c- ",
1292                                                last_group ? ' ' : '|',
1293                                                i + 1 == VECTOR_SIZE(pathvec) ?
1294                                                '`': '|')) < 0 ||
1295                             (rc = _snprint_path(gp, buff,
1296                                                 PRINT_PATH_INDENT, p_width)) < 0)
1297                                 return rc;
1298                 }
1299                 gpg->ops->rel_paths(gpg, pathvec);
1300         }
1301
1302         gmp->ops->rel_pathgroups(gmp, pgvec);
1303 out:
1304         return get_strbuf_len(buff) - initial_len;
1305 }
1306
1307
1308 static int
1309 snprint_json(struct strbuf *buff, int indent, const char *json_str)
1310 {
1311         int rc;
1312
1313         if ((rc = fill_strbuf(buff, ' ', indent * PRINT_JSON_INDENT_N)) < 0)
1314                 return rc;
1315
1316         return append_strbuf_str(buff, json_str);
1317 }
1318
1319 static int snprint_json_header(struct strbuf *buff)
1320 {
1321         int rc;
1322
1323         if ((rc = snprint_json(buff, 0, PRINT_JSON_START_ELEM)) < 0)
1324                 return rc;
1325         return print_strbuf(buff, PRINT_JSON_START_VERSION,
1326                             PRINT_JSON_MAJOR_VERSION, PRINT_JSON_MINOR_VERSION);
1327 }
1328
1329 static int snprint_json_elem_footer(struct strbuf *buff, int indent, bool last)
1330 {
1331         int rc;
1332
1333         if ((rc = fill_strbuf(buff, ' ', indent * PRINT_JSON_INDENT_N)) < 0)
1334                 return rc;
1335
1336         if (last)
1337                 return append_strbuf_str(buff, PRINT_JSON_END_LAST_ELEM);
1338         else
1339                 return append_strbuf_str(buff, PRINT_JSON_END_ELEM);
1340 }
1341
1342 static int snprint_multipath_fields_json(struct strbuf *buff,
1343                                          const struct multipath *mpp, int last)
1344 {
1345         int i, j, rc;
1346         struct path *pp;
1347         struct pathgroup *pgp;
1348         size_t initial_len = get_strbuf_len(buff);
1349
1350         if ((rc = snprint_multipath(buff, PRINT_JSON_MAP, mpp, 0)) < 0 ||
1351             (rc = snprint_json(buff, 2, PRINT_JSON_START_GROUPS)) < 0)
1352                 return rc;
1353
1354         vector_foreach_slot (mpp->pg, pgp, i) {
1355
1356                 if ((rc = snprint_pathgroup(buff, PRINT_JSON_GROUP, pgp)) < 0 ||
1357                     (rc = print_strbuf(buff, PRINT_JSON_GROUP_NUM, i + 1)) < 0 ||
1358                     (rc = snprint_json(buff, 3, PRINT_JSON_START_PATHS)) < 0)
1359                         return rc;
1360
1361                 vector_foreach_slot (pgp->paths, pp, j) {
1362                         if ((rc = snprint_path(buff, PRINT_JSON_PATH,
1363                                                pp, 0)) < 0 ||
1364                             (rc = snprint_json_elem_footer(
1365                                     buff, 3,
1366                                     j + 1 == VECTOR_SIZE(pgp->paths))) < 0)
1367                                 return rc;
1368                 }
1369                 if ((rc = snprint_json(buff, 0, PRINT_JSON_END_ARRAY)) < 0 ||
1370                     (rc = snprint_json_elem_footer(
1371                             buff, 2, i + 1 == VECTOR_SIZE(mpp->pg))) < 0)
1372                         return rc;
1373         }
1374
1375         if ((rc = snprint_json(buff, 0, PRINT_JSON_END_ARRAY)) < 0 ||
1376             (rc = snprint_json_elem_footer(buff, 1, last)) < 0)
1377                 return rc;
1378
1379         return get_strbuf_len(buff) - initial_len;
1380 }
1381
1382 int snprint_multipath_map_json(struct strbuf *buff, const struct multipath * mpp)
1383 {
1384         size_t initial_len = get_strbuf_len(buff);
1385         int rc;
1386
1387         if ((rc = snprint_json_header(buff)) < 0 ||
1388             (rc = snprint_json(buff, 0, PRINT_JSON_START_MAP)) < 0)
1389                 return rc;
1390
1391         if ((rc = snprint_multipath_fields_json(buff, mpp, 1)) < 0)
1392                 return rc;
1393
1394         if ((rc = snprint_json(buff, 0, "\n")) < 0 ||
1395             (rc = snprint_json(buff, 0, PRINT_JSON_END_LAST)) < 0)
1396                 return rc;
1397
1398         return get_strbuf_len(buff) - initial_len;
1399 }
1400
1401 int snprint_multipath_topology_json (struct strbuf *buff,
1402                                      const struct vectors * vecs)
1403 {
1404         int i;
1405         struct multipath * mpp;
1406         size_t initial_len = get_strbuf_len(buff);
1407         int rc;
1408
1409         if ((rc = snprint_json_header(buff)) < 0 ||
1410             (rc = snprint_json(buff, 1, PRINT_JSON_START_MAPS)) < 0)
1411                 return rc;
1412
1413         vector_foreach_slot(vecs->mpvec, mpp, i) {
1414                 if ((rc = snprint_multipath_fields_json(
1415                              buff, mpp, i + 1 == VECTOR_SIZE(vecs->mpvec))) < 0)
1416                         return rc;
1417         }
1418
1419         if ((rc = snprint_json(buff, 0, PRINT_JSON_END_ARRAY)) < 0 ||
1420             (rc = snprint_json(buff, 0, PRINT_JSON_END_LAST)) < 0)
1421                 return rc;
1422
1423         return get_strbuf_len(buff) - initial_len;
1424 }
1425
1426 static int
1427 snprint_hwentry (const struct config *conf,
1428                  struct strbuf *buff, const struct hwentry * hwe)
1429 {
1430         int i, rc;
1431         struct keyword * kw;
1432         struct keyword * rootkw;
1433         size_t initial_len = get_strbuf_len(buff);
1434
1435         rootkw = find_keyword(conf->keywords, NULL, "devices");
1436         assert(rootkw && rootkw->sub);
1437         rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
1438         assert(rootkw);
1439
1440         if ((rc = append_strbuf_str(buff, "\tdevice {\n")) < 0)
1441                 return rc;
1442
1443         iterate_sub_keywords(rootkw, kw, i) {
1444                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n", kw, hwe)) < 0)
1445                         return rc;
1446         }
1447         if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
1448                 return rc;
1449         return get_strbuf_len(buff) - initial_len;
1450 }
1451
1452 static int snprint_hwtable(const struct config *conf, struct strbuf *buff,
1453                            const struct _vector *hwtable)
1454 {
1455         int i, rc;
1456         struct hwentry * hwe;
1457         struct keyword * rootkw;
1458         size_t initial_len = get_strbuf_len(buff);
1459
1460         rootkw = find_keyword(conf->keywords, NULL, "devices");
1461         assert(rootkw);
1462
1463         if ((rc = append_strbuf_str(buff, "devices {\n")) < 0)
1464                 return rc;
1465
1466         vector_foreach_slot (hwtable, hwe, i) {
1467                 if ((rc = snprint_hwentry(conf, buff, hwe)) < 0)
1468                         return rc;
1469         }
1470
1471         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1472                 return rc;
1473
1474         return get_strbuf_len(buff) - initial_len;
1475 }
1476
1477 static int
1478 snprint_mpentry (const struct config *conf, struct strbuf *buff,
1479                  const struct mpentry * mpe, const struct _vector *mpvec)
1480 {
1481         int i, rc;
1482         struct keyword * kw;
1483         struct keyword * rootkw;
1484         struct multipath *mpp = NULL;
1485         size_t initial_len = get_strbuf_len(buff);
1486
1487         if (mpvec != NULL && (mpp = find_mp_by_wwid(mpvec, mpe->wwid)) == NULL)
1488                 return 0;
1489
1490         rootkw = find_keyword(conf->keywords, NULL, "multipath");
1491         assert(rootkw);
1492
1493         if ((rc = append_strbuf_str(buff, "\tmultipath {\n")) < 0)
1494                 return rc;
1495
1496         iterate_sub_keywords(rootkw, kw, i) {
1497                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n", kw, mpe)) < 0)
1498                         return rc;
1499         }
1500         /*
1501          * This mpp doesn't have alias defined. Add the alias in a comment.
1502          */
1503         if (mpp != NULL && strcmp(mpp->alias, mpp->wwid) &&
1504             (rc = print_strbuf(buff, "\t\t# alias \"%s\"\n", mpp->alias)) < 0)
1505                 return rc;
1506
1507         if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
1508                 return rc;
1509
1510         return get_strbuf_len(buff) - initial_len;
1511 }
1512
1513 static int snprint_mptable(const struct config *conf, struct strbuf *buff,
1514                            const struct _vector *mpvec)
1515 {
1516         int i, rc;
1517         struct mpentry * mpe;
1518         struct keyword * rootkw;
1519         size_t initial_len = get_strbuf_len(buff);
1520
1521         rootkw = find_keyword(conf->keywords, NULL, "multipaths");
1522         assert(rootkw);
1523
1524         if ((rc = append_strbuf_str(buff, "multipaths {\n")) < 0)
1525                 return rc;
1526
1527         vector_foreach_slot (conf->mptable, mpe, i) {
1528                 if ((rc = snprint_mpentry(conf, buff, mpe, mpvec)) < 0)
1529                         return rc;
1530         }
1531         if (mpvec != NULL) {
1532                 struct multipath *mpp;
1533
1534                 vector_foreach_slot(mpvec, mpp, i) {
1535                         if (find_mpe(conf->mptable, mpp->wwid) != NULL)
1536                                 continue;
1537
1538                         if ((rc = print_strbuf(buff,
1539                                                "\tmultipath {\n\t\twwid \"%s\"\n",
1540                                                mpp->wwid)) < 0)
1541                                 return rc;
1542                         /*
1543                          * This mpp doesn't have alias defined in
1544                          * multipath.conf - otherwise find_mpe would have
1545                          * found it. Add the alias in a comment.
1546                          */
1547                         if (strcmp(mpp->alias, mpp->wwid) &&
1548                             (rc = print_strbuf(buff, "\t\t# alias \"%s\"\n",
1549                                                mpp->alias)) < 0)
1550                                 return rc;
1551                         if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
1552                                 return rc;
1553                 }
1554         }
1555         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1556                 return rc;
1557         return get_strbuf_len(buff) - initial_len;
1558 }
1559
1560 static int snprint_overrides(const struct config *conf, struct strbuf *buff,
1561                              const struct hwentry *overrides)
1562 {
1563         int i, rc;
1564         struct keyword *rootkw;
1565         struct keyword *kw;
1566         size_t initial_len = get_strbuf_len(buff);
1567
1568         rootkw = find_keyword(conf->keywords, NULL, "overrides");
1569         assert(rootkw);
1570
1571         if ((rc = append_strbuf_str(buff, "overrides {\n")) < 0)
1572                 return rc;
1573         if (!overrides)
1574                 goto out;
1575
1576         iterate_sub_keywords(rootkw, kw, i) {
1577                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, NULL)) < 0)
1578                         return rc;
1579         }
1580 out:
1581         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1582                 return rc;
1583         return get_strbuf_len(buff) - initial_len;
1584 }
1585
1586 static int snprint_defaults(const struct config *conf, struct strbuf *buff)
1587 {
1588         int i, rc;
1589         struct keyword *rootkw;
1590         struct keyword *kw;
1591         size_t initial_len = get_strbuf_len(buff);
1592
1593         rootkw = find_keyword(conf->keywords, NULL, "defaults");
1594         assert(rootkw);
1595
1596         if ((rc = append_strbuf_str(buff, "defaults {\n")) < 0)
1597                 return rc;
1598
1599         iterate_sub_keywords(rootkw, kw, i) {
1600                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, NULL)) < 0)
1601                         return rc;
1602         }
1603         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1604                 return rc;
1605         return get_strbuf_len(buff) - initial_len;
1606 }
1607
1608 static int snprint_blacklist_group(struct strbuf *buff, vector *vec)
1609 {
1610         struct blentry * ble;
1611         size_t initial_len = get_strbuf_len(buff);
1612         int rc, i;
1613
1614         if (!VECTOR_SIZE(*vec)) {
1615                 if ((rc = append_strbuf_str(buff, "        <empty>\n")) < 0)
1616                         return rc;
1617         } else vector_foreach_slot (*vec, ble, i) {
1618                 rc = print_strbuf(buff, "        %s %s\n",
1619                                    ble->origin == ORIGIN_CONFIG ?
1620                                    "(config file rule)" :
1621                                    "(default rule)    ", ble->str);
1622                 if (rc < 0)
1623                         return rc;
1624         }
1625
1626         return get_strbuf_len(buff) - initial_len;
1627 }
1628
1629 static int
1630 snprint_blacklist_devgroup (struct strbuf *buff, vector *vec)
1631 {
1632         struct blentry_device * bled;
1633         size_t initial_len = get_strbuf_len(buff);
1634         int rc, i;
1635
1636         if (!VECTOR_SIZE(*vec)) {
1637                 if ((rc = append_strbuf_str(buff, "        <empty>\n")) < 0)
1638                         return rc;
1639         } else vector_foreach_slot (*vec, bled, i) {
1640                 rc = print_strbuf(buff, "        %s %s:%s\n",
1641                                   bled->origin == ORIGIN_CONFIG ?
1642                                   "(config file rule)" :
1643                                   "(default rule)    ",
1644                                   bled->vendor, bled->product);
1645                 if (rc < 0)
1646                         return rc;
1647         }
1648
1649         return get_strbuf_len(buff) - initial_len;
1650 }
1651
1652 int snprint_blacklist_report(struct config *conf, struct strbuf *buff)
1653 {
1654         size_t initial_len = get_strbuf_len(buff);
1655         int rc;
1656
1657         if ((rc = append_strbuf_str(buff, "device node rules:\n- blacklist:\n")) < 0)
1658                 return rc;
1659         if ((rc = snprint_blacklist_group(buff, &conf->blist_devnode)) < 0)
1660                 return rc;
1661
1662         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1663                 return rc;
1664         if ((rc = snprint_blacklist_group(buff, &conf->elist_devnode)) < 0)
1665                 return rc;
1666
1667         if ((rc = append_strbuf_str(buff, "udev property rules:\n- blacklist:\n")) < 0)
1668                 return rc;
1669         if ((rc = snprint_blacklist_group(buff, &conf->blist_property)) < 0)
1670                 return rc;
1671
1672         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1673                 return rc;
1674         if ((rc = snprint_blacklist_group(buff, &conf->elist_property)) < 0)
1675                 return rc;
1676
1677         if ((rc = append_strbuf_str(buff, "protocol rules:\n- blacklist:\n")) < 0)
1678                 return rc;
1679         if ((rc = snprint_blacklist_group(buff, &conf->blist_protocol)) < 0)
1680                 return rc;
1681
1682         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1683                 return rc;
1684         if ((rc = snprint_blacklist_group(buff, &conf->elist_protocol)) < 0)
1685                 return rc;
1686
1687         if ((rc = append_strbuf_str(buff, "wwid rules:\n- blacklist:\n")) < 0)
1688                 return rc;
1689         if ((rc = snprint_blacklist_group(buff, &conf->blist_wwid)) < 0)
1690                 return rc;
1691
1692         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1693                 return rc;
1694         if ((rc = snprint_blacklist_group(buff, &conf->elist_wwid)) < 0)
1695                 return rc;
1696
1697         if ((rc = append_strbuf_str(buff, "device rules:\n- blacklist:\n")) < 0)
1698                 return rc;
1699         if ((rc = snprint_blacklist_devgroup(buff, &conf->blist_device)) < 0)
1700                 return rc;
1701
1702         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1703              return rc;
1704         if ((rc = snprint_blacklist_devgroup(buff, &conf->elist_device)) < 0)
1705                 return rc;
1706
1707         return get_strbuf_len(buff) - initial_len;
1708 }
1709
1710 static int snprint_blacklist(const struct config *conf, struct strbuf *buff)
1711 {
1712         int i, rc;
1713         struct blentry * ble;
1714         struct blentry_device * bled;
1715         struct keyword *rootkw;
1716         struct keyword *kw, *pkw;
1717         size_t initial_len = get_strbuf_len(buff);
1718
1719         rootkw = find_keyword(conf->keywords, NULL, "blacklist");
1720         assert(rootkw);
1721
1722         if ((rc = append_strbuf_str(buff, "blacklist {\n")) < 0)
1723                 return rc;
1724
1725         vector_foreach_slot (conf->blist_devnode, ble, i) {
1726                 kw = find_keyword(conf->keywords, rootkw->sub, "devnode");
1727                 assert(kw);
1728                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ble)) < 0)
1729                         return rc;
1730         }
1731         vector_foreach_slot (conf->blist_wwid, ble, i) {
1732                 kw = find_keyword(conf->keywords, rootkw->sub, "wwid");
1733                 assert(kw);
1734                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ble)) < 0)
1735                         return rc;
1736         }
1737         vector_foreach_slot (conf->blist_property, ble, i) {
1738                 kw = find_keyword(conf->keywords, rootkw->sub, "property");
1739                 assert(kw);
1740                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ble)) < 0)
1741                         return rc;
1742         }
1743         vector_foreach_slot (conf->blist_protocol, ble, i) {
1744                 kw = find_keyword(conf->keywords, rootkw->sub, "protocol");
1745                 assert(kw);
1746                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ble)) < 0)
1747                         return rc;
1748         }
1749
1750         rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
1751         assert(rootkw);
1752         kw = find_keyword(conf->keywords, rootkw->sub, "vendor");
1753         pkw = find_keyword(conf->keywords, rootkw->sub, "product");
1754         assert(kw && pkw);
1755
1756         vector_foreach_slot (conf->blist_device, bled, i) {
1757                 if ((rc = snprint_keyword(buff, "\tdevice {\n\t\t%k %v\n",
1758                                           kw, bled)) < 0)
1759                         return rc;
1760                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n\t}\n",
1761                                           pkw, bled)) < 0)
1762                         return rc;
1763         }
1764
1765         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1766                 return rc;
1767         return get_strbuf_len(buff) - initial_len;
1768 }
1769
1770 static int snprint_blacklist_except(const struct config *conf,
1771                                     struct strbuf *buff)
1772 {
1773         int i, rc;
1774         struct blentry * ele;
1775         struct blentry_device * eled;
1776         struct keyword *rootkw;
1777         struct keyword *kw, *pkw;
1778         size_t initial_len = get_strbuf_len(buff);
1779
1780         rootkw = find_keyword(conf->keywords, NULL, "blacklist_exceptions");
1781         assert(rootkw);
1782
1783         if ((rc = append_strbuf_str(buff, "blacklist_exceptions {\n")) < 0)
1784                 return rc;
1785
1786         vector_foreach_slot (conf->elist_devnode, ele, i) {
1787                 kw = find_keyword(conf->keywords, rootkw->sub, "devnode");
1788                 assert(kw);
1789                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ele)) < 0)
1790                         return rc;
1791         }
1792         vector_foreach_slot (conf->elist_wwid, ele, i) {
1793                 kw = find_keyword(conf->keywords, rootkw->sub, "wwid");
1794                 assert(kw);
1795                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ele)) < 0)
1796                         return rc;
1797         }
1798         vector_foreach_slot (conf->elist_property, ele, i) {
1799                 kw = find_keyword(conf->keywords, rootkw->sub, "property");
1800                 assert(kw);
1801                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ele)) < 0)
1802                         return rc;
1803         }
1804         vector_foreach_slot (conf->elist_protocol, ele, i) {
1805                 kw = find_keyword(conf->keywords, rootkw->sub, "protocol");
1806                 assert(kw);
1807                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ele)) < 0)
1808                         return rc;
1809         }
1810
1811         rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
1812         assert(rootkw);
1813         kw = find_keyword(conf->keywords, rootkw->sub, "vendor");
1814         pkw = find_keyword(conf->keywords, rootkw->sub, "product");
1815         assert(kw && pkw);
1816
1817         vector_foreach_slot (conf->elist_device, eled, i) {
1818                 if ((rc = snprint_keyword(buff, "\tdevice {\n\t\t%k %v\n",
1819                                           kw, eled)) < 0)
1820                         return rc;
1821                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n\t}\n",
1822                                           pkw, eled)) < 0)
1823                         return rc;
1824         }
1825
1826         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1827                 return rc;
1828         return get_strbuf_len(buff) - initial_len;
1829 }
1830
1831 int __snprint_config(const struct config *conf, struct strbuf *buff,
1832                      const struct _vector *hwtable, const struct _vector *mpvec)
1833 {
1834         int rc;
1835
1836         if ((rc = snprint_defaults(conf, buff)) < 0 ||
1837             (rc = snprint_blacklist(conf, buff)) < 0 ||
1838             (rc = snprint_blacklist_except(conf, buff)) < 0 ||
1839             (rc = snprint_hwtable(conf, buff,
1840                                   hwtable ? hwtable : conf->hwtable)) < 0 ||
1841             (rc = snprint_overrides(conf, buff, conf->overrides)) < 0)
1842                 return rc;
1843
1844         if (VECTOR_SIZE(conf->mptable) > 0 ||
1845             (mpvec != NULL && VECTOR_SIZE(mpvec) > 0))
1846                 if ((rc = snprint_mptable(conf, buff, mpvec)) < 0)
1847                         return rc;
1848
1849         return 0;
1850 }
1851
1852 char *snprint_config(const struct config *conf, int *len,
1853                      const struct _vector *hwtable, const struct _vector *mpvec)
1854 {
1855         STRBUF_ON_STACK(buff);
1856         char *reply;
1857         int rc = __snprint_config(conf, &buff, hwtable, mpvec);
1858
1859         if (rc < 0)
1860                 return NULL;
1861
1862         if (len)
1863                 *len = get_strbuf_len(&buff);
1864         reply = steal_strbuf_str(&buff);
1865
1866         return reply;
1867 }
1868
1869 int snprint_status(struct strbuf *buff, const struct vectors *vecs)
1870 {
1871         int i, rc;
1872         unsigned int count[PATH_MAX_STATE] = {0};
1873         int monitored_count = 0;
1874         struct path * pp;
1875         size_t initial_len = get_strbuf_len(buff);
1876
1877         vector_foreach_slot (vecs->pathvec, pp, i) {
1878                 count[pp->state]++;
1879         }
1880         if ((rc = append_strbuf_str(buff, "path checker states:\n")) < 0)
1881                 return rc;
1882         for (i = 0; i < PATH_MAX_STATE; i++) {
1883                 if (!count[i])
1884                         continue;
1885                 if ((rc = print_strbuf(buff, "%-20s%u\n",
1886                                        checker_state_name(i), count[i])) < 0)
1887                         return rc;
1888         }
1889
1890         vector_foreach_slot(vecs->pathvec, pp, i)
1891                 if (pp->fd >= 0)
1892                         monitored_count++;
1893         if ((rc = print_strbuf(buff, "\npaths: %d\nbusy: %s\n",
1894                                monitored_count,
1895                                is_uevent_busy()? "True" : "False")) < 0)
1896                 return rc;
1897
1898         return get_strbuf_len(buff) - initial_len;
1899 }
1900
1901 int snprint_devices(struct config *conf, struct strbuf *buff,
1902                     const struct vectors *vecs)
1903 {
1904         int r;
1905         struct udev_enumerate *enm;
1906         struct udev_list_entry *item, *first;
1907         struct path * pp;
1908         size_t initial_len = get_strbuf_len(buff);
1909
1910         enm = udev_enumerate_new(udev);
1911         if (!enm)
1912                 return 1;
1913         udev_enumerate_add_match_subsystem(enm, "block");
1914
1915         if ((r = append_strbuf_str(buff, "available block devices:\n")) < 0)
1916                 goto out;
1917         r = udev_enumerate_scan_devices(enm);
1918         if (r < 0)
1919                 goto out;
1920
1921         first = udev_enumerate_get_list_entry(enm);
1922         udev_list_entry_foreach(item, first) {
1923                 const char *path, *devname, *status;
1924                 struct udev_device *u_dev;
1925
1926                 path = udev_list_entry_get_name(item);
1927                 if (!path)
1928                         continue;
1929                 u_dev = udev_device_new_from_syspath(udev, path);
1930                 if (!u_dev)
1931                         continue;
1932                 devname = udev_device_get_sysname(u_dev);
1933                 if (!devname) {
1934                         udev_device_unref(u_dev);
1935                         continue;
1936                 }
1937
1938                 pp = find_path_by_dev(vecs->pathvec, devname);
1939                 if (!pp) {
1940                         const char *hidden;
1941
1942                         hidden = udev_device_get_sysattr_value(u_dev,
1943                                                                "hidden");
1944                         if (hidden && !strcmp(hidden, "1"))
1945                                 status = "hidden, unmonitored";
1946                         else if (is_claimed_by_foreign(u_dev))
1947                                 status = "foreign, monitored";
1948                         else {
1949                                 r = filter_devnode(conf->blist_devnode,
1950                                                    conf->elist_devnode,
1951                                                    devname);
1952                                 if (r > 0)
1953                                         status = "devnode blacklisted, unmonitored";
1954                                 else
1955                                         status = "devnode whitelisted, unmonitored";
1956                         }
1957                 } else
1958                         status = " devnode whitelisted, monitored";
1959
1960                 r = print_strbuf(buff, "    %s %s\n", devname, status);
1961                 udev_device_unref(u_dev);
1962                 if (r < 0)
1963                         break;
1964         }
1965 out:
1966         udev_enumerate_unref(enm);
1967         if (r < 0)
1968                 return r;
1969
1970         return get_strbuf_len(buff) - initial_len;
1971 }
1972
1973 /*
1974  * stdout printing helpers
1975  */
1976 static void print_all_paths_custo(vector pathvec, int banner, const char *fmt)
1977 {
1978         int i;
1979         struct path * pp;
1980         STRBUF_ON_STACK(line);
1981         fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL;
1982
1983         if (!VECTOR_SIZE(pathvec)) {
1984                 if (banner)
1985                         fprintf(stdout, "===== no paths =====\n");
1986                 return;
1987         }
1988
1989         if ((width = alloc_path_layout()) == NULL)
1990                 return;
1991         get_path_layout(pathvec, 1, width);
1992
1993         if (banner)
1994                 append_strbuf_str(&line, "===== paths list =====\n");
1995
1996         snprint_path_header(&line, fmt, width);
1997
1998         vector_foreach_slot (pathvec, pp, i)
1999                 snprint_path(&line, fmt, pp, width);
2000
2001         printf("%s", get_strbuf_str(&line));
2002 }
2003
2004 void print_all_paths(vector pathvec, int banner)
2005 {
2006         print_all_paths_custo(pathvec, banner, PRINT_PATH_LONG);
2007 }