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