Fix error
[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->bus != SYSFS_BUS_SCSI ||
654             pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
655                 return append_strbuf_str(buff, "[undef]");
656         sprintf(host_id, "host%d", pp->sg_id.host_no);
657         host_dev = udev_device_new_from_subsystem_sysname(udev, "fc_host",
658                                                           host_id);
659         if (!host_dev) {
660                 condlog(1, "%s: No fc_host device for '%s'", pp->dev, host_id);
661                 goto out;
662         }
663         value = udev_device_get_sysattr_value(host_dev, attr);
664         if (value)
665                 ret = snprint_str(buff, value);
666         udev_device_unref(host_dev);
667 out:
668         if (!value)
669                 ret = append_strbuf_str(buff, "[unknown]");
670         return ret;
671 }
672
673 int
674 snprint_host_wwnn (struct strbuf *buff, const struct path * pp)
675 {
676         return snprint_host_attr(buff, pp, "node_name");
677 }
678
679 int
680 snprint_host_wwpn (struct strbuf *buff, const struct path * pp)
681 {
682         return snprint_host_attr(buff, pp, "port_name");
683 }
684
685 int
686 snprint_tgt_wwpn (struct strbuf *buff, const struct path * pp)
687 {
688         struct udev_device *rport_dev = NULL;
689         char rport_id[42];
690         const char *value = NULL;
691         int ret;
692
693         if (pp->bus != SYSFS_BUS_SCSI ||
694             pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
695                 return append_strbuf_str(buff, "[undef]");
696         sprintf(rport_id, "rport-%d:%d-%d",
697                 pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
698         rport_dev = udev_device_new_from_subsystem_sysname(udev,
699                                 "fc_remote_ports", rport_id);
700         if (!rport_dev) {
701                 condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev,
702                         rport_id);
703                 goto out;
704         }
705         value = udev_device_get_sysattr_value(rport_dev, "port_name");
706         if (value)
707                 ret = snprint_str(buff, value);
708         udev_device_unref(rport_dev);
709 out:
710         if (!value)
711                 ret = append_strbuf_str(buff, "[unknown]");
712         return ret;
713 }
714
715
716 int
717 snprint_tgt_wwnn (struct strbuf *buff, const struct path * pp)
718 {
719         if (pp->tgt_node_name[0] == '\0')
720                 return append_strbuf_str(buff, "[undef]");
721         return snprint_str(buff, pp->tgt_node_name);
722 }
723
724 static int
725 snprint_host_adapter (struct strbuf *buff, const struct path * pp)
726 {
727         char adapter[SLOT_NAME_SIZE];
728
729         if (sysfs_get_host_adapter_name(pp, adapter))
730                 return append_strbuf_str(buff, "[undef]");
731         return snprint_str(buff, adapter);
732 }
733
734 static int
735 snprint_path_checker (struct strbuf *buff, const struct path * pp)
736 {
737         const char * n = checker_name(&pp->checker);
738
739         if (n)
740                 return snprint_str(buff, n);
741         else
742                 return snprint_str(buff, "(null)");
743 }
744
745 static int
746 snprint_path_foreign (struct strbuf *buff,
747                       __attribute__((unused)) const struct path * pp)
748 {
749         return append_strbuf_str(buff, "--");
750 }
751
752 static int
753 snprint_path_failures(struct strbuf *buff, const struct path * pp)
754 {
755         return snprint_int(buff, pp->failcount);
756 }
757
758 /* if you add a protocol string bigger than "scsi:unspec" you must
759  * also change PROTOCOL_BUF_SIZE */
760 int
761 snprint_path_protocol(struct strbuf *buff, const struct path * pp)
762 {
763         const char *pn = protocol_name[bus_protocol_id(pp)];
764
765         assert(pn != NULL);
766         return append_strbuf_str(buff, pn);
767 }
768
769 static int
770 snprint_path_marginal(struct strbuf *buff, const struct path * pp)
771 {
772         if (pp->marginal)
773                 return append_strbuf_str(buff, "marginal");
774         return append_strbuf_str(buff, "normal");
775 }
776
777 static int
778 snprint_path_vpd_data(struct strbuf *buff, const struct path * pp)
779 {
780         if (pp->vpd_data)
781                 return append_strbuf_str(buff, pp->vpd_data);
782         return append_strbuf_str(buff, "[undef]");
783 }
784
785 static int
786 snprint_alua_tpg(struct strbuf *buff, const struct path * pp)
787 {
788         if (pp->tpg_id < 0)
789                 return append_strbuf_str(buff, "[undef]");
790         return print_strbuf(buff, "0x%04x", pp->tpg_id);
791 }
792
793 static const struct multipath_data mpd[] = {
794         {'n', "name",          snprint_name},
795         {'w', "uuid",          snprint_multipath_uuid},
796         {'d', "sysfs",         snprint_sysfs},
797         {'F', "failback",      snprint_failback},
798         {'Q', "queueing",      snprint_queueing},
799         {'N', "paths",         snprint_nb_paths},
800         {'r', "write_prot",    snprint_ro},
801         {'t', "dm-st",         snprint_dm_map_state},
802         {'S', "size",          snprint_multipath_size},
803         {'f', "features",      snprint_features},
804         {'x', "failures",      snprint_map_failures},
805         {'h', "hwhandler",     snprint_hwhandler},
806         {'A', "action",        snprint_action},
807         {'0', "path_faults",   snprint_path_faults},
808         {'1', "switch_grp",    snprint_switch_grp},
809         {'2', "map_loads",     snprint_map_loads},
810         {'3', "total_q_time",  snprint_total_q_time},
811         {'4', "q_timeouts",    snprint_q_timeouts},
812         {'s', "vend/prod/rev", snprint_multipath_vpr},
813         {'v', "vend",          snprint_multipath_vend},
814         {'p', "prod",          snprint_multipath_prod},
815         {'e', "rev",           snprint_multipath_rev},
816         {'G', "foreign",       snprint_multipath_foreign},
817         {'g', "vpd page data", snprint_multipath_vpd_data},
818 };
819
820 static const struct path_data pd[] = {
821         {'w', "uuid",          snprint_path_uuid},
822         {'i', "hcil",          snprint_hcil},
823         {'d', "dev",           snprint_dev},
824         {'D', "dev_t",         snprint_dev_t},
825         {'t', "dm_st",         snprint_dm_path_state},
826         {'o', "dev_st",        snprint_offline},
827         {'T', "chk_st",        snprint_chk_state},
828         {'s', "vend/prod/rev", snprint_vpr},
829         {'c', "checker",       snprint_path_checker},
830         {'C', "next_check",    snprint_next_check},
831         {'p', "pri",           snprint_pri},
832         {'S', "size",          snprint_path_size},
833         {'z', "serial",        snprint_path_serial},
834         {'M', "marginal_st",   snprint_path_marginal},
835         {'m', "multipath",     snprint_path_mpp},
836         {'N', "host WWNN",     snprint_host_wwnn},
837         {'n', "target WWNN",   snprint_tgt_wwnn},
838         {'R', "host WWPN",     snprint_host_wwpn},
839         {'r', "target WWPN",   snprint_tgt_wwpn},
840         {'a', "host adapter",  snprint_host_adapter},
841         {'G', "foreign",       snprint_path_foreign},
842         {'g', "vpd page data", snprint_path_vpd_data},
843         {'0', "failures",      snprint_path_failures},
844         {'P', "protocol",      snprint_path_protocol},
845         {'I', "init_st",       snprint_initialized},
846         {'L', "LUN hex",       snprint_path_lunhex},
847         {'A', "TPG",           snprint_alua_tpg},
848 };
849
850 static const struct pathgroup_data pgd[] = {
851         {'s', "selector",      snprint_pg_selector},
852         {'p', "pri",           snprint_pg_pri},
853         {'t', "dm_st",         snprint_pg_state},
854         {'M', "marginal_st",   snprint_pg_marginal},
855 };
856
857 int snprint_wildcards(struct strbuf *buff)
858 {
859         int initial_len = get_strbuf_len(buff);
860         unsigned int i;
861         int rc;
862
863         if ((rc = append_strbuf_str(buff, "multipath format wildcards:\n")) < 0)
864                 return rc;
865         for (i = 0; i < ARRAY_SIZE(mpd); i++)
866                 if ((rc = print_strbuf(buff, "%%%c  %s\n",
867                                        mpd[i].wildcard, mpd[i].header)) < 0)
868                         return rc;
869
870         if ((rc = append_strbuf_str(buff, "\npath format wildcards:\n")) < 0)
871                 return rc;
872         for (i = 0; i < ARRAY_SIZE(pd); i++)
873                 if ((rc = print_strbuf(buff, "%%%c  %s\n",
874                                        pd[i].wildcard, pd[i].header)) < 0)
875                         return rc;
876
877         if ((rc = append_strbuf_str(buff, "\npathgroup format wildcards:\n")) < 0)
878                 return rc;
879         for (i = 0; i < ARRAY_SIZE(pgd); i++)
880                 if ((rc = print_strbuf(buff, "%%%c  %s\n",
881                                        pgd[i].wildcard, pgd[i].header)) < 0)
882                         return rc;
883
884         return get_strbuf_len(buff) - initial_len;
885 }
886
887 fieldwidth_t *alloc_path_layout(void) {
888         return calloc(ARRAY_SIZE(pd), sizeof(fieldwidth_t));
889 }
890
891 void get_path_layout(vector pathvec, int header, fieldwidth_t *width)
892 {
893         vector gpvec = vector_convert(NULL, pathvec, struct path,
894                                       dm_path_to_gen);
895         _get_path_layout(gpvec,
896                          header ? LAYOUT_RESET_HEADER : LAYOUT_RESET_ZERO,
897                          width);
898         vector_free(gpvec);
899 }
900
901 static void
902 reset_width(fieldwidth_t *width, enum layout_reset reset, const char *header)
903 {
904         switch (reset) {
905         case LAYOUT_RESET_HEADER:
906                 *width = strlen(header);
907                 break;
908         case LAYOUT_RESET_ZERO:
909                 *width = 0;
910                 break;
911         default:
912                 /* don't reset */
913                 break;
914         }
915 }
916
917 void _get_path_layout (const struct _vector *gpvec, enum layout_reset reset,
918                        fieldwidth_t *width)
919 {
920         unsigned int i, j;
921         const struct gen_path *gp;
922
923         if (width == NULL)
924                 return;
925
926         for (j = 0; j < ARRAY_SIZE(pd); j++) {
927                 STRBUF_ON_STACK(buff);
928
929                 reset_width(&width[j], reset, pd[j].header);
930
931                 if (gpvec == NULL)
932                         continue;
933
934                 vector_foreach_slot (gpvec, gp, i) {
935                         gp->ops->snprint(gp, &buff, pd[j].wildcard);
936                         width[j] = MAX(width[j],
937                                        MIN(get_strbuf_len(&buff), MAX_FIELD_WIDTH));
938                         truncate_strbuf(&buff, 0);
939                 }
940         }
941 }
942
943 fieldwidth_t *alloc_multipath_layout(void) {
944
945         return calloc(ARRAY_SIZE(mpd), sizeof(fieldwidth_t));
946 }
947
948 void get_multipath_layout (vector mpvec, int header, fieldwidth_t *width) {
949         vector gmvec = vector_convert(NULL, mpvec, struct multipath,
950                                       dm_multipath_to_gen);
951         _get_multipath_layout(gmvec,
952                               header ? LAYOUT_RESET_HEADER : LAYOUT_RESET_ZERO,
953                               width);
954         vector_free(gmvec);
955 }
956
957 void
958 _get_multipath_layout (const struct _vector *gmvec, enum layout_reset reset,
959                        fieldwidth_t *width)
960 {
961         unsigned int i, j;
962         const struct gen_multipath * gm;
963
964         if (width == NULL)
965                 return;
966         for (j = 0; j < ARRAY_SIZE(mpd); j++) {
967                 STRBUF_ON_STACK(buff);
968
969                 reset_width(&width[j], reset, mpd[j].header);
970
971                 if (gmvec == NULL)
972                         continue;
973
974                 vector_foreach_slot (gmvec, gm, i) {
975                         gm->ops->snprint(gm, &buff, mpd[j].wildcard);
976                         width[j] = MAX(width[j],
977                                        MIN(get_strbuf_len(&buff), MAX_FIELD_WIDTH));
978                         truncate_strbuf(&buff, 0);
979                 }
980                 condlog(4, "%s: width %d", mpd[j].header, width[j]);
981         }
982 }
983
984 static int mpd_lookup(char wildcard)
985 {
986         unsigned int i;
987
988         for (i = 0; i < ARRAY_SIZE(mpd); i++)
989                 if (mpd[i].wildcard == wildcard)
990                         return i;
991
992         return -1;
993 }
994
995 int snprint_multipath_attr(const struct gen_multipath* gm,
996                            struct strbuf *buf, char wildcard)
997 {
998         const struct multipath *mpp = gen_multipath_to_dm(gm);
999         int i = mpd_lookup(wildcard);
1000
1001         if (i == -1)
1002                 return 0;
1003         return mpd[i].snprint(buf, mpp);
1004 }
1005
1006 static int pd_lookup(char wildcard)
1007 {
1008         unsigned int i;
1009
1010         for (i = 0; i < ARRAY_SIZE(pd); i++)
1011                 if (pd[i].wildcard == wildcard)
1012                         return i;
1013
1014         return -1;
1015 }
1016
1017 int snprint_path_attr(const struct gen_path* gp,
1018                       struct strbuf *buf, char wildcard)
1019 {
1020         const struct path *pp = gen_path_to_dm(gp);
1021         int i = pd_lookup(wildcard);
1022
1023         if (i == -1)
1024                 return 0;
1025         return pd[i].snprint(buf, pp);
1026 }
1027
1028 static int pgd_lookup(char wildcard)
1029 {
1030         unsigned int i;
1031
1032         for (i = 0; i < ARRAY_SIZE(pgd); i++)
1033                 if (pgd[i].wildcard == wildcard)
1034                         return i;
1035
1036         return -1;
1037 }
1038
1039 int snprint_pathgroup_attr(const struct gen_pathgroup* gpg,
1040                            struct strbuf *buf, char wildcard)
1041 {
1042         const struct pathgroup *pg = gen_pathgroup_to_dm(gpg);
1043         int i = pgd_lookup(wildcard);
1044
1045         if (i == -1)
1046                 return 0;
1047         return pgd[i].snprint(buf, pg);
1048 }
1049
1050 int snprint_multipath_header(struct strbuf *line, const char *format,
1051                              const fieldwidth_t *width)
1052 {
1053         int initial_len = get_strbuf_len(line);
1054         const char *f;
1055         const struct multipath_data * data;
1056         int rc;
1057
1058         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1059                 int iwc;
1060
1061                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1062                         return rc;
1063
1064                 format = f + 1;
1065                 if ((iwc = mpd_lookup(*format)) == -1)
1066                         continue; /* unknown wildcard */
1067                 data = &mpd[iwc];
1068
1069                 if ((rc = append_strbuf_str(line, data->header)) < 0)
1070                         return rc;
1071                 else if ((unsigned int)rc < width[iwc])
1072                         if ((rc = fill_strbuf(line, ' ', width[iwc] - rc)) < 0)
1073                                 return rc;
1074         }
1075
1076         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1077                 return rc;
1078         return get_strbuf_len(line) - initial_len;
1079 }
1080
1081 int _snprint_multipath(const struct gen_multipath *gmp,
1082                        struct strbuf *line, const char *format,
1083                        const fieldwidth_t *width)
1084 {
1085         int initial_len = get_strbuf_len(line);
1086         const char *f;
1087         int rc;
1088
1089         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1090                 int iwc;
1091
1092                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1093                         return rc;
1094
1095                 format = f + 1;
1096                 if ((iwc = mpd_lookup(*format)) == -1)
1097                         continue; /* unknown wildcard */
1098
1099                 if ((rc = gmp->ops->snprint(gmp, line, *format)) < 0)
1100                         return rc;
1101                 else if (width != NULL && (unsigned int)rc < width[iwc])
1102                         if ((rc = fill_strbuf(line, ' ', width[iwc] - rc)) < 0)
1103                                 return rc;
1104         }
1105
1106         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1107                 return rc;
1108         return get_strbuf_len(line) - initial_len;
1109 }
1110
1111 int snprint_path_header(struct strbuf *line, const char *format,
1112                         const fieldwidth_t *width)
1113 {
1114         int initial_len = get_strbuf_len(line);
1115         const char *f;
1116         const struct path_data *data;
1117         int rc;
1118
1119         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1120                 int iwc;
1121
1122                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1123                         return rc;
1124
1125                 format = f + 1;
1126                 if ((iwc = pd_lookup(*format)) == -1)
1127                         continue; /* unknown wildcard */
1128                 data = &pd[iwc];
1129
1130                 if ((rc = append_strbuf_str(line, data->header)) < 0)
1131                         return rc;
1132                 else if ((unsigned int)rc < width[iwc])
1133                         if ((rc = fill_strbuf(line, ' ', width[iwc] - rc)) < 0)
1134                                 return rc;
1135         }
1136
1137         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1138                 return rc;
1139         return get_strbuf_len(line) - initial_len;
1140 }
1141
1142 int _snprint_path(const struct gen_path *gp, struct strbuf *line,
1143                   const char *format, const fieldwidth_t *width)
1144 {
1145         int initial_len = get_strbuf_len(line);
1146         const char *f;
1147         int rc;
1148
1149         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1150                 int iwc;
1151
1152                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1153                         return rc;
1154
1155                 format = f + 1;
1156                 if ((iwc = pd_lookup(*format)) == -1)
1157                         continue; /* unknown wildcard */
1158
1159                 if ((rc = gp->ops->snprint(gp, line, *format)) < 0)
1160                         return rc;
1161                 else if (width != NULL && (unsigned int)rc < width[iwc])
1162                         if ((rc = fill_strbuf(line, ' ', width[iwc] - rc)) < 0)
1163                                 return rc;
1164         }
1165
1166         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1167                 return rc;
1168         return get_strbuf_len(line) - initial_len;
1169 }
1170
1171 int _snprint_pathgroup(const struct gen_pathgroup *ggp, struct strbuf *line,
1172                        const char *format)
1173 {
1174         int initial_len = get_strbuf_len(line);
1175         const char *f;
1176         int rc;
1177
1178         for (f = strchr(format, '%'); f; f = strchr(++format, '%')) {
1179                 if ((rc = __append_strbuf_str(line, format, f - format)) < 0)
1180                         return rc;
1181
1182                 format = f + 1;
1183
1184                 if ((rc = ggp->ops->snprint(ggp, line, *format)) < 0)
1185                         return rc;
1186         }
1187
1188         if ((rc = print_strbuf(line, "%s\n", format)) < 0)
1189                 return rc;
1190         return get_strbuf_len(line) - initial_len;
1191 }
1192
1193 #define snprint_pathgroup(line, fmt, pgp)                               \
1194         _snprint_pathgroup(dm_pathgroup_to_gen(pgp), line, fmt)
1195
1196 void _print_multipath_topology(const struct gen_multipath *gmp, int verbosity)
1197 {
1198         STRBUF_ON_STACK(buff);
1199         fieldwidth_t *p_width __attribute__((cleanup(cleanup_ucharp))) = NULL;
1200         const struct gen_pathgroup *gpg;
1201         const struct _vector *pgvec, *pathvec;
1202         int j;
1203
1204         p_width = alloc_path_layout();
1205         pgvec = gmp->ops->get_pathgroups(gmp);
1206
1207         if (pgvec != NULL) {
1208                 vector_foreach_slot (pgvec, gpg, j) {
1209                         pathvec = gpg->ops->get_paths(gpg);
1210                         if (pathvec == NULL)
1211                                 continue;
1212                         _get_path_layout(pathvec, LAYOUT_RESET_NOT, p_width);
1213                         gpg->ops->rel_paths(gpg, pathvec);
1214                 }
1215                 gmp->ops->rel_pathgroups(gmp, pgvec);
1216         }
1217
1218         _snprint_multipath_topology(gmp, &buff, verbosity, p_width);
1219         printf("%s", get_strbuf_str(&buff));
1220 }
1221
1222 int snprint_multipath_style(const struct gen_multipath *gmp,
1223                             struct strbuf *style, int verbosity)
1224 {
1225         const struct multipath *mpp = gen_multipath_to_dm(gmp);
1226         bool need_action = (verbosity > 1 &&
1227                             mpp->action != ACT_NOTHING &&
1228                             mpp->action != ACT_UNDEF &&
1229                             mpp->action != ACT_IMPOSSIBLE);
1230         bool need_wwid = (strncmp(mpp->alias, mpp->wwid, WWID_SIZE));
1231
1232         return print_strbuf(style, "%s%s%s%s",
1233                             need_action ? "%A: " : "", "%n",
1234                             need_wwid ? " (%w)" : "", " %d %s");
1235 }
1236
1237 int _snprint_multipath_topology(const struct gen_multipath *gmp,
1238                                 struct strbuf *buff, int verbosity,
1239                                 const fieldwidth_t *p_width)
1240 {
1241         int j, i, rc;
1242         const struct _vector *pgvec;
1243         const struct gen_pathgroup *gpg;
1244         STRBUF_ON_STACK(style);
1245         size_t initial_len = get_strbuf_len(buff);
1246         fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL;
1247
1248         if (verbosity <= 0)
1249                 return 0;
1250
1251         if ((width = alloc_multipath_layout()) == NULL)
1252                 return -ENOMEM;
1253
1254         if (verbosity == 1)
1255                 return _snprint_multipath(gmp, buff, "%n", width);
1256
1257         if(isatty(1) &&
1258            (rc = print_strbuf(&style, "%c[%dm", 0x1B, 1)) < 0) /* bold on */
1259                 return rc;
1260         if ((rc = gmp->ops->style(gmp, &style, verbosity)) < 0)
1261                 return rc;
1262         if(isatty(1) &&
1263            (rc = print_strbuf(&style, "%c[%dm", 0x1B, 0)) < 0) /* bold off */
1264                 return rc;
1265
1266         if ((rc = _snprint_multipath(gmp, buff, get_strbuf_str(&style), width)) < 0
1267             || (rc = _snprint_multipath(gmp, buff, PRINT_MAP_PROPS, width)) < 0)
1268                 return rc;
1269
1270         pgvec = gmp->ops->get_pathgroups(gmp);
1271         if (pgvec == NULL)
1272                 goto out;
1273
1274         vector_foreach_slot (pgvec, gpg, j) {
1275                 const struct _vector *pathvec;
1276                 struct gen_path *gp;
1277                 bool last_group = j + 1 == VECTOR_SIZE(pgvec);
1278
1279                 if ((rc = print_strbuf(buff, "%c-+- ",
1280                                        last_group ? '`' : '|')) < 0 ||
1281                     (rc = _snprint_pathgroup(gpg, buff, PRINT_PG_INDENT)) < 0)
1282                         return rc;
1283
1284                 pathvec = gpg->ops->get_paths(gpg);
1285                 if (pathvec == NULL)
1286                         continue;
1287
1288                 vector_foreach_slot (pathvec, gp, i) {
1289                         if ((rc = print_strbuf(buff, "%c %c- ",
1290                                                last_group ? ' ' : '|',
1291                                                i + 1 == VECTOR_SIZE(pathvec) ?
1292                                                '`': '|')) < 0 ||
1293                             (rc = _snprint_path(gp, buff,
1294                                                 PRINT_PATH_INDENT, p_width)) < 0)
1295                                 return rc;
1296                 }
1297                 gpg->ops->rel_paths(gpg, pathvec);
1298         }
1299
1300         gmp->ops->rel_pathgroups(gmp, pgvec);
1301 out:
1302         return get_strbuf_len(buff) - initial_len;
1303 }
1304
1305
1306 static int
1307 snprint_json(struct strbuf *buff, int indent, const char *json_str)
1308 {
1309         int rc;
1310
1311         if ((rc = fill_strbuf(buff, ' ', indent * PRINT_JSON_INDENT_N)) < 0)
1312                 return rc;
1313
1314         return append_strbuf_str(buff, json_str);
1315 }
1316
1317 static int snprint_json_header(struct strbuf *buff)
1318 {
1319         int rc;
1320
1321         if ((rc = snprint_json(buff, 0, PRINT_JSON_START_ELEM)) < 0)
1322                 return rc;
1323         return print_strbuf(buff, PRINT_JSON_START_VERSION,
1324                             PRINT_JSON_MAJOR_VERSION, PRINT_JSON_MINOR_VERSION);
1325 }
1326
1327 static int snprint_json_elem_footer(struct strbuf *buff, int indent, bool last)
1328 {
1329         int rc;
1330
1331         if ((rc = fill_strbuf(buff, ' ', indent * PRINT_JSON_INDENT_N)) < 0)
1332                 return rc;
1333
1334         if (last)
1335                 return append_strbuf_str(buff, PRINT_JSON_END_LAST_ELEM);
1336         else
1337                 return append_strbuf_str(buff, PRINT_JSON_END_ELEM);
1338 }
1339
1340 static int snprint_multipath_fields_json(struct strbuf *buff,
1341                                          const struct multipath *mpp, int last)
1342 {
1343         int i, j, rc;
1344         struct path *pp;
1345         struct pathgroup *pgp;
1346         size_t initial_len = get_strbuf_len(buff);
1347
1348         if ((rc = snprint_multipath(buff, PRINT_JSON_MAP, mpp, 0)) < 0 ||
1349             (rc = snprint_json(buff, 2, PRINT_JSON_START_GROUPS)) < 0)
1350                 return rc;
1351
1352         vector_foreach_slot (mpp->pg, pgp, i) {
1353
1354                 if ((rc = snprint_pathgroup(buff, PRINT_JSON_GROUP, pgp)) < 0 ||
1355                     (rc = print_strbuf(buff, PRINT_JSON_GROUP_NUM, i + 1)) < 0 ||
1356                     (rc = snprint_json(buff, 3, PRINT_JSON_START_PATHS)) < 0)
1357                         return rc;
1358
1359                 vector_foreach_slot (pgp->paths, pp, j) {
1360                         if ((rc = snprint_path(buff, PRINT_JSON_PATH,
1361                                                pp, 0)) < 0 ||
1362                             (rc = snprint_json_elem_footer(
1363                                     buff, 3,
1364                                     j + 1 == VECTOR_SIZE(pgp->paths))) < 0)
1365                                 return rc;
1366                 }
1367                 if ((rc = snprint_json(buff, 0, PRINT_JSON_END_ARRAY)) < 0 ||
1368                     (rc = snprint_json_elem_footer(
1369                             buff, 2, i + 1 == VECTOR_SIZE(mpp->pg))) < 0)
1370                         return rc;
1371         }
1372
1373         if ((rc = snprint_json(buff, 0, PRINT_JSON_END_ARRAY)) < 0 ||
1374             (rc = snprint_json_elem_footer(buff, 1, last)) < 0)
1375                 return rc;
1376
1377         return get_strbuf_len(buff) - initial_len;
1378 }
1379
1380 int snprint_multipath_map_json(struct strbuf *buff, const struct multipath * mpp)
1381 {
1382         size_t initial_len = get_strbuf_len(buff);
1383         int rc;
1384
1385         if ((rc = snprint_json_header(buff)) < 0 ||
1386             (rc = snprint_json(buff, 0, PRINT_JSON_START_MAP)) < 0)
1387                 return rc;
1388
1389         if ((rc = snprint_multipath_fields_json(buff, mpp, 1)) < 0)
1390                 return rc;
1391
1392         if ((rc = snprint_json(buff, 0, "\n")) < 0 ||
1393             (rc = snprint_json(buff, 0, PRINT_JSON_END_LAST)) < 0)
1394                 return rc;
1395
1396         return get_strbuf_len(buff) - initial_len;
1397 }
1398
1399 int snprint_multipath_topology_json (struct strbuf *buff,
1400                                      const struct vectors * vecs)
1401 {
1402         int i;
1403         struct multipath * mpp;
1404         size_t initial_len = get_strbuf_len(buff);
1405         int rc;
1406
1407         if ((rc = snprint_json_header(buff)) < 0 ||
1408             (rc = snprint_json(buff, 1, PRINT_JSON_START_MAPS)) < 0)
1409                 return rc;
1410
1411         vector_foreach_slot(vecs->mpvec, mpp, i) {
1412                 if ((rc = snprint_multipath_fields_json(
1413                              buff, mpp, i + 1 == VECTOR_SIZE(vecs->mpvec))) < 0)
1414                         return rc;
1415         }
1416
1417         if ((rc = snprint_json(buff, 0, PRINT_JSON_END_ARRAY)) < 0 ||
1418             (rc = snprint_json(buff, 0, PRINT_JSON_END_LAST)) < 0)
1419                 return rc;
1420
1421         return get_strbuf_len(buff) - initial_len;
1422 }
1423
1424 static int
1425 snprint_pcentry (const struct config *conf, struct strbuf *buff,
1426                  const struct pcentry *pce)
1427 {
1428         int i, rc;
1429         struct keyword *kw;
1430         struct keyword * rootkw;
1431         size_t initial_len = get_strbuf_len(buff);
1432
1433         rootkw = find_keyword(conf->keywords, NULL, "overrides");
1434         assert(rootkw && rootkw->sub);
1435         rootkw = find_keyword(conf->keywords, rootkw->sub, "protocol");
1436         assert(rootkw);
1437
1438         if ((rc = append_strbuf_str(buff, "\tprotocol {\n")) < 0)
1439                 return rc;
1440
1441         iterate_sub_keywords(rootkw, kw, i) {
1442                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n", kw, pce)) < 0)
1443                         return rc;
1444         }
1445
1446         if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
1447                 return rc;
1448         return get_strbuf_len(buff) - initial_len;
1449 }
1450
1451 static int
1452 snprint_pctable (const struct config *conf, struct strbuf *buff,
1453                  const struct _vector *pctable)
1454 {
1455         int i, rc;
1456         struct pcentry *pce;
1457         struct keyword * rootkw;
1458         size_t initial_len = get_strbuf_len(buff);
1459
1460         rootkw = find_keyword(conf->keywords, NULL, "overrides");
1461         assert(rootkw);
1462
1463         vector_foreach_slot(pctable, pce, i) {
1464                 if ((rc = snprint_pcentry(conf, buff, pce)) < 0)
1465                         return rc;
1466         }
1467         return get_strbuf_len(buff) - initial_len;
1468 }
1469
1470 static int
1471 snprint_hwentry (const struct config *conf,
1472                  struct strbuf *buff, const struct hwentry * hwe)
1473 {
1474         int i, rc;
1475         struct keyword * kw;
1476         struct keyword * rootkw;
1477         size_t initial_len = get_strbuf_len(buff);
1478
1479         rootkw = find_keyword(conf->keywords, NULL, "devices");
1480         assert(rootkw && rootkw->sub);
1481         rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
1482         assert(rootkw);
1483
1484         if ((rc = append_strbuf_str(buff, "\tdevice {\n")) < 0)
1485                 return rc;
1486
1487         iterate_sub_keywords(rootkw, kw, i) {
1488                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n", kw, hwe)) < 0)
1489                         return rc;
1490         }
1491         if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
1492                 return rc;
1493         return get_strbuf_len(buff) - initial_len;
1494 }
1495
1496 static int snprint_hwtable(const struct config *conf, struct strbuf *buff,
1497                            const struct _vector *hwtable)
1498 {
1499         int i, rc;
1500         struct hwentry * hwe;
1501         struct keyword * rootkw;
1502         size_t initial_len = get_strbuf_len(buff);
1503
1504         rootkw = find_keyword(conf->keywords, NULL, "devices");
1505         assert(rootkw);
1506
1507         if ((rc = append_strbuf_str(buff, "devices {\n")) < 0)
1508                 return rc;
1509
1510         vector_foreach_slot (hwtable, hwe, i) {
1511                 if ((rc = snprint_hwentry(conf, buff, hwe)) < 0)
1512                         return rc;
1513         }
1514
1515         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1516                 return rc;
1517
1518         return get_strbuf_len(buff) - initial_len;
1519 }
1520
1521 static int
1522 snprint_mpentry (const struct config *conf, struct strbuf *buff,
1523                  const struct mpentry * mpe, const struct _vector *mpvec)
1524 {
1525         int i, rc;
1526         struct keyword * kw;
1527         struct keyword * rootkw;
1528         struct multipath *mpp = NULL;
1529         size_t initial_len = get_strbuf_len(buff);
1530
1531         if (mpvec != NULL && (mpp = find_mp_by_wwid(mpvec, mpe->wwid)) == NULL)
1532                 return 0;
1533
1534         rootkw = find_keyword(conf->keywords, NULL, "multipath");
1535         assert(rootkw);
1536
1537         if ((rc = append_strbuf_str(buff, "\tmultipath {\n")) < 0)
1538                 return rc;
1539
1540         iterate_sub_keywords(rootkw, kw, i) {
1541                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n", kw, mpe)) < 0)
1542                         return rc;
1543         }
1544         /*
1545          * This mpp doesn't have alias defined. Add the alias in a comment.
1546          */
1547         if (mpp != NULL && strcmp(mpp->alias, mpp->wwid) &&
1548             (rc = print_strbuf(buff, "\t\t# alias \"%s\"\n", mpp->alias)) < 0)
1549                 return rc;
1550
1551         if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
1552                 return rc;
1553
1554         return get_strbuf_len(buff) - initial_len;
1555 }
1556
1557 static int snprint_mptable(const struct config *conf, struct strbuf *buff,
1558                            const struct _vector *mpvec)
1559 {
1560         int i, rc;
1561         struct mpentry * mpe;
1562         struct keyword * rootkw;
1563         size_t initial_len = get_strbuf_len(buff);
1564
1565         rootkw = find_keyword(conf->keywords, NULL, "multipaths");
1566         assert(rootkw);
1567
1568         if ((rc = append_strbuf_str(buff, "multipaths {\n")) < 0)
1569                 return rc;
1570
1571         vector_foreach_slot (conf->mptable, mpe, i) {
1572                 if ((rc = snprint_mpentry(conf, buff, mpe, mpvec)) < 0)
1573                         return rc;
1574         }
1575         if (mpvec != NULL) {
1576                 struct multipath *mpp;
1577
1578                 vector_foreach_slot(mpvec, mpp, i) {
1579                         if (find_mpe(conf->mptable, mpp->wwid) != NULL)
1580                                 continue;
1581
1582                         if ((rc = print_strbuf(buff,
1583                                                "\tmultipath {\n\t\twwid \"%s\"\n",
1584                                                mpp->wwid)) < 0)
1585                                 return rc;
1586                         /*
1587                          * This mpp doesn't have alias defined in
1588                          * multipath.conf - otherwise find_mpe would have
1589                          * found it. Add the alias in a comment.
1590                          */
1591                         if (strcmp(mpp->alias, mpp->wwid) &&
1592                             (rc = print_strbuf(buff, "\t\t# alias \"%s\"\n",
1593                                                mpp->alias)) < 0)
1594                                 return rc;
1595                         if ((rc = append_strbuf_str(buff, "\t}\n")) < 0)
1596                                 return rc;
1597                 }
1598         }
1599         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1600                 return rc;
1601         return get_strbuf_len(buff) - initial_len;
1602 }
1603
1604 static int snprint_overrides(const struct config *conf, struct strbuf *buff,
1605                              const struct hwentry *overrides)
1606 {
1607         int i, rc;
1608         struct keyword *rootkw;
1609         struct keyword *kw;
1610         size_t initial_len = get_strbuf_len(buff);
1611
1612         rootkw = find_keyword(conf->keywords, NULL, "overrides");
1613         assert(rootkw);
1614
1615         if ((rc = append_strbuf_str(buff, "overrides {\n")) < 0)
1616                 return rc;
1617         if (!overrides)
1618                 goto out;
1619
1620         iterate_sub_keywords(rootkw, kw, i) {
1621                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, NULL)) < 0)
1622                         return rc;
1623         }
1624
1625         if (overrides->pctable &&
1626             (rc = snprint_pctable(conf, buff, overrides->pctable)) < 0)
1627                 return rc;
1628 out:
1629         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1630                 return rc;
1631         return get_strbuf_len(buff) - initial_len;
1632 }
1633
1634 static int snprint_defaults(const struct config *conf, struct strbuf *buff)
1635 {
1636         int i, rc;
1637         struct keyword *rootkw;
1638         struct keyword *kw;
1639         size_t initial_len = get_strbuf_len(buff);
1640
1641         rootkw = find_keyword(conf->keywords, NULL, "defaults");
1642         assert(rootkw);
1643
1644         if ((rc = append_strbuf_str(buff, "defaults {\n")) < 0)
1645                 return rc;
1646
1647         iterate_sub_keywords(rootkw, kw, i) {
1648                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, NULL)) < 0)
1649                         return rc;
1650         }
1651         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1652                 return rc;
1653         return get_strbuf_len(buff) - initial_len;
1654 }
1655
1656 static int snprint_blacklist_group(struct strbuf *buff, vector *vec)
1657 {
1658         struct blentry * ble;
1659         size_t initial_len = get_strbuf_len(buff);
1660         int rc, i;
1661
1662         if (!VECTOR_SIZE(*vec)) {
1663                 if ((rc = append_strbuf_str(buff, "        <empty>\n")) < 0)
1664                         return rc;
1665         } else vector_foreach_slot (*vec, ble, i) {
1666                 rc = print_strbuf(buff, "        %s %s\n",
1667                                    ble->origin == ORIGIN_CONFIG ?
1668                                    "(config file rule)" :
1669                                    "(default rule)    ", ble->str);
1670                 if (rc < 0)
1671                         return rc;
1672         }
1673
1674         return get_strbuf_len(buff) - initial_len;
1675 }
1676
1677 static int
1678 snprint_blacklist_devgroup (struct strbuf *buff, vector *vec)
1679 {
1680         struct blentry_device * bled;
1681         size_t initial_len = get_strbuf_len(buff);
1682         int rc, i;
1683
1684         if (!VECTOR_SIZE(*vec)) {
1685                 if ((rc = append_strbuf_str(buff, "        <empty>\n")) < 0)
1686                         return rc;
1687         } else vector_foreach_slot (*vec, bled, i) {
1688                 rc = print_strbuf(buff, "        %s %s:%s\n",
1689                                   bled->origin == ORIGIN_CONFIG ?
1690                                   "(config file rule)" :
1691                                   "(default rule)    ",
1692                                   bled->vendor, bled->product);
1693                 if (rc < 0)
1694                         return rc;
1695         }
1696
1697         return get_strbuf_len(buff) - initial_len;
1698 }
1699
1700 int snprint_blacklist_report(struct config *conf, struct strbuf *buff)
1701 {
1702         size_t initial_len = get_strbuf_len(buff);
1703         int rc;
1704
1705         if ((rc = append_strbuf_str(buff, "device node rules:\n- blacklist:\n")) < 0)
1706                 return rc;
1707         if ((rc = snprint_blacklist_group(buff, &conf->blist_devnode)) < 0)
1708                 return rc;
1709
1710         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1711                 return rc;
1712         if ((rc = snprint_blacklist_group(buff, &conf->elist_devnode)) < 0)
1713                 return rc;
1714
1715         if ((rc = append_strbuf_str(buff, "udev property rules:\n- blacklist:\n")) < 0)
1716                 return rc;
1717         if ((rc = snprint_blacklist_group(buff, &conf->blist_property)) < 0)
1718                 return rc;
1719
1720         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1721                 return rc;
1722         if ((rc = snprint_blacklist_group(buff, &conf->elist_property)) < 0)
1723                 return rc;
1724
1725         if ((rc = append_strbuf_str(buff, "protocol rules:\n- blacklist:\n")) < 0)
1726                 return rc;
1727         if ((rc = snprint_blacklist_group(buff, &conf->blist_protocol)) < 0)
1728                 return rc;
1729
1730         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1731                 return rc;
1732         if ((rc = snprint_blacklist_group(buff, &conf->elist_protocol)) < 0)
1733                 return rc;
1734
1735         if ((rc = append_strbuf_str(buff, "wwid rules:\n- blacklist:\n")) < 0)
1736                 return rc;
1737         if ((rc = snprint_blacklist_group(buff, &conf->blist_wwid)) < 0)
1738                 return rc;
1739
1740         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1741                 return rc;
1742         if ((rc = snprint_blacklist_group(buff, &conf->elist_wwid)) < 0)
1743                 return rc;
1744
1745         if ((rc = append_strbuf_str(buff, "device rules:\n- blacklist:\n")) < 0)
1746                 return rc;
1747         if ((rc = snprint_blacklist_devgroup(buff, &conf->blist_device)) < 0)
1748                 return rc;
1749
1750         if ((rc = append_strbuf_str(buff, "- exceptions:\n")) < 0)
1751              return rc;
1752         if ((rc = snprint_blacklist_devgroup(buff, &conf->elist_device)) < 0)
1753                 return rc;
1754
1755         return get_strbuf_len(buff) - initial_len;
1756 }
1757
1758 static int snprint_blacklist(const struct config *conf, struct strbuf *buff)
1759 {
1760         int i, rc;
1761         struct blentry * ble;
1762         struct blentry_device * bled;
1763         struct keyword *rootkw;
1764         struct keyword *kw, *pkw;
1765         size_t initial_len = get_strbuf_len(buff);
1766
1767         rootkw = find_keyword(conf->keywords, NULL, "blacklist");
1768         assert(rootkw);
1769
1770         if ((rc = append_strbuf_str(buff, "blacklist {\n")) < 0)
1771                 return rc;
1772
1773         vector_foreach_slot (conf->blist_devnode, ble, i) {
1774                 kw = find_keyword(conf->keywords, rootkw->sub, "devnode");
1775                 assert(kw);
1776                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ble)) < 0)
1777                         return rc;
1778         }
1779         vector_foreach_slot (conf->blist_wwid, ble, i) {
1780                 kw = find_keyword(conf->keywords, rootkw->sub, "wwid");
1781                 assert(kw);
1782                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ble)) < 0)
1783                         return rc;
1784         }
1785         vector_foreach_slot (conf->blist_property, ble, i) {
1786                 kw = find_keyword(conf->keywords, rootkw->sub, "property");
1787                 assert(kw);
1788                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ble)) < 0)
1789                         return rc;
1790         }
1791         vector_foreach_slot (conf->blist_protocol, ble, i) {
1792                 kw = find_keyword(conf->keywords, rootkw->sub, "protocol");
1793                 assert(kw);
1794                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ble)) < 0)
1795                         return rc;
1796         }
1797
1798         rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
1799         assert(rootkw);
1800         kw = find_keyword(conf->keywords, rootkw->sub, "vendor");
1801         pkw = find_keyword(conf->keywords, rootkw->sub, "product");
1802         assert(kw && pkw);
1803
1804         vector_foreach_slot (conf->blist_device, bled, i) {
1805                 if ((rc = snprint_keyword(buff, "\tdevice {\n\t\t%k %v\n",
1806                                           kw, bled)) < 0)
1807                         return rc;
1808                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n\t}\n",
1809                                           pkw, bled)) < 0)
1810                         return rc;
1811         }
1812
1813         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1814                 return rc;
1815         return get_strbuf_len(buff) - initial_len;
1816 }
1817
1818 static int snprint_blacklist_except(const struct config *conf,
1819                                     struct strbuf *buff)
1820 {
1821         int i, rc;
1822         struct blentry * ele;
1823         struct blentry_device * eled;
1824         struct keyword *rootkw;
1825         struct keyword *kw, *pkw;
1826         size_t initial_len = get_strbuf_len(buff);
1827
1828         rootkw = find_keyword(conf->keywords, NULL, "blacklist_exceptions");
1829         assert(rootkw);
1830
1831         if ((rc = append_strbuf_str(buff, "blacklist_exceptions {\n")) < 0)
1832                 return rc;
1833
1834         vector_foreach_slot (conf->elist_devnode, ele, i) {
1835                 kw = find_keyword(conf->keywords, rootkw->sub, "devnode");
1836                 assert(kw);
1837                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ele)) < 0)
1838                         return rc;
1839         }
1840         vector_foreach_slot (conf->elist_wwid, ele, i) {
1841                 kw = find_keyword(conf->keywords, rootkw->sub, "wwid");
1842                 assert(kw);
1843                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ele)) < 0)
1844                         return rc;
1845         }
1846         vector_foreach_slot (conf->elist_property, ele, i) {
1847                 kw = find_keyword(conf->keywords, rootkw->sub, "property");
1848                 assert(kw);
1849                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ele)) < 0)
1850                         return rc;
1851         }
1852         vector_foreach_slot (conf->elist_protocol, ele, i) {
1853                 kw = find_keyword(conf->keywords, rootkw->sub, "protocol");
1854                 assert(kw);
1855                 if ((rc = snprint_keyword(buff, "\t%k %v\n", kw, ele)) < 0)
1856                         return rc;
1857         }
1858
1859         rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
1860         assert(rootkw);
1861         kw = find_keyword(conf->keywords, rootkw->sub, "vendor");
1862         pkw = find_keyword(conf->keywords, rootkw->sub, "product");
1863         assert(kw && pkw);
1864
1865         vector_foreach_slot (conf->elist_device, eled, i) {
1866                 if ((rc = snprint_keyword(buff, "\tdevice {\n\t\t%k %v\n",
1867                                           kw, eled)) < 0)
1868                         return rc;
1869                 if ((rc = snprint_keyword(buff, "\t\t%k %v\n\t}\n",
1870                                           pkw, eled)) < 0)
1871                         return rc;
1872         }
1873
1874         if ((rc = append_strbuf_str(buff, "}\n")) < 0)
1875                 return rc;
1876         return get_strbuf_len(buff) - initial_len;
1877 }
1878
1879 int __snprint_config(const struct config *conf, struct strbuf *buff,
1880                      const struct _vector *hwtable, const struct _vector *mpvec)
1881 {
1882         int rc;
1883
1884         if ((rc = snprint_defaults(conf, buff)) < 0 ||
1885             (rc = snprint_blacklist(conf, buff)) < 0 ||
1886             (rc = snprint_blacklist_except(conf, buff)) < 0 ||
1887             (rc = snprint_hwtable(conf, buff,
1888                                   hwtable ? hwtable : conf->hwtable)) < 0 ||
1889             (rc = snprint_overrides(conf, buff, conf->overrides)) < 0)
1890                 return rc;
1891
1892         if (VECTOR_SIZE(conf->mptable) > 0 ||
1893             (mpvec != NULL && VECTOR_SIZE(mpvec) > 0))
1894                 if ((rc = snprint_mptable(conf, buff, mpvec)) < 0)
1895                         return rc;
1896
1897         return 0;
1898 }
1899
1900 char *snprint_config(const struct config *conf, int *len,
1901                      const struct _vector *hwtable, const struct _vector *mpvec)
1902 {
1903         STRBUF_ON_STACK(buff);
1904         char *reply;
1905         int rc = __snprint_config(conf, &buff, hwtable, mpvec);
1906
1907         if (rc < 0)
1908                 return NULL;
1909
1910         if (len)
1911                 *len = get_strbuf_len(&buff);
1912         reply = steal_strbuf_str(&buff);
1913
1914         return reply;
1915 }
1916
1917 int snprint_status(struct strbuf *buff, const struct vectors *vecs)
1918 {
1919         int i, rc;
1920         unsigned int count[PATH_MAX_STATE] = {0};
1921         int monitored_count = 0;
1922         struct path * pp;
1923         size_t initial_len = get_strbuf_len(buff);
1924
1925         vector_foreach_slot (vecs->pathvec, pp, i) {
1926                 count[pp->state]++;
1927         }
1928         if ((rc = append_strbuf_str(buff, "path checker states:\n")) < 0)
1929                 return rc;
1930         for (i = 0; i < PATH_MAX_STATE; i++) {
1931                 if (!count[i])
1932                         continue;
1933                 if ((rc = print_strbuf(buff, "%-20s%u\n",
1934                                        checker_state_name(i), count[i])) < 0)
1935                         return rc;
1936         }
1937
1938         vector_foreach_slot(vecs->pathvec, pp, i)
1939                 if (pp->fd >= 0)
1940                         monitored_count++;
1941         if ((rc = print_strbuf(buff, "\npaths: %d\nbusy: %s\n",
1942                                monitored_count,
1943                                is_uevent_busy()? "True" : "False")) < 0)
1944                 return rc;
1945
1946         return get_strbuf_len(buff) - initial_len;
1947 }
1948
1949 int snprint_devices(struct config *conf, struct strbuf *buff,
1950                     const struct vectors *vecs)
1951 {
1952         int r;
1953         struct udev_enumerate *enm;
1954         struct udev_list_entry *item, *first;
1955         struct path * pp;
1956         size_t initial_len = get_strbuf_len(buff);
1957
1958         enm = udev_enumerate_new(udev);
1959         if (!enm)
1960                 return 1;
1961         udev_enumerate_add_match_subsystem(enm, "block");
1962
1963         if ((r = append_strbuf_str(buff, "available block devices:\n")) < 0)
1964                 goto out;
1965         r = udev_enumerate_scan_devices(enm);
1966         if (r < 0)
1967                 goto out;
1968
1969         first = udev_enumerate_get_list_entry(enm);
1970         udev_list_entry_foreach(item, first) {
1971                 const char *path, *devname, *status;
1972                 struct udev_device *u_dev;
1973
1974                 path = udev_list_entry_get_name(item);
1975                 if (!path)
1976                         continue;
1977                 u_dev = udev_device_new_from_syspath(udev, path);
1978                 if (!u_dev)
1979                         continue;
1980                 devname = udev_device_get_sysname(u_dev);
1981                 if (!devname) {
1982                         udev_device_unref(u_dev);
1983                         continue;
1984                 }
1985
1986                 pp = find_path_by_dev(vecs->pathvec, devname);
1987                 if (!pp) {
1988                         const char *hidden;
1989
1990                         hidden = udev_device_get_sysattr_value(u_dev,
1991                                                                "hidden");
1992                         if (hidden && !strcmp(hidden, "1"))
1993                                 status = "hidden, unmonitored";
1994                         else if (is_claimed_by_foreign(u_dev))
1995                                 status = "foreign, monitored";
1996                         else {
1997                                 r = filter_devnode(conf->blist_devnode,
1998                                                    conf->elist_devnode,
1999                                                    devname);
2000                                 if (r > 0)
2001                                         status = "devnode blacklisted, unmonitored";
2002                                 else
2003                                         status = "devnode whitelisted, unmonitored";
2004                         }
2005                 } else
2006                         status = " devnode whitelisted, monitored";
2007
2008                 r = print_strbuf(buff, "    %s %s\n", devname, status);
2009                 udev_device_unref(u_dev);
2010                 if (r < 0)
2011                         break;
2012         }
2013 out:
2014         udev_enumerate_unref(enm);
2015         if (r < 0)
2016                 return r;
2017
2018         return get_strbuf_len(buff) - initial_len;
2019 }
2020
2021 /*
2022  * stdout printing helpers
2023  */
2024 static void print_all_paths_custo(vector pathvec, int banner, const char *fmt)
2025 {
2026         int i;
2027         struct path * pp;
2028         STRBUF_ON_STACK(line);
2029         fieldwidth_t *width __attribute__((cleanup(cleanup_ucharp))) = NULL;
2030
2031         if (!VECTOR_SIZE(pathvec)) {
2032                 if (banner)
2033                         fprintf(stdout, "===== no paths =====\n");
2034                 return;
2035         }
2036
2037         if ((width = alloc_path_layout()) == NULL)
2038                 return;
2039         get_path_layout(pathvec, 1, width);
2040
2041         if (banner)
2042                 append_strbuf_str(&line, "===== paths list =====\n");
2043
2044         snprint_path_header(&line, fmt, width);
2045
2046         vector_foreach_slot (pathvec, pp, i)
2047                 snprint_path(&line, fmt, pp, width);
2048
2049         printf("%s", get_strbuf_str(&line));
2050 }
2051
2052 void print_all_paths(vector pathvec, int banner)
2053 {
2054         print_all_paths_custo(pathvec, banner, PRINT_PATH_LONG);
2055 }