📄 dmsetup.c
字号:
static int _simple(int task, const char *name, uint32_t event_nr, int display){ int r = 0; struct dm_task *dmt; if (!(dmt = dm_task_create(task))) return 0; if (!_set_task_device(dmt, name, 0)) goto out; if (event_nr && !dm_task_set_event_nr(dmt, event_nr)) goto out; if (_switches[NOFLUSH_ARG] && !dm_task_no_flush(dmt)) goto out; if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; if (_switches[NOLOCKFS_ARG] && !dm_task_skip_lockfs(dmt)) goto out; r = dm_task_run(dmt); if (r && display && _switches[VERBOSE_ARG]) r = _display_info(dmt); out: dm_task_destroy(dmt); return r;}static int _suspend(int argc, char **argv, void *data __attribute((unused))){ return _simple(DM_DEVICE_SUSPEND, argc > 1 ? argv[1] : NULL, 0, 1);}static int _resume(int argc, char **argv, void *data __attribute((unused))){ return _simple(DM_DEVICE_RESUME, argc > 1 ? argv[1] : NULL, 0, 1);}static int _clear(int argc, char **argv, void *data __attribute((unused))){ return _simple(DM_DEVICE_CLEAR, argc > 1 ? argv[1] : NULL, 0, 1);}static int _wait(int argc, char **argv, void *data __attribute((unused))){ const char *name = NULL; if (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]) { if (argc == 1) { err("No device specified."); return 0; } name = argv[1]; argc--, argv++; } return _simple(DM_DEVICE_WAITEVENT, name, (argc > 1) ? (uint32_t) atoi(argv[argc - 1]) : 0, 1);}static int _process_all(int argc, char **argv, int silent, int (*fn) (int argc, char **argv, void *data)){ int r = 1; struct dm_names *names; unsigned next = 0; struct dm_task *dmt; if (!(dmt = dm_task_create(DM_DEVICE_LIST))) return 0; if (!dm_task_run(dmt)) { r = 0; goto out; } if (!(names = dm_task_get_names(dmt))) { r = 0; goto out; } if (!names->dev) { if (!silent) printf("No devices found\n"); goto out; } do { names = (void *) names + next; if (!fn(argc, argv, (void *) names)) r = 0; next = names->next; } while (next); out: dm_task_destroy(dmt); return r;}static uint64_t _get_device_size(const char *name){ uint64_t start, length, size = UINT64_C(0); struct dm_info info; char *target_type, *params; struct dm_task *dmt; void *next = NULL; if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) return 0; if (!_set_task_device(dmt, name, 0)) goto out; if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &info) || !info.exists) goto out; do { next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); size += length; } while (next); out: dm_task_destroy(dmt); return size;}static int _error_device(int argc __attribute((unused)), char **argv __attribute((unused)), void *data){ struct dm_names *names = (struct dm_names *) data; struct dm_task *dmt; const char *name; uint64_t size; int r = 0; if (data) name = names->name; else name = argv[1]; size = _get_device_size(name); if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) return 0; if (!_set_task_device(dmt, name, 0)) goto error; if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", "")) goto error; if (_switches[READ_ONLY] && !dm_task_set_ro(dmt)) goto error; if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto error; if (!dm_task_run(dmt)) goto error; if (!_simple(DM_DEVICE_RESUME, name, 0, 0)) { _simple(DM_DEVICE_CLEAR, name, 0, 0); goto error; } r = 1;error: dm_task_destroy(dmt); return r;}static int _remove(int argc, char **argv, void *data __attribute((unused))){ int r; if (_switches[FORCE_ARG] && argc > 1) r = _error_device(argc, argv, NULL); return _simple(DM_DEVICE_REMOVE, argc > 1 ? argv[1] : NULL, 0, 0);}static int _count_devices(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused))){ _num_devices++; return 1;}static int _remove_all(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused))){ int r; /* Remove all closed devices */ r = _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL); if (!_switches[FORCE_ARG]) return r; _num_devices = 0; r |= _process_all(argc, argv, 1, _count_devices); /* No devices left? */ if (!_num_devices) return r; r |= _process_all(argc, argv, 1, _error_device); r |= _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL); _num_devices = 0; r |= _process_all(argc, argv, 1, _count_devices); if (!_num_devices) return r; fprintf(stderr, "Unable to remove %d device(s).\n", _num_devices); return r;}static void _display_dev(struct dm_task *dmt, const char *name){ struct dm_info info; if (dm_task_get_info(dmt, &info)) printf("%s\t(%u, %u)\n", name, info.major, info.minor);}static int _mknodes(int argc, char **argv, void *data __attribute((unused))){ return dm_mknodes(argc > 1 ? argv[1] : NULL);}static int _exec_command(const char *name){ int n; static char path[PATH_MAX]; static char *args[ARGS_MAX + 1]; static int argc = 0; char *c; pid_t pid; if (argc < 0) return 0; if (!dm_mknodes(name)) return 0; n = snprintf(path, sizeof(path), "%s/%s", dm_dir(), name); if (n < 0 || n > (int) sizeof(path) - 1) return 0; if (!argc) { c = _command; while (argc < ARGS_MAX) { while (*c && isspace(*c)) c++; if (!*c) break; args[argc++] = c; while (*c && !isspace(*c)) c++; if (*c) *c++ = '\0'; } if (!argc) { argc = -1; return 0; } if (argc == ARGS_MAX) { err("Too many args to --exec\n"); argc = -1; return 0; } args[argc++] = path; args[argc] = NULL; } if (!(pid = fork())) { execvp(args[0], args); exit(127); } else if (pid < (pid_t) 0) return 0; TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0)); return 1;}static int _status(int argc, char **argv, void *data){ int r = 0; struct dm_task *dmt; void *next = NULL; uint64_t start, length; char *target_type = NULL; char *params, *c; int cmd; struct dm_names *names = (struct dm_names *) data; const char *name = NULL; int matched = 0; int ls_only = 0; struct dm_info info; if (data) name = names->name; else { if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG]) return _process_all(argc, argv, 0, _status); if (argc == 2) name = argv[1]; } if (!strcmp(argv[0], "table")) cmd = DM_DEVICE_TABLE; else cmd = DM_DEVICE_STATUS; if (!strcmp(argv[0], "ls")) ls_only = 1; if (!(dmt = dm_task_create(cmd))) return 0; if (!_set_task_device(dmt, name, 0)) goto out; if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &info) || !info.exists) goto out; if (!name) name = dm_task_get_name(dmt); /* Fetch targets and print 'em */ do { next = dm_get_next_target(dmt, next, &start, &length, &target_type, ¶ms); /* Skip if target type doesn't match */ if (_switches[TARGET_ARG] && (!target_type || strcmp(target_type, _target))) continue; if (ls_only) { if (!_switches[EXEC_ARG] || !_command || _switches[VERBOSE_ARG]) _display_dev(dmt, name); next = NULL; } else if (!_switches[EXEC_ARG] || !_command || _switches[VERBOSE_ARG]) { if (!matched && _switches[VERBOSE_ARG]) _display_info(dmt); if (data && !_switches[VERBOSE_ARG]) printf("%s: ", name); if (target_type) { /* Suppress encryption key */ if (!_switches[SHOWKEYS_ARG] && cmd == DM_DEVICE_TABLE && !strcmp(target_type, "crypt")) { c = params; while (*c && *c != ' ') c++; if (*c) c++; while (*c && *c != ' ') *c++ = '0'; } printf("%" PRIu64 " %" PRIu64 " %s %s", start, length, target_type, params); } printf("\n"); } matched = 1; } while (next); if (data && _switches[VERBOSE_ARG] && matched && !ls_only) printf("\n"); if (matched && _switches[EXEC_ARG] && _command && !_exec_command(name)) goto out; r = 1; out: dm_task_destroy(dmt); return r;}/* Show target names and their version numbers */static int _targets(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused))){ int r = 0; struct dm_task *dmt; struct dm_versions *target; struct dm_versions *last_target; if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS))) return 0; if (!dm_task_run(dmt)) goto out; target = dm_task_get_versions(dmt); /* Fetch targets and print 'em */ do { last_target = target; printf("%-16s v%d.%d.%d\n", target->name, target->version[0], target->version[1], target->version[2]); target = (void *) target + target->next; } while (last_target != target); r = 1; out: dm_task_destroy(dmt); return r;}static int _info(int argc, char **argv, void *data){ int r = 0; struct dm_task *dmt; struct dm_names *names = (struct dm_names *) data; char *name = NULL; if (data) name = names->name; else { if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG]) return _process_all(argc, argv, 0, _info); if (argc == 2) name = argv[1]; } if (!(dmt = dm_task_create(DM_DEVICE_INFO))) return 0; if (!_set_task_device(dmt, name, 0)) goto out; if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; if (!dm_task_run(dmt)) goto out; r = _display_info(dmt); out: dm_task_destroy(dmt); return r;}static int _deps(int argc, char **argv, void *data){ int r = 0; uint32_t i; struct dm_deps *deps; struct dm_task *dmt; struct dm_info info; struct dm_names *names = (struct dm_names *) data; char *name = NULL; if (data) name = names->name; else { if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG]) return _process_all(argc, argv, 0, _deps); if (argc == 2) name = argv[1]; } if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) return 0; if (!_set_task_device(dmt, name, 0)) goto out; if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt)) goto out; if (!dm_task_run(dmt)) goto out; if (!dm_task_get_info(dmt, &info)) goto out; if (!(deps = dm_task_get_deps(dmt))) goto out; if (!info.exists) { printf("Device does not exist.\n"); r = 1; goto out; } if (_switches[VERBOSE_ARG]) _display_info(dmt); if (data && !_switches[VERBOSE_ARG]) printf("%s: ", name); printf("%d dependencies\t:", deps->count); for (i = 0; i < deps->count; i++) printf(" (%d, %d)", (int) MAJOR(deps->device[i]), (int) MINOR(deps->device[i])); printf("\n"); if (data && _switches[VERBOSE_ARG]) printf("\n"); r = 1; out: dm_task_destroy(dmt); return r;}static int _display_name(int argc __attribute((unused)), char **argv __attribute((unused)), void *data){ struct dm_names *names = (struct dm_names *) data; printf("%s\t(%d, %d)\n", names->name, (int) MAJOR(names->dev), (int) MINOR(names->dev)); return 1;}/* * Tree drawing code */enum { TR_DEVICE=0, /* display device major:minor number */ TR_TABLE, TR_STATUS, TR_ACTIVE, TR_RW, TR_OPENCOUNT, TR_UUID, TR_COMPACT, TR_TRUNCATE, TR_BOTTOMUP, NUM_TREEMODE,};static int _tree_switches[NUM_TREEMODE];#define TR_PRINT_ATTRIBUTE ( _tree_switches[TR_ACTIVE] || \ _tree_switches[TR_RW] || \ _tree_switches[TR_OPENCOUNT] || \ _tree_switches[TR_UUID] )#define TR_PRINT_TARGETS ( _tree_switches[TR_TABLE] || \ _tree_switches[TR_STATUS] )/* Compact - fewer newlines */#define TR_PRINT_COMPACT (_tree_switches[TR_COMPACT] && \ !TR_PRINT_ATTRIBUTE && \ !TR_PRINT_TARGETS)/* FIXME Get rid of this */#define MAX_DEPTH 100/* Drawing character definition from pstree *//* [pstree comment] UTF-8 defines by Johan Myreen, updated by Ben Winslow */#define UTF_V "\342\224\202" /* U+2502, Vertical line drawing char */#define UTF_VR "\342\224\234" /* U+251C, Vertical and right */#define UTF_H "\342\224\200" /* U+2500, Horizontal */#define UTF_UR "\342\224\224" /* U+2514, Up and right */#define UTF_HD "\342\224\254" /* U+252C, Horizontal and down */#define VT_BEG "\033(0\017" /* use graphic chars */#define VT_END "\033(B" /* back to normal char set */#define VT_V "x" /* see UTF definitions above */#define VT_VR "t"#define VT_H "q"#define VT_UR "m"#define VT_HD "w"static struct { const char *empty_2; /* */ const char *branch_2; /* |- */ const char *vert_2; /* | */ const char *last_2; /* `- */ const char *single_3; /* --- */ const char *first_3; /* -+- */}_tsym_ascii = { " ", "|-", "| ", "`-", "---", "-+-"},_tsym_utf = { " ", UTF_VR UTF_H, UTF_V " ", UTF_UR UTF_H, UTF_H UTF_H UTF_H, UTF_H UTF_HD UTF_H},_tsym_vt100 = { " ", VT_BEG VT_VR VT_H VT_END, VT_BEG VT_V VT_END " ", VT_BEG VT_UR VT_H VT_END, VT_BEG VT_H VT_H VT_H VT_END, VT_BEG VT_H VT_HD VT_H VT_END},*_tsym = &_tsym_ascii;/* * Tree drawing functions. *//* FIXME Get rid of these statics - use dynamic struct *//* FIXME Explain what these vars are for */static int _tree_width[MAX_DEPTH], _tree_more[MAX_DEPTH];static int _termwidth = 80; /* Maximum output width */static int _cur_x = 1; /* Current horizontal output position */static char _last_char = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -