LCOV - code coverage report
Current view: top level - crtools - crtools.c (source / functions) Hit Total Coverage
Test: crtools.info Lines: 79 178 44.4 %
Date: 2012-12-28 Functions: 2 2 100.0 %
Branches: 50 102 49.0 %

           Branch data     Line data    Source code
       1                 :            : #include <stdio.h>
       2                 :            : #include <stdlib.h>
       3                 :            : #include <limits.h>
       4                 :            : #include <unistd.h>
       5                 :            : #include <errno.h>
       6                 :            : #include <getopt.h>
       7                 :            : #include <string.h>
       8                 :            : #include <ctype.h>
       9                 :            : 
      10                 :            : #include <fcntl.h>
      11                 :            : 
      12                 :            : #include <sys/types.h>
      13                 :            : #include <sys/stat.h>
      14                 :            : 
      15                 :            : #include "types.h"
      16                 :            : 
      17                 :            : #include "compiler.h"
      18                 :            : #include "crtools.h"
      19                 :            : #include "sockets.h"
      20                 :            : #include "syscall.h"
      21                 :            : #include "files.h"
      22                 :            : #include "sk-inet.h"
      23                 :            : #include "net.h"
      24                 :            : 
      25                 :            : struct cr_options opts;
      26                 :            : 
      27                 :       1164 : static int parse_ns_string(const char *ptr)
      28                 :            : {
      29                 :       1164 :         const char *end = ptr + strlen(ptr);
      30                 :            : 
      31                 :            :         do {
      32         [ +  - ]:       1164 :                 if (ptr[3] != ',' && ptr[3] != '\0')
      33                 :            :                         goto bad_ns;
      34         [ +  + ]:       1164 :                 if (!strncmp(ptr, "uts", 3))
      35                 :        231 :                         opts.namespaces_flags |= CLONE_NEWUTS;
      36         [ +  + ]:        933 :                 else if (!strncmp(ptr, "ipc", 3))
      37                 :        246 :                         opts.namespaces_flags |= CLONE_NEWIPC;
      38         [ +  + ]:        687 :                 else if (!strncmp(ptr, "mnt", 3))
      39                 :        231 :                         opts.namespaces_flags |= CLONE_NEWNS;
      40         [ +  + ]:        456 :                 else if (!strncmp(ptr, "pid", 3))
      41                 :        228 :                         opts.namespaces_flags |= CLONE_NEWPID;
      42         [ +  - ]:        228 :                 else if (!strncmp(ptr, "net", 3))
      43                 :        228 :                         opts.namespaces_flags |= CLONE_NEWNET;
      44                 :            :                 else
      45                 :            :                         goto bad_ns;
      46                 :       1164 :                 ptr += 4;
      47         [ -  + ]:       1164 :         } while (ptr < end);
      48                 :            :         return 0;
      49                 :            : 
      50                 :            : bad_ns:
      51                 :          0 :         pr_err("Unknown namespace '%s'\n", ptr);
      52                 :       1164 :         return -1;
      53                 :            : }
      54                 :            : 
      55                 :        547 : int main(int argc, char *argv[])
      56                 :            : {
      57                 :        547 :         pid_t pid = 0;
      58                 :        547 :         int ret = -1;
      59                 :            :         int opt, idx;
      60                 :        547 :         int log_inited = 0;
      61                 :        547 :         int log_level = 0;
      62                 :            : 
      63                 :            :         static const char short_opts[] = "dsf:t:hcD:o:n:vxVr:j";
      64                 :            : 
      65                 :            :         BUILD_BUG_ON(PAGE_SIZE != PAGE_IMAGE_SIZE);
      66                 :            : 
      67                 :        547 :         cr_pb_init();
      68                 :            : 
      69         [ +  - ]:        547 :         if (argc < 2)
      70                 :            :                 goto usage;
      71                 :            : 
      72                 :            :         /* Default options */
      73                 :        547 :         opts.final_state = TASK_DEAD;
      74                 :            :         INIT_LIST_HEAD(&opts.veth_pairs);
      75                 :            :         INIT_LIST_HEAD(&opts.scripts);
      76                 :            : 
      77         [ +  - ]:        547 :         if (init_service_fd())
      78                 :            :                 return -1;
      79                 :            : 
      80                 :            :         while (1) {
      81                 :            :                 static struct option long_opts[] = {
      82                 :            :                         { "tree", required_argument, 0, 't' },
      83                 :            :                         { "leave-stopped", no_argument, 0, 's' },
      84                 :            :                         { "restore-detached", no_argument, 0, 'd' },
      85                 :            :                         { "contents", no_argument, 0, 'c' },
      86                 :            :                         { "file", required_argument, 0, 'f' },
      87                 :            :                         { "images-dir", required_argument, 0, 'D' },
      88                 :            :                         { "log-file", required_argument, 0, 'o' },
      89                 :            :                         { "namespaces", required_argument, 0, 'n' },
      90                 :            :                         { "root", required_argument, 0, 'r' },
      91                 :            :                         { "ext-unix-sk", no_argument, 0, 'x' },
      92                 :            :                         { "help", no_argument, 0, 'h' },
      93                 :            :                         { SK_EST_PARAM, no_argument, 0, 42 },
      94                 :            :                         { "close", required_argument, 0, 43 },
      95                 :            :                         { "log-pid", no_argument, 0, 44},
      96                 :            :                         { "version", no_argument, 0, 'V'},
      97                 :            :                         { "evasive-devices", no_argument, 0, 45},
      98                 :            :                         { "pidfile", required_argument, 0, 46},
      99                 :            :                         { "veth-pair", required_argument, 0, 47},
     100                 :            :                         { "action-script", required_argument, 0, 49},
     101                 :            :                         { LREMAP_PARAM, no_argument, 0, 41},
     102                 :            :                         { "shell-job", no_argument, 0, 'j'},
     103                 :            :                         { },
     104                 :            :                 };
     105                 :            : 
     106                 :       6155 :                 opt = getopt_long(argc, argv, short_opts, long_opts, &idx);
     107         [ +  + ]:       6155 :                 if (opt == -1)
     108                 :            :                         break;
     109                 :            : 
     110   [ -  +  +  -  :       5608 :                 switch (opt) {
          -  +  +  +  +  
          +  +  +  +  -  
          -  +  +  -  -  
                -  -  - ]
     111                 :            :                 case 's':
     112                 :          0 :                         opts.final_state = TASK_STOPPED;
     113                 :          0 :                         break;
     114                 :            :                 case 'x':
     115                 :        546 :                         opts.ext_unix_sk = true;
     116                 :        546 :                         break;
     117                 :            :                 case 't':
     118                 :       1092 :                         pid = atoi(optarg);
     119                 :        546 :                         break;
     120                 :            :                 case 'c':
     121                 :          0 :                         opts.show_pages_content = true;
     122                 :          0 :                         break;
     123                 :            :                 case 'f':
     124                 :          0 :                         opts.show_dump_file = optarg;
     125                 :          0 :                         break;
     126                 :            :                 case 'r':
     127                 :        228 :                         opts.root = optarg;
     128                 :        228 :                         break;
     129                 :            :                 case 'd':
     130                 :        380 :                         opts.restore_detach = true;
     131                 :        380 :                         break;
     132                 :            :                 case 'D':
     133         [ +  - ]:        546 :                         if (chdir(optarg)) {
     134                 :          0 :                                 pr_perror("Can't change directory to %s",
     135                 :            :                                                 optarg);
     136                 :            :                                 return -1;
     137                 :            :                         }
     138                 :            :                         break;
     139                 :            :                 case 'o':
     140                 :        546 :                         opts.output = strdup(optarg);
     141         [ +  - ]:        546 :                         if (log_init(optarg))
     142                 :            :                                 return -1;
     143                 :            :                         log_inited = 1;
     144                 :            :                         break;
     145                 :            :                 case 'n':
     146         [ +  - ]:       1164 :                         if (parse_ns_string(optarg))
     147                 :            :                                 return -1;
     148                 :            :                         break;
     149                 :            :                 case 'v':
     150         [ +  - ]:        546 :                         if (optind < argc) {
     151                 :        546 :                                 char *opt = argv[optind];
     152                 :            : 
     153         [ +  - ]:        546 :                                 if (isdigit(*opt)) {
     154                 :        546 :                                         log_level = -atoi(opt);
     155                 :        546 :                                         optind++;
     156                 :            :                                 } else {
     157         [ #  # ]:          0 :                                         if (log_level >= 0)
     158                 :          0 :                                                 log_level++;
     159                 :            :                                 }
     160                 :            :                         } else {
     161         [ #  # ]:          0 :                                 if (log_level >= 0)
     162                 :          0 :                                         log_level++;
     163                 :            :                         }
     164                 :            :                         break;
     165                 :            :                 case 41:
     166                 :        166 :                         pr_info("Will allow link remaps on FS\n");
     167                 :        166 :                         opts.link_remap_ok = true;
     168                 :        166 :                         break;
     169                 :            :                 case 42:
     170                 :        546 :                         pr_info("Will dump TCP connections\n");
     171                 :        546 :                         opts.tcp_established_ok = true;
     172                 :        546 :                         break;
     173                 :            :                 case 43: {
     174                 :            :                         int fd;
     175                 :            : 
     176                 :          0 :                         fd = atoi(optarg);
     177                 :          0 :                         pr_info("Closing fd %d\n", fd);
     178                 :          0 :                         close(fd);
     179                 :       5608 :                         break;
     180                 :            :                 }
     181                 :            :                 case 44:
     182                 :          0 :                         opts.log_file_per_pid = 1;
     183                 :          0 :                         break;
     184                 :            :                 case 45:
     185                 :        166 :                         opts.evasive_devices = true;
     186                 :        166 :                         break;
     187                 :            :                 case 46:
     188                 :        228 :                         opts.pidfile = optarg;
     189                 :        228 :                         break;
     190                 :            :                 case 47:
     191                 :            :                         {
     192                 :            :                                 struct veth_pair *n;
     193                 :            : 
     194         [ #  # ]:          0 :                                 n = xmalloc(sizeof(*n));
     195         [ #  # ]:          0 :                                 if (n == NULL)
     196                 :            :                                         return -1;
     197                 :          0 :                                 n->outside = strchr(optarg, '=');
     198         [ #  # ]:          0 :                                 if (n->outside == NULL) {
     199         [ #  # ]:          0 :                                         xfree(n);
     200                 :          0 :                                         pr_err("Invalid agument for --veth-pair\n");
     201                 :          0 :                                         goto usage;
     202                 :            :                                 }
     203                 :            : 
     204                 :          0 :                                 *n->outside++ = '\0';
     205                 :          0 :                                 n->inside = optarg;
     206                 :          0 :                                 list_add(&n->node, &opts.veth_pairs);
     207                 :            :                         }
     208                 :            :                         break;
     209                 :            :                 case 49:
     210                 :            :                         {
     211                 :            :                                 struct script *script;
     212                 :            : 
     213         [ #  # ]:          0 :                                 script = xmalloc(sizeof(struct script));
     214         [ #  # ]:          0 :                                 if (script == NULL)
     215                 :            :                                         return -1;
     216                 :            : 
     217                 :          0 :                                 script->path = optarg;
     218                 :          0 :                                 list_add(&script->node, &opts.scripts);
     219                 :            :                         }
     220                 :            :                         break;
     221                 :            :                 case 'j':
     222                 :          0 :                         opts.shell_job = true;
     223                 :          0 :                         break;
     224                 :            :                 case 'V':
     225                 :          0 :                         pr_msg("Version: %d.%d\n", CRIU_VERSION_MAJOR, CRIU_VERSION_MINOR);
     226                 :            :                         return 0;
     227                 :            :                 case 'h':
     228                 :            :                 default:
     229                 :            :                         goto usage;
     230                 :            :                 }
     231                 :            :         }
     232                 :            : 
     233         [ +  + ]:        547 :         if (log_level < 0)
     234                 :        546 :                 log_level = -log_level;
     235                 :        547 :         log_set_loglevel(log_level);
     236                 :            : 
     237         [ +  + ]:        547 :         if (!log_inited) {
     238                 :          1 :                 ret = log_init(NULL);
     239         [ +  - ]:          1 :                 if (ret)
     240                 :            :                         return ret;
     241                 :            :         }
     242                 :            : 
     243                 :        547 :         ret = open_image_dir();
     244         [ -  + ]:        547 :         if (ret < 0) {
     245                 :          0 :                 pr_perror("can't open currect directory");
     246                 :            :                 return -1;
     247                 :            :         }
     248                 :            : 
     249         [ +  - ]:        547 :         if (optind >= argc)
     250                 :            :                 goto usage;
     251                 :            : 
     252 [ +  + ][ +  + ]:        547 :         if (strcmp(argv[optind], "dump") &&
     253         [ +  - ]:          1 :             strcmp(argv[optind], "restore") &&
     254         [ -  + ]:          1 :             strcmp(argv[optind], "show") &&
     255         [ #  # ]:          0 :             strcmp(argv[optind], "check") &&
     256                 :          0 :             strcmp(argv[optind], "exec")) {
     257                 :          0 :                 pr_err("Unknown command %s\n", argv[optind]);
     258                 :          0 :                 goto usage;
     259                 :            :         }
     260                 :            : 
     261   [ +  +  -  +  :        547 :         switch (argv[optind][0]) {
                   -  - ]
     262                 :            :         case 'd':
     263         [ +  - ]:        166 :                 if (!pid)
     264                 :            :                         goto opt_pid_missing;
     265                 :        166 :                 ret = cr_dump_tasks(pid, &opts);
     266                 :        166 :                 break;
     267                 :            :         case 'r':
     268         [ +  - ]:        380 :                 if (!pid)
     269                 :            :                         goto opt_pid_missing;
     270                 :        380 :                 ret = cr_restore_tasks(pid, &opts);
     271                 :        166 :                 break;
     272                 :            :         case 's':
     273                 :          0 :                 ret = cr_show(&opts);
     274                 :          0 :                 break;
     275                 :            :         case 'c':
     276                 :          1 :                 ret = cr_check();
     277                 :          1 :                 break;
     278                 :            :         case 'e':
     279         [ #  # ]:          0 :                 if (!pid)
     280                 :            :                         goto opt_pid_missing;
     281                 :          0 :                 ret = cr_exec(pid, argv + optind + 1);
     282                 :        333 :                 break;
     283                 :            :         default:
     284                 :            :                 goto usage;
     285                 :            :                 break;
     286                 :            :         }
     287                 :            : 
     288                 :            :         return ret;
     289                 :            : 
     290                 :            : usage:
     291                 :          0 :         pr_msg("\nUsage:\n");
     292                 :          0 :         pr_msg("  %s dump -t pid [<options>]\n", argv[0]);
     293                 :          0 :         pr_msg("  %s restore -t pid [<options>]\n", argv[0]);
     294                 :          0 :         pr_msg("  %s show (-D dir)|(-f file) [<options>]\n", argv[0]);
     295                 :          0 :         pr_msg("  %s check\n", argv[0]);
     296                 :          0 :         pr_msg("  %s exec -t pid <syscall-string>\n", argv[0]);
     297                 :            : 
     298                 :          0 :         pr_msg("\nCommands:\n");
     299                 :          0 :         pr_msg("  dump           checkpoint a process/tree identified by pid\n");
     300                 :          0 :         pr_msg("  restore        restore a process/tree identified by pid\n");
     301                 :          0 :         pr_msg("  show           show dump file(s) contents\n");
     302                 :          0 :         pr_msg("  check          checks whether the kernel support is up-to-date\n");
     303                 :          0 :         pr_msg("  exec           execute a system call by other task\n");
     304                 :            : 
     305         [ #  # ]:          0 :         if (argc < 2) {
     306                 :          0 :                 pr_msg("\nTry -h|--help for more info\n");
     307                 :            :                 return -1;
     308                 :            :         }
     309                 :            : 
     310                 :          0 :         pr_msg("\nDump/Restore options:\n");
     311                 :            : 
     312                 :          0 :         pr_msg("\n* Generic:\n");
     313                 :          0 :         pr_msg("  -t|--tree             checkpoint/restore the whole process tree identified by pid\n");
     314                 :          0 :         pr_msg("  -d|--restore-detached detach after restore\n");
     315                 :          0 :         pr_msg("  -s|--leave-stopped    leave tasks in stopped state after checkpoint instead of killing them\n");
     316                 :          0 :         pr_msg("  -D|--images-dir       directory where to put images to\n");
     317                 :          0 :         pr_msg("     --pidfile [FILE]      write a pid of a root task in this file\n");
     318                 :            : 
     319                 :          0 :         pr_msg("\n* Special resources support:\n");
     320                 :          0 :         pr_msg("  -n|--namespaces       checkpoint/restore namespaces - values must be separated by comma\n");
     321                 :          0 :         pr_msg("                        supported: uts, ipc, mnt, pid, net\n");
     322                 :          0 :         pr_msg("  -x|--ext-unix-sk      allow external unix connections\n");
     323                 :          0 :         pr_msg("     --%s  checkpoint/restore established TCP connections\n", SK_EST_PARAM);
     324                 :          0 :         pr_msg("  -r|--root [PATH] change the root filesystem (when run in mount namespace)\n");
     325                 :          0 :         pr_msg("  --evasive-devices        use any path to a device file if the original one is inaccessible\n");
     326                 :          0 :         pr_msg("  --veth-pair [IN=OUT]     correspondence between outside and inside names of veth devices\n");
     327                 :          0 :         pr_msg("  --link-remap          allow to link unlinked files back when possible (modifies FS till restore)\n");
     328                 :          0 :         pr_msg("  --action-script [SCR]    add an external action script\n");
     329                 :          0 :         pr_msg("                   The environment variable CRTOOL_SCRIPT_ACTION contains one of the actions:\n");
     330                 :          0 :         pr_msg("                   * network-lock - lock network in a target network namespace\n");
     331                 :          0 :         pr_msg("                   * network-unlock - unlock network in a target network namespace\n");
     332                 :          0 :         pr_msg("  -j|--shell-job        allow to dump and restore shell jobs\n");
     333                 :            : 
     334                 :          0 :         pr_msg("\n* Logging:\n");
     335                 :          0 :         pr_msg("  -o|--log-file [NAME]  log file name (relative path is relative to --images-dir)\n");
     336                 :          0 :         pr_msg("     --log-pid             if the -o option is in effect, each restored processes is\n");
     337                 :          0 :         pr_msg("                   written to the [NAME].pid file\n");
     338                 :          0 :         pr_msg("  -v [num]              set logging level\n");
     339                 :          0 :         pr_msg("                          0 - messages regardless of log level\n");
     340                 :          0 :         pr_msg("                          1 - errors, when we are in trouble\n");
     341                 :          0 :         pr_msg("                          2 - warnings (default)\n");
     342                 :          0 :         pr_msg("                          3 - informative, everything is fine\n");
     343                 :          0 :         pr_msg("                          4 - debug only\n");
     344                 :          0 :         pr_msg("  -v             same as -v 1\n");
     345                 :          0 :         pr_msg("  -vv            same as -v 2\n");
     346                 :          0 :         pr_msg("  -vvv           same as -v 3\n");
     347                 :          0 :         pr_msg("  -vvvv          same as -v 4\n");
     348                 :            : 
     349                 :          0 :         pr_msg("\nShow options:\n");
     350                 :          0 :         pr_msg("  -f|--file             show contents of a checkpoint file\n");
     351                 :          0 :         pr_msg("  -D|--images-dir       directory where to get images from\n");
     352                 :          0 :         pr_msg("  -c|--contents         show contents of pages dumped in hexdump format\n");
     353                 :            : 
     354                 :          0 :         pr_msg("\nOther options:\n");
     355                 :          0 :         pr_msg("  -h|--help             show this text\n");
     356                 :          0 :         pr_msg("  -V|--version          show version\n");
     357                 :            : 
     358                 :            :         return -1;
     359                 :            : 
     360                 :            : opt_pid_missing:
     361                 :        333 :         pr_msg("No pid specified (-t option missing)\n");
     362                 :            :         return -1;
     363                 :            : }

Generated by: LCOV version 1.9