2011-09-23 12:00:45 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
2011-10-13 19:43:52 +04:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <string.h>
|
2012-02-17 22:51:23 +04:00
|
|
|
#include <ctype.h>
|
2011-09-23 12:00:45 +04:00
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
|
|
|
|
#include "compiler.h"
|
|
|
|
#include "crtools.h"
|
2011-12-26 22:12:03 +04:00
|
|
|
#include "sockets.h"
|
2012-01-31 22:28:22 +04:00
|
|
|
#include "syscall.h"
|
2012-04-28 17:15:12 +04:00
|
|
|
#include "files.h"
|
|
|
|
#include "sk-inet.h"
|
2012-09-02 01:07:32 +04:00
|
|
|
#include "net.h"
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-04-19 11:48:00 +04:00
|
|
|
struct cr_options opts;
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-05-12 02:34:22 +04:00
|
|
|
static int parse_ns_string(const char *ptr)
|
2012-01-31 22:28:22 +04:00
|
|
|
{
|
|
|
|
const char *end = ptr + strlen(ptr);
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (ptr[3] != ',' && ptr[3] != '\0')
|
|
|
|
goto bad_ns;
|
|
|
|
if (!strncmp(ptr, "uts", 3))
|
|
|
|
opts.namespaces_flags |= CLONE_NEWUTS;
|
2012-01-31 22:28:55 +04:00
|
|
|
else if (!strncmp(ptr, "ipc", 3))
|
|
|
|
opts.namespaces_flags |= CLONE_NEWIPC;
|
2012-05-12 03:30:10 +04:00
|
|
|
else if (!strncmp(ptr, "mnt", 3))
|
|
|
|
opts.namespaces_flags |= CLONE_NEWNS;
|
2012-06-22 00:38:00 +04:00
|
|
|
else if (!strncmp(ptr, "pid", 3))
|
|
|
|
opts.namespaces_flags |= CLONE_NEWPID;
|
2012-08-02 08:06:29 +04:00
|
|
|
else if (!strncmp(ptr, "net", 3))
|
|
|
|
opts.namespaces_flags |= CLONE_NEWNET;
|
2012-01-31 22:28:22 +04:00
|
|
|
else
|
|
|
|
goto bad_ns;
|
|
|
|
ptr += 4;
|
|
|
|
} while (ptr < end);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
bad_ns:
|
|
|
|
pr_err("Unknown namespace '%s'\n", ptr);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-09-23 12:00:45 +04:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2011-12-28 20:39:00 +04:00
|
|
|
pid_t pid = 0;
|
2011-09-23 12:00:45 +04:00
|
|
|
int ret = -1;
|
2011-10-13 19:43:52 +04:00
|
|
|
int opt, idx;
|
2011-12-08 18:39:00 +04:00
|
|
|
int log_inited = 0;
|
2012-02-17 22:51:23 +04:00
|
|
|
int log_level = 0;
|
2011-10-13 19:43:52 +04:00
|
|
|
|
2012-10-18 15:51:57 +04:00
|
|
|
static const char short_opts[] = "dsf:t:hcD:o:n:vxVr:j";
|
2011-09-23 12:00:45 +04:00
|
|
|
|
|
|
|
BUILD_BUG_ON(PAGE_SIZE != PAGE_IMAGE_SIZE);
|
|
|
|
|
2012-08-07 02:00:39 +04:00
|
|
|
cr_pb_init();
|
|
|
|
|
2012-03-02 14:01:08 +04:00
|
|
|
if (argc < 2)
|
2011-09-23 12:00:45 +04:00
|
|
|
goto usage;
|
|
|
|
|
2011-11-22 22:09:28 +04:00
|
|
|
/* Default options */
|
2012-03-01 19:09:02 +04:00
|
|
|
opts.final_state = TASK_DEAD;
|
2012-09-02 01:07:32 +04:00
|
|
|
INIT_LIST_HEAD(&opts.veth_pairs);
|
2012-09-17 20:05:23 +04:00
|
|
|
INIT_LIST_HEAD(&opts.scripts);
|
2011-11-22 22:09:28 +04:00
|
|
|
|
2012-09-13 14:45:06 +04:00
|
|
|
if (init_service_fd())
|
|
|
|
return -1;
|
|
|
|
|
2012-04-16 14:14:41 +04:00
|
|
|
while (1) {
|
2012-04-16 14:23:05 +04:00
|
|
|
static struct option long_opts[] = {
|
|
|
|
{ "tree", required_argument, 0, 't' },
|
|
|
|
{ "leave-stopped", no_argument, 0, 's' },
|
|
|
|
{ "restore-detached", no_argument, 0, 'd' },
|
|
|
|
{ "contents", no_argument, 0, 'c' },
|
|
|
|
{ "file", required_argument, 0, 'f' },
|
|
|
|
{ "images-dir", required_argument, 0, 'D' },
|
|
|
|
{ "log-file", required_argument, 0, 'o' },
|
|
|
|
{ "namespaces", required_argument, 0, 'n' },
|
2012-08-02 16:07:43 +04:00
|
|
|
{ "root", required_argument, 0, 'r' },
|
2012-04-19 11:48:00 +04:00
|
|
|
{ "ext-unix-sk", no_argument, 0, 'x' },
|
2012-04-16 14:23:05 +04:00
|
|
|
{ "help", no_argument, 0, 'h' },
|
2012-04-28 17:15:12 +04:00
|
|
|
{ SK_EST_PARAM, no_argument, 0, 42 },
|
2012-04-28 20:37:54 +04:00
|
|
|
{ "close", required_argument, 0, 43 },
|
2012-05-02 14:42:00 +04:00
|
|
|
{ "log-pid", no_argument, 0, 44},
|
2012-07-19 16:51:58 +04:00
|
|
|
{ "version", no_argument, 0, 'V'},
|
2012-08-07 19:33:49 +04:00
|
|
|
{ "evasive-devices", no_argument, 0, 45},
|
2012-08-14 12:54:00 +04:00
|
|
|
{ "pidfile", required_argument, 0, 46},
|
2012-09-02 01:07:32 +04:00
|
|
|
{ "veth-pair", required_argument, 0, 47},
|
2012-09-17 20:05:23 +04:00
|
|
|
{ "action-script", required_argument, 0, 49},
|
2012-09-26 06:39:23 +04:00
|
|
|
{ LREMAP_PARAM, no_argument, 0, 41},
|
2012-10-18 15:51:57 +04:00
|
|
|
{ "shell-job", no_argument, 0, 'j'},
|
2012-04-16 14:23:05 +04:00
|
|
|
{ },
|
|
|
|
};
|
|
|
|
|
2012-07-19 16:50:04 +04:00
|
|
|
opt = getopt_long(argc, argv, short_opts, long_opts, &idx);
|
2012-04-16 14:14:41 +04:00
|
|
|
if (opt == -1)
|
|
|
|
break;
|
|
|
|
|
2011-10-13 19:43:52 +04:00
|
|
|
switch (opt) {
|
ctrools: Rewrite task/threads stopping engine is back
This commit brings the former "Rewrite task/threads stopping engine"
commit back. Handling it separately is too complex so better try
to handle it in-place.
Note some tests might fault, it's expected.
---
Stopping tasks with STOP and proceeding with SEIZE is actually excessive --
the SEIZE if enough. Moreover, just killing a task with STOP is also racy,
since task should be given some time to come to sleep before its proc
can be parsed.
Rewrite all this code to SEIZE task and all its threads from the very beginning.
With this we can distinguish stopped task state and migrate it properly (not
supported now, need to implement).
This thing however has one BIG problem -- after we SEIZE-d a task we should
seize
it's threads, but we should do it in a loop -- reading /proc/pid/task and
seizing
them again and again, until the contents of this dir stops changing (not done
now).
Besides, after we seized a task and all its threads we cannot scan it's children
list once -- task can get reparented to init and any task's child can call clone
with CLONE_PARENT flag thus repopulating the children list of the already seized
task (not done also)
This patch is ugly, yes, but splitting it doesn't help to review it much, sorry
:(
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
2012-02-01 19:45:31 +04:00
|
|
|
case 's':
|
2012-03-01 19:09:02 +04:00
|
|
|
opts.final_state = TASK_STOPPED;
|
ctrools: Rewrite task/threads stopping engine is back
This commit brings the former "Rewrite task/threads stopping engine"
commit back. Handling it separately is too complex so better try
to handle it in-place.
Note some tests might fault, it's expected.
---
Stopping tasks with STOP and proceeding with SEIZE is actually excessive --
the SEIZE if enough. Moreover, just killing a task with STOP is also racy,
since task should be given some time to come to sleep before its proc
can be parsed.
Rewrite all this code to SEIZE task and all its threads from the very beginning.
With this we can distinguish stopped task state and migrate it properly (not
supported now, need to implement).
This thing however has one BIG problem -- after we SEIZE-d a task we should
seize
it's threads, but we should do it in a loop -- reading /proc/pid/task and
seizing
them again and again, until the contents of this dir stops changing (not done
now).
Besides, after we seized a task and all its threads we cannot scan it's children
list once -- task can get reparented to init and any task's child can call clone
with CLONE_PARENT flag thus repopulating the children list of the already seized
task (not done also)
This patch is ugly, yes, but splitting it doesn't help to review it much, sorry
:(
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
2012-02-01 19:45:31 +04:00
|
|
|
break;
|
2012-04-19 11:48:00 +04:00
|
|
|
case 'x':
|
|
|
|
opts.ext_unix_sk = true;
|
|
|
|
break;
|
2011-10-13 19:43:52 +04:00
|
|
|
case 't':
|
|
|
|
pid = atoi(optarg);
|
|
|
|
break;
|
2011-12-05 15:57:47 +04:00
|
|
|
case 'c':
|
|
|
|
opts.show_pages_content = true;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
opts.show_dump_file = optarg;
|
|
|
|
break;
|
2012-08-02 16:07:43 +04:00
|
|
|
case 'r':
|
|
|
|
opts.root = optarg;
|
|
|
|
break;
|
2012-01-18 23:24:37 +04:00
|
|
|
case 'd':
|
|
|
|
opts.restore_detach = true;
|
|
|
|
break;
|
2011-12-07 13:48:00 +04:00
|
|
|
case 'D':
|
|
|
|
if (chdir(optarg)) {
|
2012-02-01 02:08:04 +04:00
|
|
|
pr_perror("Can't change directory to %s",
|
|
|
|
optarg);
|
2011-12-19 16:51:26 +04:00
|
|
|
return -1;
|
2011-12-07 13:48:00 +04:00
|
|
|
}
|
|
|
|
break;
|
2011-12-08 18:39:00 +04:00
|
|
|
case 'o':
|
2012-05-02 14:42:00 +04:00
|
|
|
opts.output = strdup(optarg);
|
2012-03-01 18:52:42 +04:00
|
|
|
if (log_init(optarg))
|
2011-12-19 16:51:26 +04:00
|
|
|
return -1;
|
2011-12-08 18:39:00 +04:00
|
|
|
log_inited = 1;
|
|
|
|
break;
|
2012-01-26 15:27:00 +04:00
|
|
|
case 'n':
|
2012-05-12 02:34:22 +04:00
|
|
|
if (parse_ns_string(optarg))
|
2012-01-31 22:28:22 +04:00
|
|
|
return -1;
|
2012-01-26 15:27:00 +04:00
|
|
|
break;
|
2012-02-17 22:51:23 +04:00
|
|
|
case 'v':
|
2012-11-02 13:44:26 +04:00
|
|
|
if (optind < argc) {
|
2012-07-19 17:25:04 +04:00
|
|
|
char *opt = argv[optind];
|
2012-02-17 22:51:23 +04:00
|
|
|
|
|
|
|
if (isdigit(*opt)) {
|
|
|
|
log_level = -atoi(opt);
|
|
|
|
optind++;
|
|
|
|
} else {
|
|
|
|
if (log_level >= 0)
|
|
|
|
log_level++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (log_level >= 0)
|
|
|
|
log_level++;
|
|
|
|
}
|
|
|
|
break;
|
2012-09-26 06:39:23 +04:00
|
|
|
case 41:
|
|
|
|
pr_info("Will allow link remaps on FS\n");
|
|
|
|
opts.link_remap_ok = true;
|
|
|
|
break;
|
2012-04-28 17:15:12 +04:00
|
|
|
case 42:
|
|
|
|
pr_info("Will dump TCP connections\n");
|
|
|
|
opts.tcp_established_ok = true;
|
|
|
|
break;
|
2012-04-28 20:37:54 +04:00
|
|
|
case 43: {
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
fd = atoi(optarg);
|
|
|
|
pr_info("Closing fd %d\n", fd);
|
|
|
|
close(fd);
|
|
|
|
break;
|
|
|
|
}
|
2012-05-02 14:42:00 +04:00
|
|
|
case 44:
|
|
|
|
opts.log_file_per_pid = 1;
|
|
|
|
break;
|
2012-08-07 19:33:49 +04:00
|
|
|
case 45:
|
|
|
|
opts.evasive_devices = true;
|
|
|
|
break;
|
2012-08-14 12:54:00 +04:00
|
|
|
case 46:
|
|
|
|
opts.pidfile = optarg;
|
|
|
|
break;
|
2012-09-02 01:07:32 +04:00
|
|
|
case 47:
|
|
|
|
{
|
|
|
|
struct veth_pair *n;
|
|
|
|
|
|
|
|
n = xmalloc(sizeof(*n));
|
|
|
|
if (n == NULL)
|
|
|
|
return -1;
|
|
|
|
n->outside = strchr(optarg, '=');
|
|
|
|
if (n->outside == NULL) {
|
|
|
|
xfree(n);
|
|
|
|
pr_err("Invalid agument for --veth-pair\n");
|
|
|
|
goto usage;
|
|
|
|
}
|
|
|
|
|
|
|
|
*n->outside++ = '\0';
|
|
|
|
n->inside = optarg;
|
|
|
|
list_add(&n->node, &opts.veth_pairs);
|
|
|
|
}
|
|
|
|
break;
|
2012-09-17 20:05:23 +04:00
|
|
|
case 49:
|
|
|
|
{
|
|
|
|
struct script *script;
|
|
|
|
|
|
|
|
script = xmalloc(sizeof(struct script));
|
|
|
|
if (script == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
script->path = optarg;
|
|
|
|
list_add(&script->node, &opts.scripts);
|
|
|
|
}
|
|
|
|
break;
|
2012-10-18 15:51:57 +04:00
|
|
|
case 'j':
|
|
|
|
opts.shell_job = true;
|
|
|
|
break;
|
2012-07-19 16:51:58 +04:00
|
|
|
case 'V':
|
|
|
|
pr_msg("Version: %d.%d\n", CRIU_VERSION_MAJOR, CRIU_VERSION_MINOR);
|
|
|
|
return 0;
|
2011-10-13 19:43:52 +04:00
|
|
|
case 'h':
|
|
|
|
default:
|
|
|
|
goto usage;
|
|
|
|
}
|
2011-10-04 01:50:19 +04:00
|
|
|
}
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-02-17 22:51:23 +04:00
|
|
|
if (log_level < 0)
|
|
|
|
log_level = -log_level;
|
2012-03-01 18:52:42 +04:00
|
|
|
log_set_loglevel(log_level);
|
2012-02-17 22:51:23 +04:00
|
|
|
|
2011-12-13 15:03:33 +04:00
|
|
|
if (!log_inited) {
|
2012-03-01 18:52:42 +04:00
|
|
|
ret = log_init(NULL);
|
2011-12-13 15:03:33 +04:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
2011-12-08 18:39:00 +04:00
|
|
|
|
2012-03-16 17:24:00 +04:00
|
|
|
ret = open_image_dir();
|
|
|
|
if (ret < 0) {
|
|
|
|
pr_perror("can't open currect directory");
|
2011-12-13 15:03:33 +04:00
|
|
|
return -1;
|
2011-12-07 13:48:00 +04:00
|
|
|
}
|
|
|
|
|
2012-07-28 09:08:46 +04:00
|
|
|
if (optind >= argc)
|
|
|
|
goto usage;
|
|
|
|
|
2012-07-19 16:50:04 +04:00
|
|
|
if (strcmp(argv[optind], "dump") &&
|
|
|
|
strcmp(argv[optind], "restore") &&
|
|
|
|
strcmp(argv[optind], "show") &&
|
|
|
|
strcmp(argv[optind], "check")) {
|
2012-11-01 15:28:37 +04:00
|
|
|
pr_err("Unknown command %s\n", argv[optind]);
|
2012-01-18 18:53:49 +03:00
|
|
|
goto usage;
|
|
|
|
}
|
|
|
|
|
2012-07-19 16:50:04 +04:00
|
|
|
switch (argv[optind][0]) {
|
2011-10-13 19:43:52 +04:00
|
|
|
case 'd':
|
2012-03-27 11:04:23 +04:00
|
|
|
if (!pid)
|
|
|
|
goto opt_pid_missing;
|
2011-10-04 01:50:19 +04:00
|
|
|
ret = cr_dump_tasks(pid, &opts);
|
2011-10-13 19:43:52 +04:00
|
|
|
break;
|
|
|
|
case 'r':
|
2012-03-27 11:04:23 +04:00
|
|
|
if (!pid)
|
|
|
|
goto opt_pid_missing;
|
2011-10-04 01:50:19 +04:00
|
|
|
ret = cr_restore_tasks(pid, &opts);
|
2011-10-13 19:43:52 +04:00
|
|
|
break;
|
|
|
|
case 's':
|
2012-03-27 11:04:23 +04:00
|
|
|
ret = cr_show(&opts);
|
2011-10-13 19:43:52 +04:00
|
|
|
break;
|
2012-03-02 14:01:08 +04:00
|
|
|
case 'c':
|
|
|
|
ret = cr_check();
|
|
|
|
break;
|
2011-10-13 19:43:52 +04:00
|
|
|
default:
|
2011-09-23 12:00:45 +04:00
|
|
|
goto usage;
|
2011-10-13 19:43:52 +04:00
|
|
|
break;
|
|
|
|
}
|
2011-09-23 12:00:45 +04:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
usage:
|
2012-03-01 18:52:42 +04:00
|
|
|
pr_msg("\nUsage:\n");
|
2012-07-23 07:09:22 +04:00
|
|
|
pr_msg(" %s dump -t pid [<options>]\n", argv[0]);
|
|
|
|
pr_msg(" %s restore -t pid [<options>]\n", argv[0]);
|
2012-04-29 09:23:12 +04:00
|
|
|
pr_msg(" %s show (-D dir)|(-f file) [<options>]\n", argv[0]);
|
2012-03-02 14:01:08 +04:00
|
|
|
pr_msg(" %s check\n", argv[0]);
|
2012-03-01 18:52:42 +04:00
|
|
|
|
|
|
|
pr_msg("\nCommands:\n");
|
2012-04-29 09:23:12 +04:00
|
|
|
pr_msg(" dump checkpoint a process/tree identified by pid\n");
|
|
|
|
pr_msg(" restore restore a process/tree identified by pid\n");
|
2012-03-27 11:04:23 +04:00
|
|
|
pr_msg(" show show dump file(s) contents\n");
|
2012-03-02 14:01:08 +04:00
|
|
|
pr_msg(" check checks whether the kernel support is up-to-date\n");
|
2012-04-29 09:23:12 +04:00
|
|
|
|
|
|
|
pr_msg("\nDump/Restore options:\n");
|
|
|
|
|
|
|
|
pr_msg("\n* Generic:\n");
|
2012-04-16 14:23:05 +04:00
|
|
|
pr_msg(" -t|--tree checkpoint/restore the whole process tree identified by pid\n");
|
|
|
|
pr_msg(" -d|--restore-detached detach after restore\n");
|
|
|
|
pr_msg(" -s|--leave-stopped leave tasks in stopped state after checkpoint instead of killing them\n");
|
2012-04-29 09:23:12 +04:00
|
|
|
pr_msg(" -D|--images-dir directory where to put images to\n");
|
2012-08-14 12:54:00 +04:00
|
|
|
pr_msg(" --pidfile [FILE] write a pid of a root task in this file\n");
|
2012-04-29 09:23:12 +04:00
|
|
|
|
|
|
|
pr_msg("\n* Special resources support:\n");
|
2012-04-16 14:23:05 +04:00
|
|
|
pr_msg(" -n|--namespaces checkpoint/restore namespaces - values must be separated by comma\n");
|
2012-08-06 18:29:53 +04:00
|
|
|
pr_msg(" supported: uts, ipc, mnt, pid, net\n");
|
2012-04-19 11:48:00 +04:00
|
|
|
pr_msg(" -x|--ext-unix-sk allow external unix connections\n");
|
2012-04-29 09:23:12 +04:00
|
|
|
pr_msg(" --%s checkpoint/restore established TCP connections\n", SK_EST_PARAM);
|
2012-08-02 16:07:43 +04:00
|
|
|
pr_msg(" -r|--root [PATH] change the root filesystem (when run in mount namespace)\n");
|
2012-08-07 19:33:49 +04:00
|
|
|
pr_msg(" --evasive-devices use any path to a device file if the original one is inaccessible\n");
|
2012-09-02 01:07:32 +04:00
|
|
|
pr_msg(" --veth-pair [IN=OUT] correspondence between outside and inside names of veth devices\n");
|
2012-09-26 06:39:23 +04:00
|
|
|
pr_msg(" --link-remap allow to link unlinked files back when possible (modifies FS till restore)\n");
|
2012-09-17 20:05:23 +04:00
|
|
|
pr_msg(" --action-script [SCR] add an external action script\n");
|
|
|
|
pr_msg(" The environment variable CRTOOL_SCRIPT_ACTION contains one of the actions:\n");
|
2012-09-26 20:11:54 +04:00
|
|
|
pr_msg(" * network-lock - lock network in a target network namespace\n");
|
|
|
|
pr_msg(" * network-unlock - unlock network in a target network namespace\n");
|
2012-10-18 15:51:57 +04:00
|
|
|
pr_msg(" -j|--shell-job allow to dump and restore shell jobs\n");
|
2012-03-01 18:52:42 +04:00
|
|
|
|
2012-04-29 09:23:12 +04:00
|
|
|
pr_msg("\n* Logging:\n");
|
2012-05-02 14:42:00 +04:00
|
|
|
pr_msg(" -o|--log-file [NAME] log file name (relative path is relative to --images-dir)\n");
|
|
|
|
pr_msg(" --log-pid if the -o option is in effect, each restored processes is\n");
|
|
|
|
pr_msg(" written to the [NAME].pid file\n");
|
2012-04-16 14:23:05 +04:00
|
|
|
pr_msg(" -v [num] set logging level\n");
|
2012-11-02 13:45:25 +04:00
|
|
|
pr_msg(" 0 - messages regardless of log level\n");
|
|
|
|
pr_msg(" 1 - errors, when we are in trouble\n");
|
|
|
|
pr_msg(" 2 - warnings (default)\n");
|
|
|
|
pr_msg(" 3 - informative, everything is fine\n");
|
|
|
|
pr_msg(" 4 - debug only\n");
|
|
|
|
pr_msg(" -v same as -v 1\n");
|
|
|
|
pr_msg(" -vv same as -v 2\n");
|
|
|
|
pr_msg(" -vvv same as -v 3\n");
|
|
|
|
pr_msg(" -vvvv same as -v 4\n");
|
2012-04-29 09:23:12 +04:00
|
|
|
|
|
|
|
pr_msg("\nShow options:\n");
|
|
|
|
pr_msg(" -f|--file show contents of a checkpoint file\n");
|
|
|
|
pr_msg(" -D|--images-dir directory where to get images from\n");
|
|
|
|
pr_msg(" -c|--contents show contents of pages dumped in hexdump format\n");
|
2011-12-05 15:57:47 +04:00
|
|
|
|
2012-07-19 16:50:04 +04:00
|
|
|
pr_msg("\nOther options:\n");
|
|
|
|
pr_msg(" -h|--help show this text\n");
|
2012-07-19 16:51:58 +04:00
|
|
|
pr_msg(" -V|--version show version\n");
|
2012-07-19 16:50:04 +04:00
|
|
|
|
2011-09-23 12:00:45 +04:00
|
|
|
return -1;
|
2011-12-20 19:47:06 +04:00
|
|
|
|
|
|
|
opt_pid_missing:
|
2012-07-28 09:09:52 +04:00
|
|
|
pr_msg("No pid specified (-t option missing)\n");
|
2011-12-20 19:47:06 +04:00
|
|
|
return -1;
|
2011-09-23 12:00:45 +04:00
|
|
|
}
|