Imported Upstream version 2.02.79
[platform/upstream/device-mapper.git] / tools / dmsetup.c
1 /*
2  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3  * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
4  * Copyright (C) 2005-2007 NEC Corporation
5  *
6  * This file is part of the device-mapper userspace tools.
7  *
8  * It includes tree drawing code based on pstree: http://psmisc.sourceforge.net/
9  *
10  * This copyrighted material is made available to anyone wishing to use,
11  * modify, copy, or redistribute it subject to the terms and conditions
12  * of the GNU General Public License v.2.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #define _GNU_SOURCE
20 #define _FILE_OFFSET_BITS 64
21
22 #include "configure.h"
23
24 #include "dm-logging.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <dirent.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <libgen.h>
34 #include <sys/wait.h>
35 #include <unistd.h>
36 #include <sys/param.h>
37 #include <locale.h>
38 #include <langinfo.h>
39 #include <time.h>
40
41 #include <fcntl.h>
42 #include <sys/stat.h>
43
44 #ifdef UDEV_SYNC_SUPPORT
45 #  include <sys/types.h>
46 #  include <sys/ipc.h>
47 #  include <sys/sem.h>
48 #  define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
49 #  include <libudev.h>
50 #endif
51
52 /* FIXME Unused so far */
53 #undef HAVE_SYS_STATVFS_H
54
55 #ifdef HAVE_SYS_STATVFS_H
56 #  include <sys/statvfs.h>
57 #endif
58
59 #ifdef HAVE_SYS_IOCTL_H
60 #  include <sys/ioctl.h>
61 #endif
62
63 #if HAVE_TERMIOS_H
64 #  include <termios.h>
65 #endif
66
67 #ifdef HAVE_GETOPTLONG
68 #  include <getopt.h>
69 #  define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))
70 #  define OPTIND_INIT 0
71 #else
72 struct option {
73 };
74 extern int optind;
75 extern char *optarg;
76 #  define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))
77 #  define OPTIND_INIT 1
78 #endif
79
80 #ifndef TEMP_FAILURE_RETRY
81 # define TEMP_FAILURE_RETRY(expression) \
82   (__extension__                                                              \
83     ({ long int __result;                                                     \
84        do __result = (long int) (expression);                                 \
85        while (__result == -1L && errno == EINTR);                             \
86        __result; }))
87 #endif
88
89 #ifdef linux
90 #  include "kdev_t.h"
91 #else
92 #  define MAJOR(x) major((x))
93 #  define MINOR(x) minor((x))
94 #  define MKDEV(x,y) makedev((x),(y))
95 #endif
96
97 #define LINE_SIZE 4096
98 #define ARGS_MAX 256
99 #define LOOP_TABLE_SIZE (PATH_MAX + 255)
100
101 #define DEFAULT_DM_DEV_DIR "/dev/"
102
103 #define DM_DEV_DIR_ENV_VAR_NAME "DM_DEV_DIR"
104 #define DM_UDEV_COOKIE_ENV_VAR_NAME "DM_UDEV_COOKIE"
105
106 /* FIXME Should be imported */
107 #ifndef DM_MAX_TYPE_NAME
108 #  define DM_MAX_TYPE_NAME 16
109 #endif
110
111 /* FIXME Should be elsewhere */
112 #define SECTOR_SHIFT 9L
113
114 #define err(msg, x...) fprintf(stderr, msg "\n", ##x)
115
116 /*
117  * We have only very simple switches ATM.
118  */
119 enum {
120         READ_ONLY = 0,
121         COLS_ARG,
122         EXEC_ARG,
123         FORCE_ARG,
124         GID_ARG,
125         HELP_ARG,
126         INACTIVE_ARG,
127         MAJOR_ARG,
128         MINOR_ARG,
129         MODE_ARG,
130         NAMEPREFIXES_ARG,
131         NOFLUSH_ARG,
132         NOHEADINGS_ARG,
133         NOLOCKFS_ARG,
134         NOOPENCOUNT_ARG,
135         NOTABLE_ARG,
136         UDEVCOOKIE_ARG,
137         NOUDEVRULES_ARG,
138         NOUDEVSYNC_ARG,
139         OPTIONS_ARG,
140         READAHEAD_ARG,
141         ROWS_ARG,
142         SEPARATOR_ARG,
143         SETUUID_ARG,
144         SHOWKEYS_ARG,
145         SORT_ARG,
146         TABLE_ARG,
147         TARGET_ARG,
148         TREE_ARG,
149         UID_ARG,
150         UNBUFFERED_ARG,
151         UNQUOTED_ARG,
152         UUID_ARG,
153         VERBOSE_ARG,
154         VERSION_ARG,
155         YES_ARG,
156         NUM_SWITCHES
157 };
158
159 typedef enum {
160         DR_TASK = 1,
161         DR_INFO = 2,
162         DR_DEPS = 4,
163         DR_TREE = 8,    /* Complete dependency tree required */
164         DR_NAME = 16
165 } report_type_t;
166
167 static int _switches[NUM_SWITCHES];
168 static int _int_args[NUM_SWITCHES];
169 static char *_string_args[NUM_SWITCHES];
170 static int _num_devices;
171 static char *_uuid;
172 static char *_table;
173 static char *_target;
174 static char *_command;
175 static uint32_t _read_ahead_flags;
176 static uint32_t _udev_cookie;
177 static int _udev_only;
178 static struct dm_tree *_dtree;
179 static struct dm_report *_report;
180 static report_type_t _report_type;
181
182 /*
183  * Commands
184  */
185
186 typedef int (*command_fn) (int argc, char **argv, void *data);
187
188 struct command {
189         const char *name;
190         const char *help;
191         int min_args;
192         int max_args;
193         command_fn fn;
194 };
195
196 static int _parse_line(struct dm_task *dmt, char *buffer, const char *file,
197                        int line)
198 {
199         char ttype[LINE_SIZE], *ptr, *comment;
200         unsigned long long start, size;
201         int n;
202
203         /* trim trailing space */
204         for (ptr = buffer + strlen(buffer) - 1; ptr >= buffer; ptr--)
205                 if (!isspace((int) *ptr))
206                         break;
207         ptr++;
208         *ptr = '\0';
209
210         /* trim leading space */
211         for (ptr = buffer; *ptr && isspace((int) *ptr); ptr++)
212                 ;
213
214         if (!*ptr || *ptr == '#')
215                 return 1;
216
217         if (sscanf(ptr, "%llu %llu %s %n",
218                    &start, &size, ttype, &n) < 3) {
219                 err("Invalid format on line %d of table %s", line, file);
220                 return 0;
221         }
222
223         ptr += n;
224         if ((comment = strchr(ptr, (int) '#')))
225                 *comment = '\0';
226
227         if (!dm_task_add_target(dmt, start, size, ttype, ptr))
228                 return 0;
229
230         return 1;
231 }
232
233 static int _parse_file(struct dm_task *dmt, const char *file)
234 {
235         char *buffer = NULL;
236         size_t buffer_size = 0;
237         FILE *fp;
238         int r = 0, line = 0;
239
240         /* one-line table on cmdline */
241         if (_table)
242                 return _parse_line(dmt, _table, "", ++line);
243
244         /* OK for empty stdin */
245         if (file) {
246                 if (!(fp = fopen(file, "r"))) {
247                         err("Couldn't open '%s' for reading", file);
248                         return 0;
249                 }
250         } else
251                 fp = stdin;
252
253 #ifndef HAVE_GETLINE
254         buffer_size = LINE_SIZE;
255         if (!(buffer = dm_malloc(buffer_size))) {
256                 err("Failed to malloc line buffer.");
257                 return 0;
258         }
259
260         while (fgets(buffer, (int) buffer_size, fp))
261 #else
262         while (getline(&buffer, &buffer_size, fp) > 0)
263 #endif
264                 if (!_parse_line(dmt, buffer, file ? : "on stdin", ++line))
265                         goto out;
266
267         r = 1;
268
269       out:
270         memset(buffer, 0, buffer_size);
271 #ifndef HAVE_GETLINE
272         dm_free(buffer);
273 #else
274         free(buffer);
275 #endif
276         if (file && fclose(fp))
277                 fprintf(stderr, "%s: fclose failed: %s", file, strerror(errno));
278
279         return r;
280 }
281
282 struct dm_split_name {
283         char *subsystem;
284         char *vg_name;
285         char *lv_name;
286         char *lv_layer;
287 };
288
289 struct dmsetup_report_obj {
290         struct dm_task *task;
291         struct dm_info *info;
292         struct dm_task *deps_task;
293         struct dm_tree_node *tree_node;
294         struct dm_split_name *split_name;
295 };
296
297 static struct dm_task *_get_deps_task(int major, int minor)
298 {
299         struct dm_task *dmt;
300         struct dm_info info;
301
302         if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
303                 return NULL;
304
305         if (!dm_task_set_major(dmt, major) ||
306             !dm_task_set_minor(dmt, minor))
307                 goto err;
308
309         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
310                 goto err;
311
312         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
313                 goto err;
314
315         if (!dm_task_run(dmt))
316                 goto err;
317
318         if (!dm_task_get_info(dmt, &info))
319                 goto err;
320
321         if (!info.exists)
322                 goto err;
323
324         return dmt;
325
326       err:
327         dm_task_destroy(dmt);
328         return NULL;
329 }
330
331 static char *_extract_uuid_prefix(const char *uuid, const int separator)
332 {
333         char *ptr = NULL;
334         char *uuid_prefix = NULL;
335         size_t len;
336
337         if (uuid)
338                 ptr = strchr(uuid, separator);
339
340         len = ptr ? ptr - uuid : 0;
341         if (!(uuid_prefix = dm_malloc(len + 1))) {
342                 log_error("Failed to allocate memory to extract uuid prefix.");
343                 return NULL;
344         }
345
346         if (uuid)
347                 memcpy(uuid_prefix, uuid, len);
348
349         uuid_prefix[len] = '\0';
350
351         return uuid_prefix;
352 }
353
354 static struct dm_split_name *_get_split_name(const char *uuid, const char *name,
355                                              int separator)
356 {
357         struct dm_split_name *split_name;
358
359         if (!(split_name = dm_malloc(sizeof(*split_name)))) {
360                 log_error("Failed to allocate memory to split device name "
361                           "into components.");
362                 return NULL;
363         }
364
365         split_name->subsystem = _extract_uuid_prefix(uuid, separator);
366         split_name->vg_name = split_name->lv_name =
367             split_name->lv_layer = (char *) "";
368
369         if (!strcmp(split_name->subsystem, "LVM") &&
370             (!(split_name->vg_name = dm_strdup(name)) ||
371              !dm_split_lvm_name(NULL, NULL, &split_name->vg_name,
372                                 &split_name->lv_name, &split_name->lv_layer)))
373                 log_error("Failed to allocate memory to split LVM name "
374                           "into components.");
375
376         return split_name;
377 }
378
379 static void _destroy_split_name(struct dm_split_name *split_name)
380 {
381         /*
382          * lv_name and lv_layer are allocated within the same block
383          * of memory as vg_name so don't need to be freed separately.
384          */
385         if (!strcmp(split_name->subsystem, "LVM"))
386                 dm_free(split_name->vg_name);
387
388         dm_free(split_name->subsystem);
389         dm_free(split_name);
390 }
391
392 static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
393 {
394         struct dmsetup_report_obj obj;
395         int r = 0;
396
397         if (!info->exists) {
398                 fprintf(stderr, "Device does not exist.\n");
399                 return 0;
400         }
401
402         obj.task = dmt;
403         obj.info = info;
404         obj.deps_task = NULL;
405         obj.split_name = NULL;
406
407         if (_report_type & DR_TREE)
408                 obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor);
409
410         if (_report_type & DR_DEPS)
411                 obj.deps_task = _get_deps_task(info->major, info->minor);
412
413         if (_report_type & DR_NAME)
414                 obj.split_name = _get_split_name(dm_task_get_uuid(dmt), dm_task_get_name(dmt), '-');
415
416         if (!dm_report_object(_report, &obj))
417                 goto out;
418
419         r = 1;
420
421       out:
422         if (obj.deps_task)
423                 dm_task_destroy(obj.deps_task);
424         if (obj.split_name)
425                 _destroy_split_name(obj.split_name);
426         return r;
427 }
428
429 static void _display_info_long(struct dm_task *dmt, struct dm_info *info)
430 {
431         const char *uuid;
432         uint32_t read_ahead;
433
434         if (!info->exists) {
435                 printf("Device does not exist.\n");
436                 return;
437         }
438
439         printf("Name:              %s\n", dm_task_get_name(dmt));
440
441         printf("State:             %s%s\n",
442                info->suspended ? "SUSPENDED" : "ACTIVE",
443                info->read_only ? " (READ-ONLY)" : "");
444
445         /* FIXME Old value is being printed when it's being changed. */
446         if (dm_task_get_read_ahead(dmt, &read_ahead))
447                 printf("Read Ahead:        %" PRIu32 "\n", read_ahead);
448
449         if (!info->live_table && !info->inactive_table)
450                 printf("Tables present:    None\n");
451         else
452                 printf("Tables present:    %s%s%s\n",
453                        info->live_table ? "LIVE" : "",
454                        info->live_table && info->inactive_table ? " & " : "",
455                        info->inactive_table ? "INACTIVE" : "");
456
457         if (info->open_count != -1)
458                 printf("Open count:        %d\n", info->open_count);
459
460         printf("Event number:      %" PRIu32 "\n", info->event_nr);
461         printf("Major, minor:      %d, %d\n", info->major, info->minor);
462
463         if (info->target_count != -1)
464                 printf("Number of targets: %d\n", info->target_count);
465
466         if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
467                 printf("UUID: %s\n", uuid);
468
469         printf("\n");
470 }
471
472 static int _display_info(struct dm_task *dmt)
473 {
474         struct dm_info info;
475
476         if (!dm_task_get_info(dmt, &info))
477                 return 0;
478
479         if (!_switches[COLS_ARG])
480                 _display_info_long(dmt, &info);
481         else
482                 /* FIXME return code */
483                 _display_info_cols(dmt, &info);
484
485         return info.exists ? 1 : 0;
486 }
487
488 static int _set_task_device(struct dm_task *dmt, const char *name, int optional)
489 {
490         if (name) {
491                 if (!dm_task_set_name(dmt, name))
492                         return 0;
493         } else if (_switches[UUID_ARG]) {
494                 if (!dm_task_set_uuid(dmt, _uuid))
495                         return 0;
496         } else if (_switches[MAJOR_ARG] && _switches[MINOR_ARG]) {
497                 if (!dm_task_set_major(dmt, _int_args[MAJOR_ARG]) ||
498                     !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))
499                         return 0;
500         } else if (!optional) {
501                 fprintf(stderr, "No device specified.\n");
502                 return 0;
503         }
504
505         return 1;
506 }
507
508 static int _load(int argc, char **argv, void *data __attribute__((unused)))
509 {
510         int r = 0;
511         struct dm_task *dmt;
512         const char *file = NULL;
513         const char *name = NULL;
514
515         if (_switches[NOTABLE_ARG]) {
516                 err("--notable only available when creating new device\n");
517                 return 0;
518         }
519
520         if (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]) {
521                 if (argc == 1) {
522                         err("Please specify device.\n");
523                         return 0;
524                 }
525                 name = argv[1];
526                 argc--;
527                 argv++;
528         } else if (argc > 2) {
529                 err("Too many command line arguments.\n");
530                 return 0;
531         }
532
533         if (argc == 2)
534                 file = argv[1];
535
536         if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
537                 return 0;
538
539         if (!_set_task_device(dmt, name, 0))
540                 goto out;
541
542         if (!_switches[NOTABLE_ARG] && !_parse_file(dmt, file))
543                 goto out;
544
545         if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
546                 goto out;
547
548         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
549                 goto out;
550
551         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
552                 goto out;
553
554         if (!dm_task_run(dmt))
555                 goto out;
556
557         r = 1;
558
559         if (_switches[VERBOSE_ARG])
560                 r = _display_info(dmt);
561
562       out:
563         dm_task_destroy(dmt);
564
565         return r;
566 }
567
568 static int _create(int argc, char **argv, void *data __attribute__((unused)))
569 {
570         int r = 0;
571         struct dm_task *dmt;
572         const char *file = NULL;
573         uint32_t cookie = 0;
574         uint16_t udev_flags = 0;
575
576         if (argc == 3)
577                 file = argv[2];
578
579         if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
580                 return 0;
581
582         if (!dm_task_set_name(dmt, argv[1]))
583                 goto out;
584
585         if (_switches[UUID_ARG] && !dm_task_set_uuid(dmt, _uuid))
586                 goto out;
587
588         if (!_switches[NOTABLE_ARG] && !_parse_file(dmt, file))
589                 goto out;
590
591         if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
592                 goto out;
593
594         if (_switches[MAJOR_ARG] && !dm_task_set_major(dmt, _int_args[MAJOR_ARG]))
595                 goto out;
596
597         if (_switches[MINOR_ARG] && !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))
598                 goto out;
599
600         if (_switches[UID_ARG] && !dm_task_set_uid(dmt, _int_args[UID_ARG]))
601                 goto out;
602
603         if (_switches[GID_ARG] && !dm_task_set_gid(dmt, _int_args[GID_ARG]))
604                 goto out;
605
606         if (_switches[MODE_ARG] && !dm_task_set_mode(dmt, _int_args[MODE_ARG]))
607                 goto out;
608
609         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
610                 goto out;
611
612         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
613                 goto out;
614
615         if (_switches[READAHEAD_ARG] &&
616             !dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG],
617                                     _read_ahead_flags))
618                 goto out;
619
620         if (_switches[NOTABLE_ARG])
621                 dm_udev_set_sync_support(0);
622
623         if (_switches[NOUDEVRULES_ARG])
624                 udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
625                               DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
626
627         if (_udev_cookie) {
628                 cookie = _udev_cookie;
629                 if (_udev_only)
630                         udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
631         }
632
633         if (!dm_task_set_cookie(dmt, &cookie, udev_flags) ||
634             !dm_task_run(dmt))
635                 goto out;
636
637         r = 1;
638
639         if (!_udev_cookie)
640                 (void) dm_udev_wait(cookie);
641
642         if (_switches[VERBOSE_ARG])
643                 r = _display_info(dmt);
644
645         dm_task_destroy(dmt);
646
647         return r;
648
649       out:
650         if (!_udev_cookie)
651                 (void) dm_udev_wait(cookie);
652         dm_task_destroy(dmt);
653
654         return r;
655 }
656
657 static int _rename(int argc, char **argv, void *data __attribute__((unused)))
658 {
659         int r = 0;
660         struct dm_task *dmt;
661         uint32_t cookie = 0;
662         uint16_t udev_flags = 0;
663
664         if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))
665                 return 0;
666
667         /* FIXME Kernel doesn't support uuid or device number here yet */
668         if (!_set_task_device(dmt, (argc == 3) ? argv[1] : NULL, 0))
669                 goto out;
670
671         if (_switches[SETUUID_ARG]) {
672                 if  (!dm_task_set_newuuid(dmt, argv[argc - 1]))
673                         goto out;
674         } else if (!dm_task_set_newname(dmt, argv[argc - 1]))
675                 goto out;
676
677         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
678                 goto out;
679
680         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
681                 goto out;
682
683         if (_switches[NOUDEVRULES_ARG])
684                 udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
685                               DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
686
687         if (_udev_cookie) {
688                 cookie = _udev_cookie;
689                 if (_udev_only)
690                         udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
691         }
692
693         if (!dm_task_set_cookie(dmt, &cookie, udev_flags) ||
694             !dm_task_run(dmt))
695                 goto out;
696
697         r = 1;
698
699       out:
700         if (!_udev_cookie)
701                 (void) dm_udev_wait(cookie);
702         dm_task_destroy(dmt);
703
704         return r;
705 }
706
707 static int _message(int argc, char **argv, void *data __attribute__((unused)))
708 {
709         int r = 0, i;
710         size_t sz = 1;
711         struct dm_task *dmt;
712         char *str;
713
714         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
715                 return 0;
716
717         if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {
718                 if (!_set_task_device(dmt, NULL, 0))
719                         goto out;
720         } else {
721                 if (!_set_task_device(dmt, argv[1], 0))
722                         goto out;
723                 argc--;
724                 argv++;
725         }
726
727         if (!dm_task_set_sector(dmt, (uint64_t) atoll(argv[1])))
728                 goto out;
729
730         argc -= 2;
731         argv += 2;
732
733         if (argc <= 0)
734                 err("No message supplied.\n");
735
736         for (i = 0; i < argc; i++)
737                 sz += strlen(argv[i]) + 1;
738
739         if (!(str = dm_zalloc(sz))) {
740                 err("message string allocation failed");
741                 goto out;
742         }
743
744         for (i = 0; i < argc; i++) {
745                 if (i)
746                         strcat(str, " ");
747                 strcat(str, argv[i]);
748         }
749
750         if (!dm_task_set_message(dmt, str))
751                 goto out;
752
753         dm_free(str);
754
755         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
756                 goto out;
757
758         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
759                 goto out;
760
761         if (!dm_task_run(dmt))
762                 goto out;
763
764         r = 1;
765
766       out:
767         dm_task_destroy(dmt);
768
769         return r;
770 }
771
772 static int _setgeometry(int argc, char **argv, void *data __attribute__((unused)))
773 {
774         int r = 0;
775         struct dm_task *dmt;
776
777         if (!(dmt = dm_task_create(DM_DEVICE_SET_GEOMETRY)))
778                 return 0;
779
780         if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {
781                 if (!_set_task_device(dmt, NULL, 0))
782                         goto out;
783         } else {
784                 if (!_set_task_device(dmt, argv[1], 0))
785                         goto out;
786                 argc--;
787                 argv++;
788         }
789
790         if (!dm_task_set_geometry(dmt, argv[1], argv[2], argv[3], argv[4]))
791                 goto out;
792
793         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
794                 goto out;
795
796         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
797                 goto out;
798
799         /* run the task */
800         if (!dm_task_run(dmt))
801                 goto out;
802
803         r = 1;
804
805       out:
806         dm_task_destroy(dmt);
807
808         return r;
809 }
810
811 static int _splitname(int argc, char **argv, void *data __attribute__((unused)))
812 {
813         struct dmsetup_report_obj obj;
814         int r = 1;
815
816         obj.task = NULL;
817         obj.info = NULL;
818         obj.deps_task = NULL;
819         obj.tree_node = NULL;
820         obj.split_name = _get_split_name((argc == 3) ? argv[2] : "LVM",
821                                          argv[1], '\0');
822
823         r = dm_report_object(_report, &obj);
824         _destroy_split_name(obj.split_name);
825
826         return r;
827 }
828
829 static uint32_t _get_cookie_value(const char *str_value)
830 {
831         unsigned long int value;
832         char *p;
833
834         if (!(value = strtoul(str_value, &p, 0)) ||
835             *p ||
836             (value == ULONG_MAX && errno == ERANGE) ||
837             value > 0xFFFFFFFF) {
838                 err("Incorrect cookie value");
839                 return 0;
840         }
841         else
842                 return (uint32_t) value;
843 }
844
845 static int _udevflags(int args, char **argv, void *data __attribute__((unused)))
846 {
847         uint32_t cookie;
848         uint16_t flags;
849         int i;
850         static const char *dm_flag_names[] = {"DISABLE_DM_RULES",
851                                               "DISABLE_SUBSYSTEM_RULES",
852                                               "DISABLE_DISK_RULES",
853                                               "DISABLE_OTHER_RULES",
854                                               "LOW_PRIORITY",
855                                               "DISABLE_LIBRARY_FALLBACK",
856                                               "PRIMARY_SOURCE",
857                                                0};
858
859         if (!(cookie = _get_cookie_value(argv[1])))
860                 return 0;
861
862         flags = cookie >> DM_UDEV_FLAGS_SHIFT;
863
864         for (i = 0; i < DM_UDEV_FLAGS_SHIFT; i++)
865                 if (1 << i & flags) {
866                         if (i < DM_UDEV_FLAGS_SHIFT / 2 && dm_flag_names[i])
867                                 printf("DM_UDEV_%s_FLAG='1'\n", dm_flag_names[i]);
868                         else if (i < DM_UDEV_FLAGS_SHIFT / 2)
869                                 /*
870                                  * This is just a fallback. Each new DM flag
871                                  * should have its symbolic name assigned.
872                                  */
873                                 printf("DM_UDEV_FLAG%d='1'\n", i);
874                         else
875                                 /*
876                                  * We can't assign symbolic names to subsystem
877                                  * flags. Their semantics vary based on the
878                                  * subsystem that is currently used.
879                                  */
880                                 printf("DM_SUBSYSTEM_UDEV_FLAG%d='1'\n",
881                                         i - DM_UDEV_FLAGS_SHIFT / 2);
882                 }
883
884         return 1;
885 }
886
887 static int _udevcomplete(int argc, char **argv, void *data __attribute__((unused)))
888 {
889         uint32_t cookie;
890
891         if (!(cookie = _get_cookie_value(argv[1])))
892                 return 0;
893
894         /*
895          * Strip flags from the cookie and use cookie magic instead.
896          * If the cookie has non-zero prefix and the base is zero then
897          * this one carries flags to control udev rules only and it is
898          * not meant to be for notification. Return with success in this
899          * situation.
900          */
901         if (!(cookie &= ~DM_UDEV_FLAGS_MASK))
902                 return 1;
903
904         cookie |= DM_COOKIE_MAGIC << DM_UDEV_FLAGS_SHIFT;
905
906         return dm_udev_complete(cookie);
907 }
908
909 #ifndef UDEV_SYNC_SUPPORT
910 static const char _cmd_not_supported[] = "Command not supported. Recompile with \"--enable-udev-sync\" to enable.";
911
912 static int _udevcreatecookie(int argc, char **argv,
913                                   void *data __attribute__((unused)))
914 {
915         log_error(_cmd_not_supported);
916
917         return 0;
918 }
919
920 static int _udevreleasecookie(int argc, char **argv,
921                                 void *data __attribute__((unused)))
922 {
923         log_error(_cmd_not_supported);
924
925         return 0;
926 }
927
928 static int _udevcomplete_all(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
929 {
930         log_error(_cmd_not_supported);
931
932         return 0;
933 }
934
935 static int _udevcookies(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
936 {
937         log_error(_cmd_not_supported);
938
939         return 0;
940 }
941
942 #else   /* UDEV_SYNC_SUPPORT */
943 static int _set_up_udev_support(const char *dev_dir)
944 {
945         struct udev *udev;
946         const char *udev_dev_dir;
947         size_t udev_dev_dir_len;
948         int dirs_diff;
949         const char *env;
950
951         if (_switches[NOUDEVSYNC_ARG])
952                 dm_udev_set_sync_support(0);
953
954         if (!_udev_cookie) {
955                 env = getenv(DM_UDEV_COOKIE_ENV_VAR_NAME);
956                 if (env && *env && (_udev_cookie = _get_cookie_value(env)))
957                         log_debug("Using udev transaction 0x%08" PRIX32
958                                   " defined by %s environment variable.",
959                                    _udev_cookie,
960                                    DM_UDEV_COOKIE_ENV_VAR_NAME);
961         }
962         else if (_switches[UDEVCOOKIE_ARG])
963                 log_debug("Using udev transaction 0x%08" PRIX32
964                           " defined by --udevcookie option.",
965                           _udev_cookie);
966
967         if (!(udev = udev_new()) ||
968             !(udev_dev_dir = udev_get_dev_path(udev)) ||
969             !*udev_dev_dir) {
970                 log_error("Could not get udev dev path.");
971                 return 0;
972         }
973         udev_dev_dir_len = strlen(udev_dev_dir);
974
975         /*
976          * Normally, there's always a fallback action by libdevmapper if udev
977          * has not done its job correctly, e.g. the nodes were not created.
978          * If using udev transactions by specifying existing cookie value,
979          * we need to disable node creation by libdevmapper completely,
980          * disabling any fallback actions, since any synchronisation happens
981          * at the end of the transaction only. We need to do this to prevent
982          * races between udev and libdevmapper but only in case udev "dev path"
983          * is the same as "dev path" used by libdevmapper.
984          */
985
986         /* There's always a slash at the end of dev_dir. But check udev_dev_dir! */
987         if (udev_dev_dir[udev_dev_dir_len - 1] != '/')
988                 dirs_diff = strncmp(dev_dir, udev_dev_dir, udev_dev_dir_len);
989         else
990                 dirs_diff = strcmp(dev_dir, udev_dev_dir);
991
992         _udev_only = _udev_cookie && !dirs_diff;
993
994         if (dirs_diff) {
995                 log_debug("The path %s used for creating device nodes that is "
996                           "set via DM_DEV_DIR environment variable differs from "
997                           "the path %s that is used by udev. All warnings "
998                           "about udev not working correctly while processing "
999                           "particular nodes will be suppressed. These nodes "
1000                           "and symlinks will be managed in each directory "
1001                           "separately.", dev_dir, udev_dev_dir);
1002                 dm_udev_set_checking(0);
1003         }
1004
1005         udev_unref(udev);
1006         return 1;
1007 }
1008
1009 static int _udevcreatecookie(int argc, char **argv,
1010                                   void *data __attribute__((unused)))
1011 {
1012         uint32_t cookie;
1013
1014         if (!dm_udev_create_cookie(&cookie))
1015                 return 0;
1016
1017         if (cookie)
1018                 printf("0x%08" PRIX32 "\n", cookie);
1019
1020         return 1;
1021 }
1022
1023 static int _udevreleasecookie(int argc, char **argv,
1024                                 void *data __attribute__((unused)))
1025 {
1026         if (argv[1] && !(_udev_cookie = _get_cookie_value(argv[1])))
1027                 return 0;
1028
1029         if (!_udev_cookie) {
1030                 log_error("No udev transaction cookie given.");
1031                 return 0;
1032         }
1033
1034         return dm_udev_wait(_udev_cookie);
1035 }
1036
1037 static char _yes_no_prompt(const char *prompt, ...)
1038 {
1039         int c = 0, ret = 0;
1040         va_list ap;
1041
1042         do {
1043                 if (c == '\n' || !c) {
1044                         va_start(ap, prompt);
1045                         vprintf(prompt, ap);
1046                         va_end(ap);
1047                 }
1048
1049                 if ((c = getchar()) == EOF) {
1050                         ret = 'n';
1051                         break;
1052                 }
1053
1054                 c = tolower(c);
1055                 if ((c == 'y') || (c == 'n'))
1056                         ret = c;
1057         } while (!ret || c != '\n');
1058
1059         if (c != '\n')
1060                 printf("\n");
1061
1062         return ret;
1063 }
1064
1065 static int _udevcomplete_all(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
1066 {
1067         int max_id, id, sid;
1068         struct seminfo sinfo;
1069         struct semid_ds sdata;
1070         int counter = 0;
1071
1072         if (!_switches[YES_ARG]) {
1073                 log_warn("This operation will destroy all semaphores with keys "
1074                          "that have a prefix %" PRIu16 " (0x%" PRIx16 ").",
1075                          DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
1076
1077                 if (_yes_no_prompt("Do you really want to continue? [y/n]: ") == 'n') {
1078                         log_print("Semaphores with keys prefixed by %" PRIu16
1079                                   " (0x%" PRIx16 ") NOT destroyed.",
1080                                   DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
1081                         return 1;
1082                 }
1083         }
1084
1085         if ((max_id = semctl(0, 0, SEM_INFO, &sinfo)) < 0) {
1086                 log_sys_error("semctl", "SEM_INFO");
1087                 return 0;
1088         }
1089
1090         for (id = 0; id <= max_id; id++) {
1091                 if ((sid = semctl(id, 0, SEM_STAT, &sdata)) < 0)
1092                         continue;
1093
1094                 if (sdata.sem_perm.__key >> 16 == DM_COOKIE_MAGIC) {
1095                         if (semctl(sid, 0, IPC_RMID, 0) < 0) {
1096                                 log_error("Could not cleanup notification semaphore "
1097                                           "with semid %d and cookie value "
1098                                           "%" PRIu32 " (0x%" PRIx32 ")", sid,
1099                                           sdata.sem_perm.__key, sdata.sem_perm.__key);
1100                                 continue;
1101                         }
1102
1103                         counter++;
1104                 }
1105         }
1106
1107         log_print("%d semaphores with keys prefixed by "
1108                   "%" PRIu16 " (0x%" PRIx16 ") destroyed.",
1109                   counter, DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
1110
1111         return 1;
1112 }
1113
1114 static int _udevcookies(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
1115 {
1116         int max_id, id, sid;
1117         struct seminfo sinfo;
1118         struct semid_ds sdata;
1119         int val;
1120         char *time_str;
1121
1122         if ((max_id = semctl(0, 0, SEM_INFO, &sinfo)) < 0) {
1123                 log_sys_error("sem_ctl", "SEM_INFO");
1124                 return 0;
1125         }
1126
1127         printf("cookie       semid      value      last_semop_time\n");
1128
1129         for (id = 0; id <= max_id; id++) {
1130                 if ((sid = semctl(id, 0, SEM_STAT, &sdata)) < 0)
1131                         continue;
1132
1133                 if (sdata.sem_perm.__key >> 16 == DM_COOKIE_MAGIC) {
1134                         if ((val = semctl(sid, 0, GETVAL)) < 0) {
1135                                 log_error("semid %d: sem_ctl failed for "
1136                                           "cookie 0x%" PRIx32 ": %s",
1137                                           sid, sdata.sem_perm.__key,
1138                                           strerror(errno));
1139                                 continue;
1140                         }
1141
1142                         time_str = ctime((const time_t *) &sdata.sem_otime);
1143
1144                         printf("0x%-10x %-10d %-10d %s", sdata.sem_perm.__key,
1145                                 sid, val, time_str ? time_str : "unknown\n");
1146                 }
1147         }
1148
1149         return 1;
1150 }
1151 #endif  /* UDEV_SYNC_SUPPORT */
1152
1153 static int _version(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
1154 {
1155         char version[80];
1156
1157         if (dm_get_library_version(version, sizeof(version)))
1158                 printf("Library version:   %s\n", version);
1159
1160         if (!dm_driver_version(version, sizeof(version)))
1161                 return 0;
1162
1163         printf("Driver version:    %s\n", version);
1164
1165         return 1;
1166 }
1167
1168 static int _simple(int task, const char *name, uint32_t event_nr, int display)
1169 {
1170         uint32_t cookie = 0;
1171         uint16_t udev_flags = 0;
1172         int udev_wait_flag = task == DM_DEVICE_RESUME ||
1173                              task == DM_DEVICE_REMOVE;
1174         int r = 0;
1175
1176         struct dm_task *dmt;
1177
1178         if (!(dmt = dm_task_create(task)))
1179                 return 0;
1180
1181         if (!_set_task_device(dmt, name, 0))
1182                 goto out;
1183
1184         if (event_nr && !dm_task_set_event_nr(dmt, event_nr))
1185                 goto out;
1186
1187         if (_switches[NOFLUSH_ARG] && !dm_task_no_flush(dmt))
1188                 goto out;
1189
1190         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
1191                 goto out;
1192
1193         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
1194                 goto out;
1195
1196         if (_switches[NOLOCKFS_ARG] && !dm_task_skip_lockfs(dmt))
1197                 goto out;
1198
1199         if (_switches[READAHEAD_ARG] &&
1200             !dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG],
1201                                     _read_ahead_flags))
1202                 goto out;
1203
1204         if (_switches[NOUDEVRULES_ARG])
1205                 udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
1206                               DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
1207
1208         if (_udev_cookie) {
1209                 cookie = _udev_cookie;
1210                 if (_udev_only)
1211                         udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
1212         }
1213
1214         if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags))
1215                 goto out;
1216
1217         r = dm_task_run(dmt);
1218
1219         if (r && display && _switches[VERBOSE_ARG])
1220                 r = _display_info(dmt);
1221
1222       out:
1223         if (!_udev_cookie && udev_wait_flag)
1224                 (void) dm_udev_wait(cookie);
1225
1226         dm_task_destroy(dmt);
1227         return r;
1228 }
1229
1230 static int _suspend(int argc, char **argv, void *data __attribute__((unused)))
1231 {
1232         return _simple(DM_DEVICE_SUSPEND, argc > 1 ? argv[1] : NULL, 0, 1);
1233 }
1234
1235 static int _resume(int argc, char **argv, void *data __attribute__((unused)))
1236 {
1237         return _simple(DM_DEVICE_RESUME, argc > 1 ? argv[1] : NULL, 0, 1);
1238 }
1239
1240 static int _clear(int argc, char **argv, void *data __attribute__((unused)))
1241 {
1242         return _simple(DM_DEVICE_CLEAR, argc > 1 ? argv[1] : NULL, 0, 1);
1243 }
1244
1245 static int _wait(int argc, char **argv, void *data __attribute__((unused)))
1246 {
1247         const char *name = NULL;
1248
1249         if (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]) {
1250                 if (argc == 1) {
1251                         err("No device specified.");
1252                         return 0;
1253                 }
1254                 name = argv[1];
1255                 argc--, argv++;
1256         }
1257
1258         return _simple(DM_DEVICE_WAITEVENT, name,
1259                        (argc > 1) ? (uint32_t) atoi(argv[argc - 1]) : 0, 1);
1260 }
1261
1262 static int _process_all(int argc, char **argv, int silent,
1263                         int (*fn) (int argc, char **argv, void *data))
1264 {
1265         int r = 1;
1266         struct dm_names *names;
1267         unsigned next = 0;
1268
1269         struct dm_task *dmt;
1270
1271         if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
1272                 return 0;
1273
1274         if (!dm_task_run(dmt)) {
1275                 r = 0;
1276                 goto out;
1277         }
1278
1279         if (!(names = dm_task_get_names(dmt))) {
1280                 r = 0;
1281                 goto out;
1282         }
1283
1284         if (!names->dev) {
1285                 if (!silent)
1286                         printf("No devices found\n");
1287                 goto out;
1288         }
1289
1290         do {
1291                 names = (struct dm_names *)((char *) names + next);
1292                 if (!fn(argc, argv, names))
1293                         r = 0;
1294                 next = names->next;
1295         } while (next);
1296
1297       out:
1298         dm_task_destroy(dmt);
1299         return r;
1300 }
1301
1302 static uint64_t _get_device_size(const char *name)
1303 {
1304         uint64_t start, length, size = UINT64_C(0);
1305         struct dm_info info;
1306         char *target_type, *params;
1307         struct dm_task *dmt;
1308         void *next = NULL;
1309
1310         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
1311                 return 0;
1312
1313         if (!_set_task_device(dmt, name, 0))
1314                 goto out;
1315
1316         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
1317                 goto out;
1318
1319         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
1320                 goto out;
1321
1322         if (!dm_task_run(dmt))
1323                 goto out;
1324
1325         if (!dm_task_get_info(dmt, &info) || !info.exists)
1326                 goto out;
1327
1328         do {
1329                 next = dm_get_next_target(dmt, next, &start, &length,
1330                                           &target_type, &params);
1331                 size += length;
1332         } while (next);
1333
1334       out:
1335         dm_task_destroy(dmt);
1336         return size;
1337 }
1338
1339 static int _error_device(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data)
1340 {
1341         struct dm_names *names = (struct dm_names *) data;
1342         struct dm_task *dmt;
1343         const char *name;
1344         uint64_t size;
1345         int r = 0;
1346
1347         if (data)
1348                 name = names->name;
1349         else
1350                 name = argv[1];
1351
1352         size = _get_device_size(name);
1353
1354         if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
1355                 return 0;
1356
1357         if (!_set_task_device(dmt, name, 0))
1358                 goto error;
1359
1360         if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
1361                 goto error;
1362
1363         if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
1364                 goto error;
1365
1366         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
1367                 goto error;
1368
1369         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
1370                 goto error;
1371
1372         if (!dm_task_run(dmt))
1373                 goto error;
1374
1375         if (!_simple(DM_DEVICE_RESUME, name, 0, 0)) {
1376                 _simple(DM_DEVICE_CLEAR, name, 0, 0);
1377                 goto error;
1378         }
1379
1380         r = 1;
1381
1382 error:
1383         dm_task_destroy(dmt);
1384         return r;
1385 }
1386
1387 static int _remove(int argc, char **argv, void *data __attribute__((unused)))
1388 {
1389         if (_switches[FORCE_ARG] && argc > 1)
1390                 (void) _error_device(argc, argv, NULL);
1391
1392         return _simple(DM_DEVICE_REMOVE, argc > 1 ? argv[1] : NULL, 0, 0);
1393 }
1394
1395 static int _count_devices(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
1396 {
1397         _num_devices++;
1398
1399         return 1;
1400 }
1401
1402 static int _remove_all(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
1403 {
1404         int r;
1405
1406         /* Remove all closed devices */
1407         r =  _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
1408
1409         if (!_switches[FORCE_ARG])
1410                 return r;
1411
1412         _num_devices = 0;
1413         r |= _process_all(argc, argv, 1, _count_devices);
1414
1415         /* No devices left? */
1416         if (!_num_devices)
1417                 return r;
1418
1419         r |= _process_all(argc, argv, 1, _error_device);
1420         r |= _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
1421
1422         _num_devices = 0;
1423         r |= _process_all(argc, argv, 1, _count_devices);
1424         if (!_num_devices)
1425                 return r;
1426
1427         fprintf(stderr, "Unable to remove %d device(s).\n", _num_devices);
1428
1429         return r;
1430 }
1431
1432 static void _display_dev(struct dm_task *dmt, const char *name)
1433 {
1434         struct dm_info info;
1435
1436         if (dm_task_get_info(dmt, &info))
1437                 printf("%s\t(%u, %u)\n", name, info.major, info.minor);
1438 }
1439
1440 static int _mknodes(int argc, char **argv, void *data __attribute__((unused)))
1441 {
1442         return dm_mknodes(argc > 1 ? argv[1] : NULL);
1443 }
1444
1445 static int _exec_command(const char *name)
1446 {
1447         int n;
1448         static char path[PATH_MAX];
1449         static char *args[ARGS_MAX + 1];
1450         static int argc = 0;
1451         char *c;
1452         pid_t pid;
1453
1454         if (argc < 0)
1455                 return 0;
1456
1457         if (!dm_mknodes(name))
1458                 return 0;
1459
1460         n = snprintf(path, sizeof(path), "%s/%s", dm_dir(), name);
1461         if (n < 0 || n > (int) sizeof(path) - 1)
1462                 return 0;
1463
1464         if (!argc) {
1465                 c = _command;
1466                 while (argc < ARGS_MAX) {
1467                         while (*c && isspace(*c))
1468                                 c++;
1469                         if (!*c)
1470                                 break;
1471                         args[argc++] = c;
1472                         while (*c && !isspace(*c))
1473                                 c++;
1474                         if (*c)
1475                                 *c++ = '\0';
1476                 }
1477
1478                 if (!argc) {
1479                         argc = -1;
1480                         return 0;
1481                 }
1482
1483                 if (argc == ARGS_MAX) {
1484                         err("Too many args to --exec\n");
1485                         argc = -1;
1486                         return 0;
1487                 }
1488
1489                 args[argc++] = path;
1490                 args[argc] = NULL;
1491         }
1492
1493         if (!(pid = fork())) {
1494                 execvp(args[0], args);
1495                 _exit(127);
1496         } else if (pid < (pid_t) 0)
1497                 return 0;
1498
1499         TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
1500
1501         return 1;
1502 }
1503
1504 static int _status(int argc, char **argv, void *data)
1505 {
1506         int r = 0;
1507         struct dm_task *dmt;
1508         void *next = NULL;
1509         uint64_t start, length;
1510         char *target_type = NULL;
1511         char *params, *c;
1512         int cmd;
1513         struct dm_names *names = (struct dm_names *) data;
1514         const char *name = NULL;
1515         int matched = 0;
1516         int ls_only = 0;
1517         struct dm_info info;
1518
1519         if (data)
1520                 name = names->name;
1521         else {
1522                 if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
1523                         return _process_all(argc, argv, 0, _status);
1524                 if (argc == 2)
1525                         name = argv[1];
1526         }
1527
1528         if (!strcmp(argv[0], "table"))
1529                 cmd = DM_DEVICE_TABLE;
1530         else
1531                 cmd = DM_DEVICE_STATUS;
1532
1533         if (!strcmp(argv[0], "ls"))
1534                 ls_only = 1;
1535
1536         if (!(dmt = dm_task_create(cmd)))
1537                 return 0;
1538
1539         if (!_set_task_device(dmt, name, 0))
1540                 goto out;
1541
1542         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
1543                 goto out;
1544
1545         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
1546                 goto out;
1547
1548         if (!dm_task_run(dmt))
1549                 goto out;
1550
1551         if (!dm_task_get_info(dmt, &info) || !info.exists)
1552                 goto out;
1553
1554         if (!name)
1555                 name = dm_task_get_name(dmt);
1556
1557         /* Fetch targets and print 'em */
1558         do {
1559                 next = dm_get_next_target(dmt, next, &start, &length,
1560                                           &target_type, &params);
1561                 /* Skip if target type doesn't match */
1562                 if (_switches[TARGET_ARG] &&
1563                     (!target_type || strcmp(target_type, _target)))
1564                         continue;
1565                 if (ls_only) {
1566                         if (!_switches[EXEC_ARG] || !_command ||
1567                             _switches[VERBOSE_ARG])
1568                                 _display_dev(dmt, name);
1569                         next = NULL;
1570                 } else if (!_switches[EXEC_ARG] || !_command ||
1571                            _switches[VERBOSE_ARG]) {
1572                         if (!matched && _switches[VERBOSE_ARG])
1573                                 _display_info(dmt);
1574                         if (data && !_switches[VERBOSE_ARG])
1575                                 printf("%s: ", name);
1576                         if (target_type) {
1577                                 /* Suppress encryption key */
1578                                 if (!_switches[SHOWKEYS_ARG] &&
1579                                     cmd == DM_DEVICE_TABLE &&
1580                                     !strcmp(target_type, "crypt")) {
1581                                         c = params;
1582                                         while (*c && *c != ' ')
1583                                                 c++;
1584                                         if (*c)
1585                                                 c++;
1586                                         while (*c && *c != ' ')
1587                                                 *c++ = '0';
1588                                 }
1589                                 printf("%" PRIu64 " %" PRIu64 " %s %s",
1590                                        start, length, target_type, params);
1591                         }
1592                         printf("\n");
1593                 }
1594                 matched = 1;
1595         } while (next);
1596
1597         if (data && _switches[VERBOSE_ARG] && matched && !ls_only)
1598                 printf("\n");
1599
1600         if (matched && _switches[EXEC_ARG] && _command && !_exec_command(name))
1601                 goto out;
1602
1603         r = 1;
1604
1605       out:
1606         dm_task_destroy(dmt);
1607         return r;
1608 }
1609
1610 /* Show target names and their version numbers */
1611 static int _targets(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
1612 {
1613         int r = 0;
1614         struct dm_task *dmt;
1615         struct dm_versions *target;
1616         struct dm_versions *last_target;
1617
1618         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
1619                 return 0;
1620
1621         if (!dm_task_run(dmt))
1622                 goto out;
1623
1624         target = dm_task_get_versions(dmt);
1625
1626         /* Fetch targets and print 'em */
1627         do {
1628                 last_target = target;
1629
1630                 printf("%-16s v%d.%d.%d\n", target->name, target->version[0],
1631                        target->version[1], target->version[2]);
1632
1633                 target = (struct dm_versions *)((char *) target + target->next);
1634         } while (last_target != target);
1635
1636         r = 1;
1637
1638       out:
1639         dm_task_destroy(dmt);
1640         return r;
1641 }
1642
1643 static int _info(int argc, char **argv, void *data)
1644 {
1645         int r = 0;
1646
1647         struct dm_task *dmt;
1648         struct dm_names *names = (struct dm_names *) data;
1649         char *name = NULL;
1650
1651         if (data)
1652                 name = names->name;
1653         else {
1654                 if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
1655                         return _process_all(argc, argv, 0, _info);
1656                 if (argc == 2)
1657                         name = argv[1];
1658         }
1659
1660         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
1661                 return 0;
1662
1663         if (!_set_task_device(dmt, name, 0))
1664                 goto out;
1665
1666         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
1667                 goto out;
1668
1669         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
1670                 goto out;
1671
1672         if (!dm_task_run(dmt))
1673                 goto out;
1674
1675         r = _display_info(dmt);
1676
1677       out:
1678         dm_task_destroy(dmt);
1679         return r;
1680 }
1681
1682 static int _deps(int argc, char **argv, void *data)
1683 {
1684         int r = 0;
1685         uint32_t i;
1686         struct dm_deps *deps;
1687         struct dm_task *dmt;
1688         struct dm_info info;
1689         struct dm_names *names = (struct dm_names *) data;
1690         char *name = NULL;
1691
1692         if (data)
1693                 name = names->name;
1694         else {
1695                 if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
1696                         return _process_all(argc, argv, 0, _deps);
1697                 if (argc == 2)
1698                         name = argv[1];
1699         }
1700
1701         if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
1702                 return 0;
1703
1704         if (!_set_task_device(dmt, name, 0))
1705                 goto out;
1706
1707         if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
1708                 goto out;
1709
1710         if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
1711                 goto out;
1712
1713         if (!dm_task_run(dmt))
1714                 goto out;
1715
1716         if (!dm_task_get_info(dmt, &info))
1717                 goto out;
1718
1719         if (!(deps = dm_task_get_deps(dmt)))
1720                 goto out;
1721
1722         if (!info.exists) {
1723                 printf("Device does not exist.\n");
1724                 r = 1;
1725                 goto out;
1726         }
1727
1728         if (_switches[VERBOSE_ARG])
1729                 _display_info(dmt);
1730
1731         if (data && !_switches[VERBOSE_ARG])
1732                 printf("%s: ", name);
1733         printf("%d dependencies\t:", deps->count);
1734
1735         for (i = 0; i < deps->count; i++)
1736                 printf(" (%d, %d)",
1737                        (int) MAJOR(deps->device[i]),
1738                        (int) MINOR(deps->device[i]));
1739         printf("\n");
1740
1741         if (data && _switches[VERBOSE_ARG])
1742                 printf("\n");
1743
1744         r = 1;
1745
1746       out:
1747         dm_task_destroy(dmt);
1748         return r;
1749 }
1750
1751 static int _display_name(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data)
1752 {
1753         struct dm_names *names = (struct dm_names *) data;
1754
1755         printf("%s\t(%d, %d)\n", names->name,
1756                (int) MAJOR(names->dev), (int) MINOR(names->dev));
1757
1758         return 1;
1759 }
1760
1761 /*
1762  * Tree drawing code
1763  */
1764
1765 enum {
1766         TR_DEVICE=0,    /* display device major:minor number */
1767         TR_TABLE,
1768         TR_STATUS,
1769         TR_ACTIVE,
1770         TR_RW,
1771         TR_OPENCOUNT,
1772         TR_UUID,
1773         TR_COMPACT,
1774         TR_TRUNCATE,
1775         TR_BOTTOMUP,
1776         NUM_TREEMODE,
1777 };
1778
1779 static int _tree_switches[NUM_TREEMODE];
1780
1781 #define TR_PRINT_ATTRIBUTE ( _tree_switches[TR_ACTIVE] || \
1782                              _tree_switches[TR_RW] || \
1783                              _tree_switches[TR_OPENCOUNT] || \
1784                              _tree_switches[TR_UUID] )
1785
1786 #define TR_PRINT_TARGETS ( _tree_switches[TR_TABLE] || \
1787                            _tree_switches[TR_STATUS] )
1788
1789 /* Compact - fewer newlines */
1790 #define TR_PRINT_COMPACT (_tree_switches[TR_COMPACT] && \
1791                           !TR_PRINT_ATTRIBUTE && \
1792                           !TR_PRINT_TARGETS)
1793
1794 /* FIXME Get rid of this */
1795 #define MAX_DEPTH 100
1796
1797 /* Drawing character definition from pstree */
1798 /* [pstree comment] UTF-8 defines by Johan Myreen, updated by Ben Winslow */
1799 #define UTF_V   "\342\224\202"  /* U+2502, Vertical line drawing char */
1800 #define UTF_VR  "\342\224\234"  /* U+251C, Vertical and right */
1801 #define UTF_H   "\342\224\200"  /* U+2500, Horizontal */
1802 #define UTF_UR  "\342\224\224"  /* U+2514, Up and right */
1803 #define UTF_HD  "\342\224\254"  /* U+252C, Horizontal and down */
1804
1805 #define VT_BEG  "\033(0\017"    /* use graphic chars */
1806 #define VT_END  "\033(B"        /* back to normal char set */
1807 #define VT_V    "x"             /* see UTF definitions above */
1808 #define VT_VR   "t"
1809 #define VT_H    "q"
1810 #define VT_UR   "m"
1811 #define VT_HD   "w"
1812
1813 static struct {
1814         const char *empty_2;    /*    */
1815         const char *branch_2;   /* |- */
1816         const char *vert_2;     /* |  */
1817         const char *last_2;     /* `- */
1818         const char *single_3;   /* --- */
1819         const char *first_3;    /* -+- */
1820 }
1821 _tsym_ascii = {
1822         "  ",
1823         "|-",
1824         "| ",
1825         "`-",
1826         "---",
1827         "-+-"
1828 },
1829 _tsym_utf = {
1830         "  ",
1831         UTF_VR UTF_H,
1832         UTF_V " ",
1833         UTF_UR UTF_H,
1834         UTF_H UTF_H UTF_H,
1835         UTF_H UTF_HD UTF_H
1836 },
1837 _tsym_vt100 = {
1838         "  ",
1839         VT_BEG VT_VR VT_H VT_END,
1840         VT_BEG VT_V VT_END " ",
1841         VT_BEG VT_UR VT_H VT_END,
1842         VT_BEG VT_H VT_H VT_H VT_END,
1843         VT_BEG VT_H VT_HD VT_H VT_END
1844 },
1845 *_tsym = &_tsym_ascii;
1846
1847 /*
1848  * Tree drawing functions.
1849  */
1850 /* FIXME Get rid of these statics - use dynamic struct */
1851 /* FIXME Explain what these vars are for */
1852 static int _tree_width[MAX_DEPTH], _tree_more[MAX_DEPTH];
1853 static int _termwidth = 80;     /* Maximum output width */
1854 static int _cur_x = 1;          /* Current horizontal output position */
1855 static char _last_char = 0;
1856
1857 static void _out_char(const unsigned c)
1858 {
1859         /* Only first UTF-8 char counts */
1860         _cur_x += ((c & 0xc0) != 0x80);
1861
1862         if (!_tree_switches[TR_TRUNCATE]) {
1863                 putchar((int) c);
1864                 return;
1865         }
1866
1867         /* Truncation? */
1868         if (_cur_x <= _termwidth)
1869                 putchar((int) c);
1870
1871         if (_cur_x == _termwidth + 1 && ((c & 0xc0) != 0x80)) {
1872                 if (_last_char || (c & 0x80)) {
1873                         putchar('.');
1874                         putchar('.');
1875                         putchar('.');
1876                 } else {
1877                         _last_char = c;
1878                         _cur_x--;
1879                 }
1880         }
1881 }
1882
1883 static void _out_string(const char *str)
1884 {
1885         while (*str)
1886                 _out_char((unsigned char) *str++);
1887 }
1888
1889 /* non-negative integers only */
1890 static unsigned _out_int(unsigned num)
1891 {
1892         unsigned digits = 0;
1893         unsigned divi;
1894
1895         if (!num) {
1896                 _out_char('0');
1897                 return 1;
1898         }
1899
1900         /* non zero case */
1901         for (divi = 1; num / divi; divi *= 10)
1902                 digits++;
1903
1904         for (divi /= 10; divi; divi /= 10)
1905                 _out_char('0' + (num / divi) % 10);
1906
1907         return digits;
1908 }
1909
1910 static void _out_newline(void)
1911 {
1912         if (_last_char && _cur_x == _termwidth)
1913                 putchar(_last_char);
1914         _last_char = 0;
1915         putchar('\n');
1916         _cur_x = 1;
1917 }
1918
1919 static void _out_prefix(unsigned depth)
1920 {
1921         unsigned x, d;
1922
1923         for (d = 0; d < depth; d++) {
1924                 for (x = _tree_width[d] + 1; x > 0; x--)
1925                         _out_char(' ');
1926
1927                 _out_string(d == depth - 1 ?
1928                                 !_tree_more[depth] ? _tsym->last_2 : _tsym->branch_2
1929                            : _tree_more[d + 1] ?
1930                                 _tsym->vert_2 : _tsym->empty_2);
1931         }
1932 }
1933
1934 /*
1935  * Display tree
1936  */
1937 static void _display_tree_attributes(struct dm_tree_node *node)
1938 {
1939         int attr = 0;
1940         const char *uuid;
1941         const struct dm_info *info;
1942
1943         uuid = dm_tree_node_get_uuid(node);
1944         info = dm_tree_node_get_info(node);
1945
1946         if (!info->exists)
1947                 return;
1948
1949         if (_tree_switches[TR_ACTIVE]) {
1950                 _out_string(attr++ ? ", " : " [");
1951                 _out_string(info->suspended ? "SUSPENDED" : "ACTIVE");
1952         }
1953
1954         if (_tree_switches[TR_RW]) {
1955                 _out_string(attr++ ? ", " : " [");
1956                 _out_string(info->read_only ? "RO" : "RW");
1957         }
1958
1959         if (_tree_switches[TR_OPENCOUNT]) {
1960                 _out_string(attr++ ? ", " : " [");
1961                 (void) _out_int((unsigned) info->open_count);
1962         }
1963
1964         if (_tree_switches[TR_UUID]) {
1965                 _out_string(attr++ ? ", " : " [");
1966                 _out_string(uuid && *uuid ? uuid : "");
1967         }
1968
1969         if (attr)
1970                 _out_char(']');
1971 }
1972
1973 static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
1974                                unsigned first_child __attribute__((unused)),
1975                                unsigned last_child, unsigned has_children)
1976 {
1977         int offset;
1978         const char *name;
1979         const struct dm_info *info;
1980         int first_on_line = 0;
1981
1982         /* Sub-tree for targets has 2 more depth */
1983         if (depth + 2 > MAX_DEPTH)
1984                 return;
1985
1986         name = dm_tree_node_get_name(node);
1987
1988         if ((!name || !*name) && !_tree_switches[TR_DEVICE])
1989                 return;
1990
1991         /* Indicate whether there are more nodes at this depth */
1992         _tree_more[depth] = !last_child;
1993         _tree_width[depth] = 0;
1994
1995         if (_cur_x == 1)
1996                 first_on_line = 1;
1997
1998         if (!TR_PRINT_COMPACT || first_on_line)
1999                 _out_prefix(depth);
2000
2001         /* Remember the starting point for compact */
2002         offset = _cur_x;
2003
2004         if (TR_PRINT_COMPACT && !first_on_line)
2005                 _out_string(_tree_more[depth] ? _tsym->first_3 : _tsym->single_3);
2006
2007         /* display node */
2008         if (name)
2009                 _out_string(name);
2010
2011         info = dm_tree_node_get_info(node);
2012
2013         if (_tree_switches[TR_DEVICE]) {
2014                 _out_string(name ? " (" : "(");
2015                 (void) _out_int(info->major);
2016                 _out_char(':');
2017                 (void) _out_int(info->minor);
2018                 _out_char(')');
2019         }
2020
2021         /* display additional info */
2022         if (TR_PRINT_ATTRIBUTE)
2023                 _display_tree_attributes(node);
2024
2025         if (TR_PRINT_COMPACT)
2026                 _tree_width[depth] = _cur_x - offset;
2027
2028         if (!TR_PRINT_COMPACT || !has_children)
2029                 _out_newline();
2030
2031         if (TR_PRINT_TARGETS) {
2032                 _tree_more[depth + 1] = has_children;
2033                 // FIXME _display_tree_targets(name, depth + 2);
2034         }
2035 }
2036
2037 /*
2038  * Walk the dependency tree
2039  */
2040 static void _display_tree_walk_children(struct dm_tree_node *node,
2041                                         unsigned depth)
2042 {
2043         struct dm_tree_node *child, *next_child;
2044         void *handle = NULL;
2045         uint32_t inverted = _tree_switches[TR_BOTTOMUP];
2046         unsigned first_child = 1;
2047         unsigned has_children;
2048
2049         next_child = dm_tree_next_child(&handle, node, inverted);
2050
2051         while ((child = next_child)) {
2052                 next_child = dm_tree_next_child(&handle, node, inverted);
2053                 has_children =
2054                     dm_tree_node_num_children(child, inverted) ? 1 : 0;
2055
2056                 _display_tree_node(child, depth, first_child,
2057                                    next_child ? 0U : 1U, has_children);
2058
2059                 if (has_children)
2060                         _display_tree_walk_children(child, depth + 1);
2061
2062                 first_child = 0;
2063         }
2064 }
2065
2066 static int _add_dep(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data)
2067 {
2068         struct dm_names *names = (struct dm_names *) data;
2069
2070         if (!dm_tree_add_dev(_dtree, (unsigned) MAJOR(names->dev), (unsigned) MINOR(names->dev)))
2071                 return 0;
2072
2073         return 1;
2074 }
2075
2076 /*
2077  * Create and walk dependency tree
2078  */
2079 static int _build_whole_deptree(void)
2080 {
2081         if (_dtree)
2082                 return 1;
2083
2084         if (!(_dtree = dm_tree_create()))
2085                 return 0;
2086
2087         if (!_process_all(0, NULL, 0, _add_dep))
2088                 return 0;
2089
2090         return 1;
2091 }
2092
2093 static int _display_tree(int argc __attribute__((unused)),
2094                          char **argv __attribute__((unused)),
2095                          void *data __attribute__((unused)))
2096 {
2097         if (!_build_whole_deptree())
2098                 return 0;
2099
2100         _display_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);
2101
2102         return 1;
2103 }
2104
2105 /*
2106  * Report device information
2107  */
2108
2109 /* dm specific display functions */
2110
2111 static int _int32_disp(struct dm_report *rh,
2112                        struct dm_pool *mem __attribute__((unused)),
2113                        struct dm_report_field *field, const void *data,
2114                        void *private __attribute__((unused)))
2115 {
2116         const int32_t value = *(const int32_t *)data;
2117
2118         return dm_report_field_int32(rh, field, &value);
2119 }
2120
2121 static int _uint32_disp(struct dm_report *rh,
2122                         struct dm_pool *mem __attribute__((unused)),
2123                         struct dm_report_field *field, const void *data,
2124                         void *private __attribute__((unused)))
2125 {
2126         const uint32_t value = *(const int32_t *)data;
2127
2128         return dm_report_field_uint32(rh, field, &value);
2129 }
2130
2131 static int _dm_name_disp(struct dm_report *rh,
2132                          struct dm_pool *mem __attribute__((unused)),
2133                          struct dm_report_field *field, const void *data,
2134                          void *private __attribute__((unused)))
2135 {
2136         const char *name = dm_task_get_name((const struct dm_task *) data);
2137
2138         return dm_report_field_string(rh, field, &name);
2139 }
2140
2141 static int _dm_uuid_disp(struct dm_report *rh,
2142                          struct dm_pool *mem __attribute__((unused)),
2143                          struct dm_report_field *field,
2144                          const void *data, void *private __attribute__((unused)))
2145 {
2146         const char *uuid = dm_task_get_uuid((const struct dm_task *) data);
2147
2148         if (!uuid || !*uuid)
2149                 uuid = "";
2150
2151         return dm_report_field_string(rh, field, &uuid);
2152 }
2153
2154 static int _dm_read_ahead_disp(struct dm_report *rh,
2155                                struct dm_pool *mem __attribute__((unused)),
2156                                struct dm_report_field *field, const void *data,
2157                                void *private __attribute__((unused)))
2158 {
2159         uint32_t value;
2160
2161         if (!dm_task_get_read_ahead((const struct dm_task *) data, &value))
2162                 value = 0;
2163
2164         return dm_report_field_uint32(rh, field, &value);
2165 }
2166
2167 static int _dm_info_status_disp(struct dm_report *rh,
2168                                 struct dm_pool *mem __attribute__((unused)),
2169                                 struct dm_report_field *field, const void *data,
2170                                 void *private __attribute__((unused)))
2171 {
2172         char buf[5];
2173         const char *s = buf;
2174         const struct dm_info *info = data;
2175
2176         buf[0] = info->live_table ? 'L' : '-';
2177         buf[1] = info->inactive_table ? 'I' : '-';
2178         buf[2] = info->suspended ? 's' : '-';
2179         buf[3] = info->read_only ? 'r' : 'w';
2180         buf[4] = '\0';
2181
2182         return dm_report_field_string(rh, field, &s);
2183 }
2184
2185 static int _dm_info_table_loaded_disp(struct dm_report *rh,
2186                                       struct dm_pool *mem __attribute__((unused)),
2187                                       struct dm_report_field *field,
2188                                       const void *data,
2189                                       void *private __attribute__((unused)))
2190 {
2191         const struct dm_info *info = data;
2192
2193         if (info->live_table) {
2194                 if (info->inactive_table)
2195                         dm_report_field_set_value(field, "Both", NULL);
2196                 else
2197                         dm_report_field_set_value(field, "Live", NULL);
2198                 return 1;
2199         }
2200
2201         if (info->inactive_table)
2202                 dm_report_field_set_value(field, "Inactive", NULL);
2203         else
2204                 dm_report_field_set_value(field, "None", NULL);
2205
2206         return 1;
2207 }
2208
2209 static int _dm_info_suspended_disp(struct dm_report *rh,
2210                                    struct dm_pool *mem __attribute__((unused)),
2211                                    struct dm_report_field *field,
2212                                    const void *data,
2213                                    void *private __attribute__((unused)))
2214 {
2215         const struct dm_info *info = data;
2216
2217         if (info->suspended)
2218                 dm_report_field_set_value(field, "Suspended", NULL);
2219         else
2220                 dm_report_field_set_value(field, "Active", NULL);
2221
2222         return 1;
2223 }
2224
2225 static int _dm_info_read_only_disp(struct dm_report *rh,
2226                                    struct dm_pool *mem __attribute__((unused)),
2227                                    struct dm_report_field *field,
2228                                    const void *data,
2229                                    void *private __attribute__((unused)))
2230 {
2231         const struct dm_info *info = data;
2232
2233         if (info->read_only)
2234                 dm_report_field_set_value(field, "Read-only", NULL);
2235         else
2236                 dm_report_field_set_value(field, "Writeable", NULL);
2237
2238         return 1;
2239 }
2240
2241
2242 static int _dm_info_devno_disp(struct dm_report *rh, struct dm_pool *mem,
2243                                struct dm_report_field *field, const void *data,
2244                                void *private)
2245 {
2246         char buf[DM_MAX_TYPE_NAME], *repstr;
2247         const struct dm_info *info = data;
2248
2249         if (!dm_pool_begin_object(mem, 8)) {
2250                 log_error("dm_pool_begin_object failed");
2251                 return 0;
2252         }
2253
2254         if (dm_snprintf(buf, sizeof(buf), "%d:%d",
2255                         info->major, info->minor) < 0) {
2256                 log_error("dm_pool_alloc failed");
2257                 goto out_abandon;
2258         }
2259
2260         if (!dm_pool_grow_object(mem, buf, strlen(buf) + 1)) {
2261                 log_error("dm_pool_grow_object failed");
2262                 goto out_abandon;
2263         }
2264
2265         repstr = dm_pool_end_object(mem);
2266         dm_report_field_set_value(field, repstr, repstr);
2267         return 1;
2268
2269       out_abandon:
2270         dm_pool_abandon_object(mem);
2271         return 0;
2272 }
2273
2274 static int _dm_tree_names(struct dm_report *rh, struct dm_pool *mem,
2275                           struct dm_report_field *field, const void *data,
2276                           void *private, unsigned inverted)
2277 {
2278         const struct dm_tree_node *node = data;
2279         struct dm_tree_node *parent;
2280         void *t = NULL;
2281         const char *name;
2282         int first_node = 1;
2283         char *repstr;
2284
2285         if (!dm_pool_begin_object(mem, 16)) {
2286                 log_error("dm_pool_begin_object failed");
2287                 return 0;
2288         }
2289
2290         while ((parent = dm_tree_next_child(&t, node, inverted))) {
2291                 name = dm_tree_node_get_name(parent);
2292                 if (!name || !*name)
2293                         continue;
2294                 if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
2295                         log_error("dm_pool_grow_object failed");
2296                         goto out_abandon;
2297                 }
2298                 if (!dm_pool_grow_object(mem, name, 0)) {
2299                         log_error("dm_pool_grow_object failed");
2300                         goto out_abandon;
2301                 }
2302                 if (first_node)
2303                         first_node = 0;
2304         }
2305
2306         if (!dm_pool_grow_object(mem, "\0", 1)) {
2307                 log_error("dm_pool_grow_object failed");
2308                 goto out_abandon;
2309         }
2310
2311         repstr = dm_pool_end_object(mem);
2312         dm_report_field_set_value(field, repstr, repstr);
2313         return 1;
2314
2315       out_abandon:
2316         dm_pool_abandon_object(mem);
2317         return 0;
2318 }
2319
2320 static int _dm_deps_names_disp(struct dm_report *rh,
2321                                       struct dm_pool *mem,
2322                                       struct dm_report_field *field,
2323                                       const void *data, void *private)
2324 {
2325         return _dm_tree_names(rh, mem, field, data, private, 0);
2326 }
2327
2328 static int _dm_tree_parents_names_disp(struct dm_report *rh,
2329                                        struct dm_pool *mem,
2330                                        struct dm_report_field *field,
2331                                        const void *data, void *private)
2332 {
2333         return _dm_tree_names(rh, mem, field, data, private, 1);
2334 }
2335
2336 static int _dm_tree_parents_devs_disp(struct dm_report *rh, struct dm_pool *mem,
2337                                       struct dm_report_field *field,
2338                                       const void *data, void *private)
2339 {
2340         const struct dm_tree_node *node = data;
2341         struct dm_tree_node *parent;
2342         void *t = NULL;
2343         const struct dm_info *info;
2344         int first_node = 1;
2345         char buf[DM_MAX_TYPE_NAME], *repstr;
2346
2347         if (!dm_pool_begin_object(mem, 16)) {
2348                 log_error("dm_pool_begin_object failed");
2349                 return 0;
2350         }
2351
2352         while ((parent = dm_tree_next_child(&t, node, 1))) {
2353                 info = dm_tree_node_get_info(parent);
2354                 if (!info->major && !info->minor)
2355                         continue;
2356                 if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
2357                         log_error("dm_pool_grow_object failed");
2358                         goto out_abandon;
2359                 }
2360                 if (dm_snprintf(buf, sizeof(buf), "%d:%d",
2361                                 info->major, info->minor) < 0) {
2362                         log_error("dm_snprintf failed");
2363                         goto out_abandon;
2364                 }
2365                 if (!dm_pool_grow_object(mem, buf, 0)) {
2366                         log_error("dm_pool_grow_object failed");
2367                         goto out_abandon;
2368                 }
2369                 if (first_node)
2370                         first_node = 0;
2371         }
2372
2373         if (!dm_pool_grow_object(mem, "\0", 1)) {
2374                 log_error("dm_pool_grow_object failed");
2375                 goto out_abandon;
2376         }
2377
2378         repstr = dm_pool_end_object(mem);
2379         dm_report_field_set_value(field, repstr, repstr);
2380         return 1;
2381
2382       out_abandon:
2383         dm_pool_abandon_object(mem);
2384         return 0;
2385 }
2386
2387 static int _dm_tree_parents_count_disp(struct dm_report *rh,
2388                                        struct dm_pool *mem,
2389                                        struct dm_report_field *field,
2390                                        const void *data, void *private)
2391 {
2392         const struct dm_tree_node *node = data;
2393         int num_parent = dm_tree_node_num_children(node, 1);
2394
2395         return dm_report_field_int(rh, field, &num_parent);
2396 }
2397
2398 static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,
2399                          struct dm_report_field *field, const void *data,
2400                          void *private)
2401 {
2402         const struct dm_deps *deps = data;
2403         int i;
2404         char buf[DM_MAX_TYPE_NAME], *repstr;
2405
2406         if (!dm_pool_begin_object(mem, 16)) {
2407                 log_error("dm_pool_begin_object failed");
2408                 return 0;
2409         }
2410
2411         for (i = 0; i < deps->count; i++) {
2412                 if (dm_snprintf(buf, sizeof(buf), "%d:%d",
2413                        (int) MAJOR(deps->device[i]),
2414                        (int) MINOR(deps->device[i])) < 0) {
2415                         log_error("dm_snprintf failed");
2416                         goto out_abandon;
2417                 }
2418                 if (!dm_pool_grow_object(mem, buf, 0)) {
2419                         log_error("dm_pool_grow_object failed");
2420                         goto out_abandon;
2421                 }
2422                 if (i + 1 < deps->count && !dm_pool_grow_object(mem, ",", 1)) {
2423                         log_error("dm_pool_grow_object failed");
2424                         goto out_abandon;
2425                 }
2426         }
2427
2428         if (!dm_pool_grow_object(mem, "\0", 1)) {
2429                 log_error("dm_pool_grow_object failed");
2430                 goto out_abandon;
2431         }
2432
2433         repstr = dm_pool_end_object(mem);
2434         dm_report_field_set_value(field, repstr, repstr);
2435         return 1;
2436
2437       out_abandon:
2438         dm_pool_abandon_object(mem);
2439         return 0;
2440 }
2441
2442 static int _dm_subsystem_disp(struct dm_report *rh,
2443                                struct dm_pool *mem __attribute__((unused)),
2444                                struct dm_report_field *field, const void *data,
2445                                void *private __attribute__((unused)))
2446 {
2447         return dm_report_field_string(rh, field, (const char **) data);
2448 }
2449
2450 static int _dm_vg_name_disp(struct dm_report *rh,
2451                              struct dm_pool *mem __attribute__((unused)),
2452                              struct dm_report_field *field, const void *data,
2453                              void *private __attribute__((unused)))
2454 {
2455
2456         return dm_report_field_string(rh, field, (const char **) data);
2457 }
2458
2459 static int _dm_lv_name_disp(struct dm_report *rh,
2460                              struct dm_pool *mem __attribute__((unused)),
2461                              struct dm_report_field *field, const void *data,
2462                              void *private __attribute__((unused)))
2463
2464 {
2465         return dm_report_field_string(rh, field, (const char **) data);
2466 }
2467
2468 static int _dm_lv_layer_name_disp(struct dm_report *rh,
2469                                    struct dm_pool *mem __attribute__((unused)),
2470                                    struct dm_report_field *field, const void *data,
2471                                    void *private __attribute__((unused)))
2472
2473 {
2474         return dm_report_field_string(rh, field, (const char **) data);
2475 }
2476
2477 static void *_task_get_obj(void *obj)
2478 {
2479         return ((struct dmsetup_report_obj *)obj)->task;
2480 }
2481
2482 static void *_info_get_obj(void *obj)
2483 {
2484         return ((struct dmsetup_report_obj *)obj)->info;
2485 }
2486
2487 static void *_deps_get_obj(void *obj)
2488 {
2489         return dm_task_get_deps(((struct dmsetup_report_obj *)obj)->deps_task);
2490 }
2491
2492 static void *_tree_get_obj(void *obj)
2493 {
2494         return ((struct dmsetup_report_obj *)obj)->tree_node;
2495 }
2496
2497 static void *_split_name_get_obj(void *obj)
2498 {
2499         return ((struct dmsetup_report_obj *)obj)->split_name;
2500 }
2501
2502 static const struct dm_report_object_type _report_types[] = {
2503         { DR_TASK, "Mapped Device Name", "", _task_get_obj },
2504         { DR_INFO, "Mapped Device Information", "", _info_get_obj },
2505         { DR_DEPS, "Mapped Device Relationship Information", "", _deps_get_obj },
2506         { DR_TREE, "Mapped Device Relationship Information", "", _tree_get_obj },
2507         { DR_NAME, "Mapped Device Name Components", "", _split_name_get_obj },
2508         { 0, "", "", NULL },
2509 };
2510
2511 /* Column definitions */
2512 #define OFFSET_OF(strct, field) (((char*)&((struct strct*)0)->field) - (char*)0)
2513 #define STR (DM_REPORT_FIELD_TYPE_STRING)
2514 #define NUM (DM_REPORT_FIELD_TYPE_NUMBER)
2515 #define FIELD_O(type, strct, sorttype, head, field, width, func, id, desc) {DR_ ## type, sorttype, OFFSET_OF(strct, field), width, id, head, &_ ## func ## _disp, desc},
2516 #define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, sorttype, 0, width, id, head, &_ ## func ## _disp, desc},
2517
2518 static const struct dm_report_field_type _report_fields[] = {
2519 /* *INDENT-OFF* */
2520 FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.")
2521 FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")
2522
2523 /* FIXME Next one should be INFO */
2524 FIELD_F(TASK, NUM, "RAhead", 6, dm_read_ahead, "read_ahead", "Read ahead in sectors.")
2525
2526 FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.")
2527 FIELD_F(INFO, STR, "Tables", 6, dm_info_table_loaded, "tables_loaded", "Which of the live and inactive table slots are filled.")
2528 FIELD_F(INFO, STR, "Suspended", 9, dm_info_suspended, "suspended", "Whether the device is suspended.")
2529 FIELD_F(INFO, STR, "Read-only", 9, dm_info_read_only, "readonly", "Whether the device is read-only or writeable.")
2530 FIELD_F(INFO, STR, "DevNo", 5, dm_info_devno, "devno", "Device major and minor numbers")
2531 FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.")
2532 FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.")
2533 FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.")
2534 FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.")
2535 FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.")
2536
2537 FIELD_O(DEPS, dm_deps, NUM, "#Devs", count, 5, int32, "device_count", "Number of devices used by this one.")
2538 FIELD_F(TREE, STR, "DevNames", 8, dm_deps_names, "devs_used", "List of names of mapped devices used by this one.")
2539 FIELD_F(DEPS, STR, "DevNos", 6, dm_deps, "devnos_used", "List of device numbers of devices used by this one.")
2540
2541 FIELD_F(TREE, NUM, "#Refs", 5, dm_tree_parents_count, "device_ref_count", "Number of mapped devices referencing this one.")
2542 FIELD_F(TREE, STR, "RefNames", 8, dm_tree_parents_names, "names_using_dev", "List of names of mapped devices using this one.")
2543 FIELD_F(TREE, STR, "RefDevNos", 9, dm_tree_parents_devs, "devnos_using_dev", "List of device numbers of mapped devices using this one.")
2544
2545 FIELD_O(NAME, dm_split_name, STR, "Subsys", subsystem, 6, dm_subsystem, "subsystem", "Userspace subsystem responsible for this device.")
2546 FIELD_O(NAME, dm_split_name, STR, "VG", vg_name, 4, dm_vg_name, "vg_name", "LVM Volume Group name.")
2547 FIELD_O(NAME, dm_split_name, STR, "LV", lv_name, 4, dm_lv_name, "lv_name", "LVM Logical Volume name.")
2548 FIELD_O(NAME, dm_split_name, STR, "LVLayer", lv_layer, 7, dm_lv_layer_name, "lv_layer", "LVM device layer.")
2549
2550 {0, 0, 0, 0, "", "", NULL, NULL},
2551 /* *INDENT-ON* */
2552 };
2553
2554 #undef STR
2555 #undef NUM
2556 #undef FIELD_O
2557 #undef FIELD_F
2558
2559 static const char *default_report_options = "name,major,minor,attr,open,segments,events,uuid";
2560 static const char *splitname_report_options = "vg_name,lv_name,lv_layer";
2561
2562 static int _report_init(struct command *c)
2563 {
2564         char *options = (char *) default_report_options;
2565         const char *keys = "";
2566         const char *separator = " ";
2567         int aligned = 1, headings = 1, buffered = 1, field_prefixes = 0;
2568         int quoted = 1, columns_as_rows = 0;
2569         uint32_t flags = 0;
2570         size_t len = 0;
2571         int r = 0;
2572
2573         if (c && !strcmp(c->name, "splitname"))
2574                 options = (char *) splitname_report_options;
2575
2576         /* emulate old dmsetup behaviour */
2577         if (_switches[NOHEADINGS_ARG]) {
2578                 separator = ":";
2579                 aligned = 0;
2580                 headings = 0;
2581         }
2582
2583         if (_switches[UNBUFFERED_ARG])
2584                 buffered = 0;
2585
2586         if (_switches[ROWS_ARG])
2587                 columns_as_rows = 1;
2588
2589         if (_switches[UNQUOTED_ARG])
2590                 quoted = 0;
2591
2592         if (_switches[NAMEPREFIXES_ARG]) {
2593                 aligned = 0;
2594                 field_prefixes = 1;
2595         }
2596
2597         if (_switches[OPTIONS_ARG] && _string_args[OPTIONS_ARG]) {
2598                 if (*_string_args[OPTIONS_ARG] != '+')
2599                         options = _string_args[OPTIONS_ARG];
2600                 else {
2601                         len = strlen(default_report_options) +
2602                               strlen(_string_args[OPTIONS_ARG]) + 1;
2603                         if (!(options = dm_malloc(len))) {
2604                                 err("Failed to allocate option string.");
2605                                 return 0;
2606                         }
2607                         if (dm_snprintf(options, len, "%s,%s",
2608                                         default_report_options,
2609                                         &_string_args[OPTIONS_ARG][1]) < 0) {
2610                                 err("snprintf failed");
2611                                 goto out;
2612                         }
2613                 }
2614         }
2615
2616         if (_switches[SORT_ARG] && _string_args[SORT_ARG]) {
2617                 keys = _string_args[SORT_ARG];
2618                 buffered = 1;
2619                 if (c && (!strcmp(c->name, "status") || !strcmp(c->name, "table"))) {
2620                         err("--sort is not yet supported with status and table");
2621                         goto out;
2622                 }
2623         }
2624
2625         if (_switches[SEPARATOR_ARG] && _string_args[SEPARATOR_ARG]) {
2626                 separator = _string_args[SEPARATOR_ARG];
2627                 aligned = 0;
2628         }
2629
2630         if (aligned)
2631                 flags |= DM_REPORT_OUTPUT_ALIGNED;
2632
2633         if (buffered)
2634                 flags |= DM_REPORT_OUTPUT_BUFFERED;
2635
2636         if (headings)
2637                 flags |= DM_REPORT_OUTPUT_HEADINGS;
2638
2639         if (field_prefixes)
2640                 flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
2641
2642         if (!quoted)
2643                 flags |= DM_REPORT_OUTPUT_FIELD_UNQUOTED;
2644
2645         if (columns_as_rows)
2646                 flags |= DM_REPORT_OUTPUT_COLUMNS_AS_ROWS;
2647
2648         if (!(_report = dm_report_init(&_report_type,
2649                                        _report_types, _report_fields,
2650                                        options, separator, flags, keys, NULL)))
2651                 goto out;
2652
2653         if ((_report_type & DR_TREE) && !_build_whole_deptree()) {
2654                 err("Internal device dependency tree creation failed.");
2655                 goto out;
2656         }
2657
2658         if (field_prefixes)
2659                 dm_report_set_output_field_name_prefix(_report, "dm_");
2660
2661         r = 1;
2662
2663 out:
2664         if (!strcasecmp(options, "help") || !strcmp(options, "?"))
2665                 r = 1;
2666
2667         if (len)
2668                 dm_free(options);
2669
2670         return r;
2671 }
2672
2673 /*
2674  * List devices
2675  */
2676 static int _ls(int argc, char **argv, void *data)
2677 {
2678         if ((_switches[TARGET_ARG] && _target) ||
2679             (_switches[EXEC_ARG] && _command))
2680                 return _status(argc, argv, data);
2681         else if ((_switches[TREE_ARG]))
2682                 return _display_tree(argc, argv, data);
2683         else
2684                 return _process_all(argc, argv, 0, _display_name);
2685 }
2686
2687 static int _help(int argc, char **argv, void *data);
2688
2689 /*
2690  * Dispatch table
2691  */
2692 static struct command _commands[] = {
2693         {"help", "[-c|-C|--columns]", 0, 0, _help},
2694         {"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
2695           "\t                  [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
2696           "\t                  [-u|uuid <uuid>]\n"
2697           "\t                  [--notable | --table <table> | <table_file>]",
2698          1, 2, _create},
2699         {"remove", "[-f|--force] <device>", 0, 1, _remove},
2700         {"remove_all", "[-f|--force]", 0, 0, _remove_all},
2701         {"suspend", "[--noflush] <device>", 0, 1, _suspend},
2702         {"resume", "<device>", 0, 1, _resume},
2703         {"load", "<device> [<table_file>]", 0, 2, _load},
2704         {"clear", "<device>", 0, 1, _clear},
2705         {"reload", "<device> [<table_file>]", 0, 2, _load},
2706         {"rename", "<device> [--setuuid] <new_name_or_uuid>", 1, 2, _rename},
2707         {"message", "<device> <sector> <message>", 2, -1, _message},
2708         {"ls", "[--target <target_type>] [--exec <command>] [--tree [-o options]]", 0, 0, _ls},
2709         {"info", "[<device>]", 0, 1, _info},
2710         {"deps", "[<device>]", 0, 1, _deps},
2711         {"status", "[<device>] [--target <target_type>]", 0, 1, _status},
2712         {"table", "[<device>] [--target <target_type>] [--showkeys]", 0, 1, _status},
2713         {"wait", "<device> [<event_nr>]", 0, 2, _wait},
2714         {"mknodes", "[<device>]", 0, 1, _mknodes},
2715         {"udevcreatecookie", "", 0, 0, _udevcreatecookie},
2716         {"udevreleasecookie", "[<cookie>]", 0, 1, _udevreleasecookie},
2717         {"udevflags", "<cookie>", 1, 1, _udevflags},
2718         {"udevcomplete", "<cookie>", 1, 1, _udevcomplete},
2719         {"udevcomplete_all", "", 0, 0, _udevcomplete_all},
2720         {"udevcookies", "", 0, 0, _udevcookies},
2721         {"targets", "", 0, 0, _targets},
2722         {"version", "", 0, 0, _version},
2723         {"setgeometry", "<device> <cyl> <head> <sect> <start>", 5, 5, _setgeometry},
2724         {"splitname", "<device> [<subsystem>]", 1, 2, _splitname},
2725         {NULL, NULL, 0, 0, NULL}
2726 };
2727
2728 static void _usage(FILE *out)
2729 {
2730         int i;
2731
2732         fprintf(out, "Usage:\n\n");
2733         fprintf(out, "dmsetup [--version] [-h|--help [-c|-C|--columns]]\n"
2734                 "        [-v|--verbose [-v|--verbose ...]]\n"
2735                 "        [-r|--readonly] [--noopencount] [--nolockfs] [--inactive]\n"
2736                 "        [--udevcookie] [--noudevrules] [--noudevsync] [-y|--yes]\n"
2737                 "        [--readahead [+]<sectors>|auto|none]\n"
2738                 "        [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>]\n"
2739                 "        [--nameprefixes] [--noheadings] [--separator <separator>]\n\n");
2740         for (i = 0; _commands[i].name; i++)
2741                 fprintf(out, "\t%s %s\n", _commands[i].name, _commands[i].help);
2742         fprintf(out, "\n<device> may be device name or -u <uuid> or "
2743                      "-j <major> -m <minor>\n");
2744         fprintf(out, "<fields> are comma-separated.  Use 'help -c' for list.\n");
2745         fprintf(out, "Table_file contents may be supplied on stdin.\n");
2746         fprintf(out, "Tree options are: ascii, utf, vt100; compact, inverted, notrunc;\n"
2747                      "                  [no]device, active, open, rw and uuid.\n");
2748         fprintf(out, "\n");
2749 }
2750
2751 static void _losetup_usage(FILE *out)
2752 {
2753         fprintf(out, "Usage:\n\n");
2754         fprintf(out, "losetup [-d|-a] [-e encryption] "
2755                      "[-o offset] [-f|loop_device] [file]\n\n");
2756 }
2757
2758 static int _help(int argc __attribute__((unused)),
2759                  char **argv __attribute__((unused)),
2760                  void *data __attribute__((unused)))
2761 {
2762         _usage(stderr);
2763
2764         if (_switches[COLS_ARG]) {
2765                 _switches[OPTIONS_ARG] = 1;
2766                 _string_args[OPTIONS_ARG] = (char *) "help";
2767                 _switches[SORT_ARG] = 0;
2768
2769                 if (_report) {
2770                         dm_report_free(_report);
2771                         _report = NULL;
2772                 }
2773                 (void) _report_init(NULL);
2774         }
2775
2776         return 1;
2777 }
2778
2779 static struct command *_find_command(const char *name)
2780 {
2781         int i;
2782
2783         for (i = 0; _commands[i].name; i++)
2784                 if (!strcmp(_commands[i].name, name))
2785                         return _commands + i;
2786
2787         return NULL;
2788 }
2789
2790 static int _process_tree_options(const char *options)
2791 {
2792         const char *s, *end;
2793         struct winsize winsz;
2794         size_t len;
2795
2796         /* Symbol set default */
2797         if (!strcmp(nl_langinfo(CODESET), "UTF-8"))
2798                 _tsym = &_tsym_utf;
2799         else
2800                 _tsym = &_tsym_ascii;
2801
2802         /* Default */
2803         _tree_switches[TR_DEVICE] = 1;
2804         _tree_switches[TR_TRUNCATE] = 1;
2805
2806         /* parse */
2807         for (s = options; s && *s; s++) {
2808                 len = 0;
2809                 for (end = s; *end && *end != ','; end++, len++)
2810                         ;
2811                 if (!strncmp(s, "device", len))
2812                         _tree_switches[TR_DEVICE] = 1;
2813                 else if (!strncmp(s, "nodevice", len))
2814                         _tree_switches[TR_DEVICE] = 0;
2815                 else if (!strncmp(s, "status", len))
2816                         _tree_switches[TR_STATUS] = 1;
2817                 else if (!strncmp(s, "table", len))
2818                         _tree_switches[TR_TABLE] = 1;
2819                 else if (!strncmp(s, "active", len))
2820                         _tree_switches[TR_ACTIVE] = 1;
2821                 else if (!strncmp(s, "open", len))
2822                         _tree_switches[TR_OPENCOUNT] = 1;
2823                 else if (!strncmp(s, "uuid", len))
2824                         _tree_switches[TR_UUID] = 1;
2825                 else if (!strncmp(s, "rw", len))
2826                         _tree_switches[TR_RW] = 1;
2827                 else if (!strncmp(s, "utf", len))
2828                         _tsym = &_tsym_utf;
2829                 else if (!strncmp(s, "vt100", len))
2830                         _tsym = &_tsym_vt100;
2831                 else if (!strncmp(s, "ascii", len))
2832                         _tsym = &_tsym_ascii;
2833                 else if (!strncmp(s, "inverted", len))
2834                         _tree_switches[TR_BOTTOMUP] = 1;
2835                 else if (!strncmp(s, "compact", len))
2836                         _tree_switches[TR_COMPACT] = 1;
2837                 else if (!strncmp(s, "notrunc", len))
2838                         _tree_switches[TR_TRUNCATE] = 0;
2839                 else {
2840                         fprintf(stderr, "Tree options not recognised: %s\n", s);
2841                         return 0;
2842                 }
2843                 if (!*end)
2844                         break;
2845                 s = end;
2846         }
2847
2848         /* Truncation doesn't work well with vt100 drawing char */
2849         if (_tsym != &_tsym_vt100)
2850                 if (ioctl(1, (unsigned long) TIOCGWINSZ, &winsz) >= 0 && winsz.ws_col > 3)
2851                         _termwidth = winsz.ws_col - 3;
2852
2853         return 1;
2854 }
2855
2856 /*
2857  * Returns the full absolute path, or NULL if the path could
2858  * not be resolved.
2859  */
2860 static char *_get_abspath(const char *path)
2861 {
2862         char *_path;
2863
2864 #ifdef HAVE_CANONICALIZE_FILE_NAME
2865         _path = canonicalize_file_name(path);
2866 #else
2867         /* FIXME Provide alternative */
2868 #endif
2869         return _path;
2870 }
2871
2872 static char *parse_loop_device_name(const char *dev, const char *dev_dir)
2873 {
2874         char *buf;
2875         char *device;
2876
2877         if (!(buf = dm_malloc(PATH_MAX)))
2878                 return NULL;
2879
2880         if (dev[0] == '/') {
2881                 if (!(device = _get_abspath(dev)))
2882                         goto error;
2883
2884                 if (strncmp(device, dev_dir, strlen(dev_dir)))
2885                         goto error;
2886
2887                 /* If dev_dir does not end in a slash, ensure that the
2888                    following byte in the device string is "/".  */
2889                 if (dev_dir[strlen(dev_dir) - 1] != '/' &&
2890                     device[strlen(dev_dir)] != '/')
2891                         goto error;
2892
2893                 strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX);
2894                 dm_free(device);
2895
2896         } else {
2897                 /* check for device number */
2898                 if (!strncmp(dev, "loop", strlen("loop")))
2899                         strncpy(buf, dev, (size_t) PATH_MAX);
2900                 else
2901                         goto error;
2902         }
2903
2904         return buf;
2905
2906 error:
2907         dm_free(buf);
2908         return NULL;
2909 }
2910
2911 /*
2912  *  create a table for a mapped device using the loop target.
2913  */
2914 static int _loop_table(char *table, size_t tlen, char *file,
2915                        char *dev __attribute__((unused)), off_t off)
2916 {
2917         struct stat fbuf;
2918         off_t size, sectors;
2919         int fd = -1;
2920 #ifdef HAVE_SYS_STATVFS_H
2921         struct statvfs fsbuf;
2922         off_t blksize;
2923 #endif
2924
2925         if (!_switches[READ_ONLY])
2926                 fd = open(file, O_RDWR);
2927
2928         if (fd < 0) {
2929                 _switches[READ_ONLY]++;
2930                 fd = open(file, O_RDONLY);
2931         }
2932
2933         if (fd < 0)
2934                 goto error;
2935
2936         if (fstat(fd, &fbuf))
2937                 goto error;
2938
2939         size = (fbuf.st_size - off);
2940         sectors = size >> SECTOR_SHIFT;
2941
2942         if (_switches[VERBOSE_ARG])
2943                 fprintf(stderr, "losetup: set loop size to %llukB "
2944                         "(%llu sectors)\n", (long long unsigned) sectors >> 1,
2945                         (long long unsigned) sectors);
2946
2947 #ifdef HAVE_SYS_STATVFS_H
2948         if (fstatvfs(fd, &fsbuf))
2949                 goto error;
2950
2951         /* FIXME Fragment size currently unused */
2952         blksize = fsbuf.f_frsize;
2953 #endif
2954
2955         close(fd);
2956
2957         if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL,
2958                         (long long unsigned)sectors, file, (long long unsigned)off) < 0)
2959                 return 0;
2960
2961         if (_switches[VERBOSE_ARG] > 1)
2962                 fprintf(stderr, "Table: %s\n", table);
2963
2964         return 1;
2965
2966 error:
2967         if (fd > -1)
2968                 close(fd);
2969         return 0;
2970 }
2971
2972 static int _process_losetup_switches(const char *base, int *argc, char ***argv,
2973                                      const char *dev_dir)
2974 {
2975         static int ind;
2976         int c;
2977         int encrypt_loop = 0, delete = 0, find = 0, show_all = 0;
2978         char *device_name = NULL;
2979         char *loop_file = NULL;
2980         off_t offset = 0;
2981
2982 #ifdef HAVE_GETOPTLONG
2983         static struct option long_options[] = {
2984                 {0, 0, 0, 0}
2985         };
2986 #endif
2987
2988         optarg = 0;
2989         optind = OPTIND_INIT;
2990         while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "ade:fo:v",
2991                                             long_options, NULL)) != -1 ) {
2992                 if (c == ':' || c == '?')
2993                         return 0;
2994                 if (c == 'a')
2995                         show_all++;
2996                 if (c == 'd')
2997                         delete++;
2998                 if (c == 'e')
2999                         encrypt_loop++;
3000                 if (c == 'f')
3001                         find++;
3002                 if (c == 'o')
3003                         offset = atoi(optarg);
3004                 if (c == 'v')
3005                         _switches[VERBOSE_ARG]++;
3006         }
3007
3008         *argv += optind ;
3009         *argc -= optind ;
3010
3011         if (encrypt_loop){
3012                 fprintf(stderr, "%s: Sorry, cryptoloop is not yet implemented "
3013                                 "in this version.\n", base);
3014                 return 0;
3015         }
3016
3017         if (show_all) {
3018                 fprintf(stderr, "%s: Sorry, show all is not yet implemented "
3019                                 "in this version.\n", base);
3020                 return 0;
3021         }
3022
3023         if (find) {
3024                 fprintf(stderr, "%s: Sorry, find is not yet implemented "
3025                                 "in this version.\n", base);
3026                 if (!*argc)
3027                         return 0;
3028         }
3029
3030         if (!*argc) {
3031                 fprintf(stderr, "%s: Please specify loop_device.\n", base);
3032                 _losetup_usage(stderr);
3033                 return 0;
3034         }
3035
3036         if (!(device_name = parse_loop_device_name((*argv)[0], dev_dir))) {
3037                 fprintf(stderr, "%s: Could not parse loop_device %s\n",
3038                         base, (*argv)[0]);
3039                 _losetup_usage(stderr);
3040                 return 0;
3041         }
3042
3043         if (delete) {
3044                 *argc = 2;
3045
3046                 (*argv)[1] = device_name;
3047                 (*argv)[0] = (char *) "remove";
3048
3049                 return 1;
3050         }
3051
3052         if (*argc != 2) {
3053                 fprintf(stderr, "%s: Too few arguments\n", base);
3054                 _losetup_usage(stderr);
3055                 dm_free(device_name);
3056                 return 0;
3057         }
3058
3059         /* FIXME move these to make them available to native dmsetup */
3060         if (!(loop_file = _get_abspath((*argv)[(find) ? 0 : 1]))) {
3061                 fprintf(stderr, "%s: Could not parse loop file name %s\n",
3062                         base, (*argv)[1]);
3063                 _losetup_usage(stderr);
3064                 dm_free(device_name);
3065                 return 0;
3066         }
3067
3068         /* FIXME Missing free */
3069         _table = dm_malloc(LOOP_TABLE_SIZE);
3070         if (!_loop_table(_table, (size_t) LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
3071                 fprintf(stderr, "Could not build device-mapper table for %s\n", (*argv)[0]);
3072                 dm_free(device_name);
3073                 return 0;
3074         }
3075         _switches[TABLE_ARG]++;
3076
3077         (*argv)[0] = (char *) "create";
3078         (*argv)[1] = device_name ;
3079
3080         return 1;
3081 }
3082
3083 static int _process_switches(int *argc, char ***argv, const char *dev_dir)
3084 {
3085         char *base, *namebase, *s;
3086         static int ind;
3087         int c, r;
3088
3089 #ifdef HAVE_GETOPTLONG
3090         static struct option long_options[] = {
3091                 {"readonly", 0, &ind, READ_ONLY},
3092                 {"columns", 0, &ind, COLS_ARG},
3093                 {"exec", 1, &ind, EXEC_ARG},
3094                 {"force", 0, &ind, FORCE_ARG},
3095                 {"gid", 1, &ind, GID_ARG},
3096                 {"help", 0, &ind, HELP_ARG},
3097                 {"inactive", 0, &ind, INACTIVE_ARG},
3098                 {"major", 1, &ind, MAJOR_ARG},
3099                 {"minor", 1, &ind, MINOR_ARG},
3100                 {"mode", 1, &ind, MODE_ARG},
3101                 {"nameprefixes", 0, &ind, NAMEPREFIXES_ARG},
3102                 {"noflush", 0, &ind, NOFLUSH_ARG},
3103                 {"noheadings", 0, &ind, NOHEADINGS_ARG},
3104                 {"nolockfs", 0, &ind, NOLOCKFS_ARG},
3105                 {"noopencount", 0, &ind, NOOPENCOUNT_ARG},
3106                 {"notable", 0, &ind, NOTABLE_ARG},
3107                 {"udevcookie", 1, &ind, UDEVCOOKIE_ARG},
3108                 {"noudevrules", 0, &ind, NOUDEVRULES_ARG},
3109                 {"noudevsync", 0, &ind, NOUDEVSYNC_ARG},
3110                 {"options", 1, &ind, OPTIONS_ARG},
3111                 {"readahead", 1, &ind, READAHEAD_ARG},
3112                 {"rows", 0, &ind, ROWS_ARG},
3113                 {"separator", 1, &ind, SEPARATOR_ARG},
3114                 {"setuuid", 0, &ind, SETUUID_ARG},
3115                 {"showkeys", 0, &ind, SHOWKEYS_ARG},
3116                 {"sort", 1, &ind, SORT_ARG},
3117                 {"table", 1, &ind, TABLE_ARG},
3118                 {"target", 1, &ind, TARGET_ARG},
3119                 {"tree", 0, &ind, TREE_ARG},
3120                 {"uid", 1, &ind, UID_ARG},
3121                 {"uuid", 1, &ind, UUID_ARG},
3122                 {"unbuffered", 0, &ind, UNBUFFERED_ARG},
3123                 {"unquoted", 0, &ind, UNQUOTED_ARG},
3124                 {"verbose", 1, &ind, VERBOSE_ARG},
3125                 {"version", 0, &ind, VERSION_ARG},
3126                 {"yes", 0, &ind, YES_ARG},
3127                 {0, 0, 0, 0}
3128         };
3129 #else
3130         struct option long_options;
3131 #endif
3132
3133         /*
3134          * Zero all the index counts.
3135          */
3136         memset(&_switches, 0, sizeof(_switches));
3137         memset(&_int_args, 0, sizeof(_int_args));
3138         _read_ahead_flags = 0;
3139
3140         namebase = strdup((*argv)[0]);
3141         base = basename(namebase);
3142
3143         if (!strcmp(base, "devmap_name")) {
3144                 free(namebase);
3145                 _switches[COLS_ARG]++;
3146                 _switches[NOHEADINGS_ARG]++;
3147                 _switches[OPTIONS_ARG]++;
3148                 _switches[MAJOR_ARG]++;
3149                 _switches[MINOR_ARG]++;
3150                 _string_args[OPTIONS_ARG] = (char *) "name";
3151
3152                 if (*argc == 3) {
3153                         _int_args[MAJOR_ARG] = atoi((*argv)[1]);
3154                         _int_args[MINOR_ARG] = atoi((*argv)[2]);
3155                         *argc -= 2;
3156                         *argv += 2;
3157                 } else if ((*argc == 2) &&
3158                            (2 == sscanf((*argv)[1], "%i:%i",
3159                                         &_int_args[MAJOR_ARG],
3160                                         &_int_args[MINOR_ARG]))) {
3161                         *argc -= 1;
3162                         *argv += 1;
3163                 } else {
3164                         fprintf(stderr, "Usage: devmap_name <major> <minor>\n");
3165                         return 0;
3166                 }
3167
3168                 (*argv)[0] = (char *) "info";
3169                 return 1;
3170         }
3171
3172         if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
3173                 r = _process_losetup_switches(base, argc, argv, dev_dir);
3174                 free(namebase);
3175                 return r;
3176         }
3177
3178         free(namebase);
3179
3180         optarg = 0;
3181         optind = OPTIND_INIT;
3182         while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "cCfG:hj:m:M:no:O:ru:U:vy",
3183                                             long_options, NULL)) != -1) {
3184                 if (c == ':' || c == '?')
3185                         return 0;
3186                 if (c == 'h' || ind == HELP_ARG)
3187                         _switches[HELP_ARG]++;
3188                 if (c == 'c' || c == 'C' || ind == COLS_ARG)
3189                         _switches[COLS_ARG]++;
3190                 if (c == 'f' || ind == FORCE_ARG)
3191                         _switches[FORCE_ARG]++;
3192                 if (c == 'r' || ind == READ_ONLY)
3193                         _switches[READ_ONLY]++;
3194                 if (c == 'j' || ind == MAJOR_ARG) {
3195                         _switches[MAJOR_ARG]++;
3196                         _int_args[MAJOR_ARG] = atoi(optarg);
3197                 }
3198                 if (c == 'm' || ind == MINOR_ARG) {
3199                         _switches[MINOR_ARG]++;
3200                         _int_args[MINOR_ARG] = atoi(optarg);
3201                 }
3202                 if (c == 'n' || ind == NOTABLE_ARG)
3203                         _switches[NOTABLE_ARG]++;
3204                 if (c == 'o' || ind == OPTIONS_ARG) {
3205                         _switches[OPTIONS_ARG]++;
3206                         _string_args[OPTIONS_ARG] = optarg;
3207                 }
3208                 if (ind == SEPARATOR_ARG) {
3209                         _switches[SEPARATOR_ARG]++;
3210                         _string_args[SEPARATOR_ARG] = optarg;
3211                 }
3212                 if (c == 'O' || ind == SORT_ARG) {
3213                         _switches[SORT_ARG]++;
3214                         _string_args[SORT_ARG] = optarg;
3215                 }
3216                 if (c == 'v' || ind == VERBOSE_ARG)
3217                         _switches[VERBOSE_ARG]++;
3218                 if (c == 'u' || ind == UUID_ARG) {
3219                         _switches[UUID_ARG]++;
3220                         _uuid = optarg;
3221                 }
3222                 if (c == 'y' || ind == YES_ARG)
3223                         _switches[YES_ARG]++;
3224                 if (ind == UDEVCOOKIE_ARG) {
3225                         _switches[UDEVCOOKIE_ARG]++;
3226                         _udev_cookie = _get_cookie_value(optarg);
3227                 }
3228                 if (ind == NOUDEVRULES_ARG)
3229                         _switches[NOUDEVRULES_ARG]++;
3230                 if (ind == NOUDEVSYNC_ARG)
3231                         _switches[NOUDEVSYNC_ARG]++;
3232                 if (c == 'G' || ind == GID_ARG) {
3233                         _switches[GID_ARG]++;
3234                         _int_args[GID_ARG] = atoi(optarg);
3235                 }
3236                 if (c == 'U' || ind == UID_ARG) {
3237                         _switches[UID_ARG]++;
3238                         _int_args[UID_ARG] = atoi(optarg);
3239                 }
3240                 if (c == 'M' || ind == MODE_ARG) {
3241                         _switches[MODE_ARG]++;
3242                         /* FIXME Accept modes as per chmod */
3243                         _int_args[MODE_ARG] = (int) strtol(optarg, NULL, 8);
3244                 }
3245                 if ((ind == EXEC_ARG)) {
3246                         _switches[EXEC_ARG]++;
3247                         _command = optarg;
3248                 }
3249                 if ((ind == TARGET_ARG)) {
3250                         _switches[TARGET_ARG]++;
3251                         _target = optarg;
3252                 }
3253                 if ((ind == INACTIVE_ARG))
3254                         _switches[INACTIVE_ARG]++;
3255                 if ((ind == NAMEPREFIXES_ARG))
3256                         _switches[NAMEPREFIXES_ARG]++;
3257                 if ((ind == NOFLUSH_ARG))
3258                         _switches[NOFLUSH_ARG]++;
3259                 if ((ind == NOHEADINGS_ARG))
3260                         _switches[NOHEADINGS_ARG]++;
3261                 if ((ind == NOLOCKFS_ARG))
3262                         _switches[NOLOCKFS_ARG]++;
3263                 if ((ind == NOOPENCOUNT_ARG))
3264                         _switches[NOOPENCOUNT_ARG]++;
3265                 if ((ind == READAHEAD_ARG)) {
3266                         _switches[READAHEAD_ARG]++;
3267                         if (!strcasecmp(optarg, "auto"))
3268                                 _int_args[READAHEAD_ARG] = DM_READ_AHEAD_AUTO;
3269                         else if (!strcasecmp(optarg, "none"))
3270                                 _int_args[READAHEAD_ARG] = DM_READ_AHEAD_NONE;
3271                         else {
3272                                 for (s = optarg; isspace(*s); s++)
3273                                         ;
3274                                 if (*s == '+')
3275                                         _read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG;
3276                                 _int_args[READAHEAD_ARG] = atoi(optarg);
3277                                 if (_int_args[READAHEAD_ARG] < -1) {
3278                                         log_error("Negative read ahead value "
3279                                                   "(%d) is not understood.",
3280                                                   _int_args[READAHEAD_ARG]);
3281                                         return 0;
3282                                 }
3283                         }
3284                 }
3285                 if ((ind == ROWS_ARG))
3286                         _switches[ROWS_ARG]++;
3287                 if ((ind == SETUUID_ARG))
3288                         _switches[SETUUID_ARG]++;
3289                 if ((ind == SHOWKEYS_ARG))
3290                         _switches[SHOWKEYS_ARG]++;
3291                 if ((ind == TABLE_ARG)) {
3292                         _switches[TABLE_ARG]++;
3293                         _table = optarg;
3294                 }
3295                 if ((ind == TREE_ARG))
3296                         _switches[TREE_ARG]++;
3297                 if ((ind == UNQUOTED_ARG))
3298                         _switches[UNQUOTED_ARG]++;
3299                 if ((ind == VERSION_ARG))
3300                         _switches[VERSION_ARG]++;
3301         }
3302
3303         if (_switches[VERBOSE_ARG] > 1)
3304                 dm_log_init_verbose(_switches[VERBOSE_ARG] - 1);
3305
3306         if ((_switches[MAJOR_ARG] && !_switches[MINOR_ARG]) ||
3307             (!_switches[MAJOR_ARG] && _switches[MINOR_ARG])) {
3308                 fprintf(stderr, "Please specify both major number and "
3309                                 "minor number.\n");
3310                 return 0;
3311         }
3312
3313         if (_switches[TREE_ARG] && !_process_tree_options(_string_args[OPTIONS_ARG]))
3314                 return 0;
3315
3316         if (_switches[TABLE_ARG] && _switches[NOTABLE_ARG]) {
3317                 fprintf(stderr, "--table and --notable are incompatible.\n");
3318                 return 0;
3319         }
3320
3321         *argv += optind;
3322         *argc -= optind;
3323         return 1;
3324 }
3325
3326 int main(int argc, char **argv)
3327 {
3328         struct command *c;
3329         int r = 1;
3330         const char *dev_dir;
3331
3332         (void) setlocale(LC_ALL, "");
3333
3334         dev_dir = getenv (DM_DEV_DIR_ENV_VAR_NAME);
3335         if (dev_dir && *dev_dir) {
3336                 if (!dm_set_dev_dir(dev_dir)) {
3337                         fprintf(stderr, "Invalid DM_DEV_DIR environment variable value.\n");
3338                         goto out;
3339                 }
3340         } else
3341                 dev_dir = DEFAULT_DM_DEV_DIR;
3342
3343         if (!_process_switches(&argc, &argv, dev_dir)) {
3344                 fprintf(stderr, "Couldn't process command line.\n");
3345                 goto out;
3346         }
3347
3348         if (_switches[HELP_ARG]) {
3349                 c = _find_command("help");
3350                 goto doit;
3351         }
3352
3353         if (_switches[VERSION_ARG]) {
3354                 c = _find_command("version");
3355                 goto doit;
3356         }
3357
3358         if (argc == 0) {
3359                 _usage(stderr);
3360                 goto out;
3361         }
3362
3363         if (!(c = _find_command(argv[0]))) {
3364                 fprintf(stderr, "Unknown command\n");
3365                 _usage(stderr);
3366                 goto out;
3367         }
3368
3369         if (argc < c->min_args + 1 ||
3370             (c->max_args >= 0 && argc > c->max_args + 1)) {
3371                 fprintf(stderr, "Incorrect number of arguments\n");
3372                 _usage(stderr);
3373                 goto out;
3374         }
3375
3376         if (!_switches[COLS_ARG] && !strcmp(c->name, "splitname"))
3377                 _switches[COLS_ARG]++;
3378
3379         if (_switches[COLS_ARG]) {
3380                 if (!_report_init(c))
3381                         goto out;
3382                 if (!_report) {
3383                         if (!strcmp(c->name, "info"))
3384                                 r = 0;  /* info -c -o help */
3385                         goto out;
3386                 }
3387         }
3388
3389         #ifdef UDEV_SYNC_SUPPORT
3390         if (!_set_up_udev_support(dev_dir))
3391                 goto out;
3392         #endif
3393
3394       doit:
3395         if (!c->fn(argc, argv, NULL)) {
3396                 fprintf(stderr, "Command failed\n");
3397                 goto out;
3398         }
3399
3400         r = 0;
3401
3402 out:
3403         if (_report) {
3404                 dm_report_output(_report);
3405                 dm_report_free(_report);
3406         }
3407
3408         if (_dtree)
3409                 dm_tree_free(_dtree);
3410
3411         return r;
3412 }