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