1 /*
2 * ProjectAcrn
3 * Acrnctl
4 *
5 * Copyright (C) 2018-2022 Intel Corporation.
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 *
10 * Author: Tao Yuhong <yuhong.tao@intel.com>
11 */
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <stdlib.h>
18 #include <sys/queue.h>
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #include <stdbool.h>
22 #include "acrn_mngr.h"
23 #include "acrnctl.h"
24 #include "ioc.h"
25
26 #define ACMD(CMD,FUNC,DESC, VALID_ARGS) \
27 {.cmd = CMD, .func = FUNC, .desc = DESC, .valid_args = VALID_ARGS}
28
29 /* vm life cycle cmd description */
30 #define LIST_DESC "List all the virtual machines added"
31 #define START_DESC "Start virtual machine VM_NAME"
32 #define STOP_DESC "Stop virtual machine VM_NAME, [--force/-f, force to stop VM]"
33 #define DEL_DESC "Delete virtual machine VM_NAME"
34 #define ADD_DESC "Add one virtual machine with SCRIPTS and OPTIONS"
35 #define RESET_DESC "Stop and then start virtual machine VM_NAME"
36 #define BLKRESCAN_DESC "Rescan virtio-blk device attached to a virtual machine"
37
38 #define VM_NAME (1)
39 #define CMD_ARGS (2)
40
41 #define STOP_TIMEOUT 30U
42
43 struct acrnctl_cmd {
44 const char *cmd;
45 const char desc[128]; /* Description of the cmd */
46 int (*func) (int argc, char *argv[]);
47 /* Callback function to check whether args is valid */
48 int (*valid_args) (struct acrnctl_cmd * cmd, int argc, char *argv[]);
49 };
50
51 /* There are acrnctl cmds */
52 /* command: list */
acrnctl_do_list(int argc,char * argv[])53 static int acrnctl_do_list(int argc, char *argv[])
54 {
55 return list_vm();
56 }
57
check_name(const char * name)58 static int check_name(const char *name)
59 {
60 int i = 0, j = 0;
61 char illegal[] = "!@#$%^&*, ";
62
63 /* Name should start with a letter */
64 if ((name[0] < 'a' || name[0] > 'z')
65 && (name[0] < 'A' || name[0] > 'Z')) {
66 printf("name not started with letter!\n");
67 return -1;
68 }
69
70 /* no illegal charactoer */
71 while (name[i]) {
72 j = 0;
73 while (illegal[j]) {
74 if (name[i] == illegal[j]) {
75 printf("vmname[%d] is '%c'!\n", i, name[i]);
76 return -1;
77 }
78 j++;
79 }
80 i++;
81 }
82
83 if (!strcmp(name, "help"))
84 return -1;
85 if (!strcmp(name, "nothing"))
86 return -1;
87
88 if (strnlen(name, MAX_VM_NAME_LEN) >= MAX_VM_NAME_LEN) {
89 printf("(%s) size exceed MAX_VM_NAME_LEN:%u\n", name, MAX_VM_NAME_LEN);
90 return -1;
91 }
92
93 return 0;
94 }
95
96 static const char *acrnctl_bin_path;
97 static int find_acrn_dm;
98 #define MAX_WORD 64
99
write_tmp_file(int fd,int n,char * word[])100 static int write_tmp_file(int fd, int n, char *word[])
101 {
102 int len, ret, i = 0;
103 char buf[PATH_LEN];
104
105 if (!n)
106 return 0;
107
108 len = strnlen(word[0], MAX_WORD);
109 if (len >= strlen("acrn-dm")) {
110 if (!strcmp(word[0] + len - strlen("acrn-dm"), "acrn-dm")) {
111 find_acrn_dm++;
112 memset(buf, 0, sizeof(buf));
113 if (snprintf(buf, sizeof(buf), "%s gentmpfile",
114 acrnctl_bin_path) >= sizeof(buf)) {
115 printf("ERROR: acrnctl bin path is truncated\n");
116 return -1;
117 }
118 ret = write(fd, buf, strnlen(buf, sizeof(buf)));
119 if (ret < 0)
120 return -1;
121 i++;
122 }
123 }
124
125 while (i < n) {
126 memset(buf, 0, sizeof(buf));
127 if (snprintf(buf, sizeof(buf), " %s", word[i]) >= sizeof(buf))
128 printf("WARN: buf is truncated\n");
129 i++;
130 ret = write(fd, buf, strnlen(buf, sizeof(buf)));
131 if (ret < 0)
132 return -1;
133 }
134 ret = write(fd, "\n", 1);
135 if (ret < 0)
136 return -1;
137 return 0;
138 }
139
140 /*
141 * get vmname from the string src, and src
142 * format is "acrnctl: [vmname]"
143 */
_get_vmname(const char * src,char * vmname,int max_len_vmname)144 static inline int _get_vmname(const char *src, char *vmname, int max_len_vmname)
145 {
146 const char *vmname_p = NULL;
147
148 if (!strncmp("acrnctl: ", src, strlen("acrnctl: "))) {
149 vmname_p = src + strlen("acrnctl: ");
150
151 memset(vmname, 0, max_len_vmname);
152 strncpy(vmname, vmname_p, max_len_vmname);
153 if(vmname[max_len_vmname - 1]) {
154 /* vmname is truncated */
155 printf("get vmname failed, vmname is truncated\n");
156 return -1;
157 }
158 } else {
159 /* the prefix of the string "src" isn't "acrnctl: " */
160 printf("can't found prefix 'acrnctl: '\n");
161 return -1;
162 }
163
164 return 0;
165 }
166
167 #define MAX_FILE_SIZE (4096 * 5)
168
169 #define TMP_FILE_SUFFIX ".acrnctl"
170
acrnctl_do_add(int argc,char * argv[])171 static int acrnctl_do_add(int argc, char *argv[])
172 {
173 struct vmmngr_struct *s;
174 int fd, fd_tmp, ret = 0;
175 char *buf;
176 char *word[MAX_WORD], *line;
177 char *word_p = NULL, *line_p = NULL;
178 int n_word;
179 char fname[PATH_LEN + sizeof(TMP_FILE_SUFFIX)];
180 char cmd[PATH_LEN];
181 char args[PATH_LEN];
182 int p, i, len_cmd_out = 0, c_flag = 0;
183 char cmd_out[PATH_LEN * 2];
184 char vmname[PATH_LEN];
185 size_t len = sizeof(cmd_out);
186
187 if (strnlen(argv[1], PATH_LEN) == PATH_LEN) {
188 printf("File name too long (maximum len %d)\n", PATH_LEN);
189 return -1;
190 }
191
192 memset(args, 0, sizeof(args));
193 p = 0;
194 for (i = 2; i < argc; i++) {
195 if (p >= sizeof(args) - 1) {
196 args[sizeof(args) - 1] = 0;
197 printf("Too many input options\n");
198 return -1;
199 }
200
201 /*
202 * If there's "-C" parameter in acrnctl add command
203 * check if the SoS support runC container at first, then
204 * strip "-C" and set the flag.
205 */
206 if (strncmp(argv[i], "-C", 2) == 0) {
207 if (access("/sbin/runc", F_OK) != 0) {
208 printf("runC command not supproted\n");
209 return -1;
210 }
211 c_flag = 1;
212 continue;
213 }
214
215 p += snprintf(&args[p], sizeof(args) - p, " %s", argv[i]);
216 }
217 args[p] = ' ';
218
219 fd = open(argv[1], O_RDONLY);
220 if (fd < 0) {
221 perror(argv[1]);
222 ret = -1;
223 goto open_read_file;
224 }
225
226 buf = calloc(1, MAX_FILE_SIZE);
227 if (!buf) {
228 perror("calloc for add vm");
229 ret = -1;
230 goto calloc_err;
231 }
232
233 ret = read(fd, buf, MAX_FILE_SIZE);
234 if (ret >= MAX_FILE_SIZE) {
235 printf("%s exceed MAX_FILE_SIZE:%d", argv[1], MAX_FILE_SIZE);
236 ret = -1;
237 goto file_exceed;
238 }
239
240 /* open tmp file for write */
241 memset(fname, 0, sizeof(fname));
242 if (snprintf(fname, sizeof(fname), "%s%s", argv[1], TMP_FILE_SUFFIX)
243 >= sizeof(fname)) {
244 printf("ERROR: file name is truncated\n");
245 ret = -1;
246 goto file_exceed;
247 }
248 fd_tmp = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0666);
249 if (fd_tmp < 0) {
250 perror(fname);
251 ret = -1;
252 goto open_tmp_file;
253 }
254
255 find_acrn_dm = 0;
256
257 /* Properly null-terminate buf */
258 buf[MAX_FILE_SIZE - 1] = '\0';
259
260 line = strtok_r(buf, "\n", &line_p);
261 while (line) {
262 word_p = NULL;
263 n_word = 0;
264 word[n_word] = strtok_r(line, " ", &word_p);
265 while ((n_word < (MAX_WORD-1)) && word[n_word]) {
266 n_word++;
267 word[n_word] = strtok_r(NULL, " ", &word_p);
268 }
269 if (write_tmp_file(fd_tmp, n_word, word)) {
270 ret = -1;
271 perror(fname);
272 goto write_tmpfile;
273 }
274 line = strtok_r(NULL, "\n", &line_p);
275 }
276
277 if (!find_acrn_dm) {
278 printf("No 'acrn-dm' found in %s, expecting 'acrn-dm' command to get vmname.\n", argv[1]);
279 ret = -1;
280 goto no_acrn_dm;
281 }
282
283 if (snprintf(cmd, sizeof(cmd), "mv %s %s.back", argv[1], argv[1])
284 >= sizeof(cmd)) {
285 printf("ERROR: cmd is truncated\n");
286 ret = -1;
287 goto get_vmname;
288 }
289 system(cmd);
290
291 if (snprintf(cmd, sizeof(cmd), "mv %s %s", fname, argv[1]) >= sizeof(cmd)) {
292 printf("ERROR: cmd is truncated\n");
293 ret = -1;
294 goto get_vmname;
295 }
296 system(cmd);
297
298 if (snprintf(cmd, sizeof(cmd), "bash %s%s > %s.result", argv[1],
299 args, argv[1]) >= sizeof(cmd)) {
300 printf("ERROR: cmd is truncated\n");
301 ret = -1 ;
302 goto get_vmname;
303 }
304 ret = shell_cmd(cmd, cmd_out, sizeof(cmd_out));
305 if (ret < 0)
306 goto get_vmname;
307
308 if (snprintf(cmd, sizeof(cmd), "grep -a \"acrnctl: \" %s.result",
309 argv[1]) >= sizeof(cmd)) {
310 printf("ERROR: cmd is truncated\n");
311 ret = -1;
312 goto get_vmname;
313 }
314 len_cmd_out = shell_cmd(cmd, cmd_out, sizeof(cmd_out));
315 if (len_cmd_out < 0) {
316 ret = len_cmd_out;
317 goto get_vmname;
318 }
319
320 if(cmd_out[len_cmd_out - 1] == '\n')
321 cmd_out[len_cmd_out - 1] = '\0';
322
323 ret = _get_vmname(cmd_out, vmname, sizeof(vmname));
324 if (ret < 0) {
325 /* failed to get vmname */
326 if (snprintf(cmd, sizeof(cmd), "cat %s.result", argv[1]) >= sizeof(cmd)) {
327 printf("ERROR: cmd is truncated\n");
328 goto get_vmname;
329 }
330 shell_cmd(cmd, cmd_out, sizeof(cmd_out));
331
332 /* Properly null-terminate cmd_out */
333 cmd_out[len - 1] = '\0';
334
335 printf("No executable acrn-dm found: %s, ,please make sure it can launch an User VM\n"
336 "result:\n%s\n", argv[1], cmd_out);
337 goto get_vmname;
338 }
339
340 ret = check_name(vmname);
341 if (ret) {
342 printf("\"%s\" is a bad name, please select another name\n",
343 vmname);
344 goto get_vmname;
345 }
346
347 s = vmmngr_find(vmname);
348 if (s) {
349 printf("%s(%s) already exist, can't add %s%s\n",
350 vmname, state_str[s->state], argv[1], args);
351 ret = -1;
352 goto vm_exist;
353 }
354
355 if (snprintf(cmd, sizeof(cmd), "cp %s.back %s/%s.sh", argv[1],
356 ACRN_CONF_PATH_ADD, vmname) >= sizeof(cmd)) {
357 printf("ERROR: cmd is truncated\n");
358 ret = -1;
359 goto vm_exist;
360 }
361 system(cmd);
362
363 /* If c_flag have been seted, add stripped "-C" to args file */
364 if (c_flag)
365 strncpy(args + p + 1, "-C", 2);
366 if (snprintf(cmd, sizeof(cmd), "echo %s >%s/%s.args", args,
367 ACRN_CONF_PATH_ADD, vmname) >= sizeof(cmd)) {
368 printf("ERROR: cmd is truncated\n");
369 ret = -1;
370 goto vm_exist;
371 }
372 system(cmd);
373 printf("%s added\n", vmname);
374
375 vm_exist:
376 get_vmname:
377 if (snprintf(cmd, sizeof(cmd), "rm -f %s.result", argv[1]) >= sizeof(cmd)) {
378 printf("WARN: cmd is truncated\n");
379 } else
380 system(cmd);
381
382 if (snprintf(cmd, sizeof(cmd), "mv %s %s", argv[1], fname) >= sizeof(cmd)) {
383 printf("ERROR: cmd is truncated\n");
384 ret = -1;
385 } else
386 system(cmd);
387
388 if (snprintf(cmd, sizeof(cmd), "mv %s.back %s", argv[1], argv[1]) >= sizeof(cmd)) {
389 printf("ERROR: cmd is truncated\n");
390 ret = -1;
391 } else
392 system(cmd);
393
394 no_acrn_dm:
395 if (snprintf(cmd, sizeof(cmd), "rm -f %s", fname) >= sizeof(cmd)) {
396 printf("WARN: cmd is truncated\n");
397 } else
398 system(cmd);
399 write_tmpfile:
400 close(fd_tmp);
401 open_tmp_file:
402 file_exceed:
403 free(buf);
404 calloc_err:
405 close(fd);
406 open_read_file:
407 return ret;
408 }
409
acrnctl_do_blkrescan(int argc,char * argv[])410 static int acrnctl_do_blkrescan(int argc, char *argv[])
411 {
412 struct vmmngr_struct *s;
413
414 s = vmmngr_find(argv[VM_NAME]);
415 if (!s) {
416 printf("can't find %s\n", argv[VM_NAME]);
417 return -1;
418 }
419 if (s->state != VM_STARTED) {
420 printf("%s is in %s state but should be in %s state for blockrescan\n",
421 argv[VM_NAME], state_str[s->state], state_str[VM_STARTED]);
422 return -1;
423 }
424
425 blkrescan_vm(argv[VM_NAME], argv[CMD_ARGS]);
426
427 return 0;
428 }
429
acrnctl_do_stop(int argc,char * argv[])430 static int acrnctl_do_stop(int argc, char *argv[])
431 {
432 struct vmmngr_struct *s;
433 int i, force = 0;
434 const char *vmname = NULL;
435
436 for (i = 1; i < argc; i++) {
437 if (strcmp(argv[i], "--force") && strcmp(argv[i], "-f")) {
438 if (vmname == NULL)
439 vmname = argv[i];
440 } else {
441 force = 1;
442 }
443 }
444
445 if (!vmname) {
446 printf("Please give a VM name\n");
447 return -1;
448 }
449
450 s = vmmngr_find(vmname);
451 if (!s) {
452 printf("can't find %s\n", vmname);
453 return -1;
454 }
455 if (s->state == VM_CREATED) {
456 printf("%s is already (%s)\n", vmname, state_str[s->state]);
457 return -1;
458 }
459
460 return stop_vm(vmname, force);
461
462 }
463
464 /* Function: Delete runC configuration */
del_runC(char * argv)465 static inline int del_runC(char *argv)
466 {
467 char cmd[PATH_LEN];
468 char cmd_out[PATH_LEN * 2];
469 char runc_path[PATH_LEN];
470
471 /* The configuration added by launch_uos script */
472 if (snprintf(runc_path, sizeof(runc_path), "%s/runc/%s",
473 ACRN_CONF_PATH_ADD, argv) >= sizeof(runc_path)) {
474 printf("ERROR: runC path %s is truncated\n", runc_path);
475 return -1;
476 }
477 if (access(runc_path, F_OK) != 0)
478 return 0;
479
480 /* Check if there is a container */
481 if (snprintf(cmd, sizeof(cmd), "runc list | grep %s",
482 argv) >= sizeof(cmd)) {
483 printf("ERROR: runc cmd: %s is truncated\n", cmd);
484 return -1;
485 }
486 shell_cmd(cmd, cmd_out, sizeof(cmd_out));
487 cmd_out[PATH_LEN * 2 - 1] = '\0';
488 if (strstr(cmd_out, argv) != NULL) {
489 /* If the container is still running stop it by runc pause */
490 if (strstr(cmd_out, "stopped") == NULL) {
491 printf("Pls stop the runC before del it !!\n");
492 return -1;
493 }
494 if (snprintf(cmd, sizeof(cmd), "runc delete %s",
495 argv) >= sizeof(cmd)) {
496 printf("ERROR: del container: %s trancated!", cmd);
497 return -1;
498 }
499 system(cmd);
500 if (snprintf(cmd, sizeof(cmd), "rm -f %s/runc/%s -rf",
501 ACRN_CONF_PATH_ADD, argv) >= sizeof(cmd)) {
502 printf("ERROR: delete cmd: %s trancated!\n", cmd);
503 return -1;
504 }
505 system(cmd);
506 }
507
508 return 0;
509 }
510
511 /* command: delete */
acrnctl_do_del(int argc,char * argv[])512 static int acrnctl_do_del(int argc, char *argv[])
513 {
514 struct vmmngr_struct *s;
515 char cmd[PATH_LEN];
516
517 s = vmmngr_find(argv[1]);
518 if (!s) {
519 printf("can't find %s\n", argv[1]);
520 return -1;
521 }
522 if (s->state != VM_CREATED) {
523 printf("can't delete %s(%s)\n", argv[1], state_str[s->state]);
524 return -1;
525 }
526 if (snprintf(cmd, sizeof(cmd), "rm -f %s/%s.sh", ACRN_CONF_PATH_ADD, argv[1]) >= sizeof(cmd)) {
527 printf("WARN: cmd is truncated\n");
528 return -1;
529 }
530 system(cmd);
531 if (snprintf(cmd, sizeof(cmd), "rm -f %s/%s.args", ACRN_CONF_PATH_ADD, argv[1]) >= sizeof(cmd)) {
532 printf("WARN: cmd is truncated\n");
533 return -1;
534 }
535 system(cmd);
536 if (del_runC(argv[1]) < 0) {
537 printf("ERROR: del runC failed!\n");
538 return -1;
539 }
540
541 return 0;
542 }
543
acrnctl_do_start(int argc,char * argv[])544 static int acrnctl_do_start(int argc, char *argv[])
545 {
546 struct vmmngr_struct *s;
547
548 s = vmmngr_find(argv[1]);
549 if (!s) {
550 printf("can't find %s\n", argv[1]);
551 return -1;
552 }
553
554 if (s->state != VM_CREATED) {
555 printf("can't start %s(%s)\n", argv[1], state_str[s->state]);
556 return -1;
557 }
558
559 return start_vm(argv[1]);
560
561 }
562
wait_vm_stop(const char * vmname,unsigned int timeout)563 static int wait_vm_stop(const char * vmname, unsigned int timeout)
564 {
565 unsigned long t = timeout;
566 struct vmmngr_struct *s;
567
568 do {
569 /* list and update the vm status */
570 vmmngr_update();
571
572 s = vmmngr_find(vmname);
573 if (s == NULL) {
574 printf("%s: vm %s not found\n", __func__, vmname);
575 return -1;
576 } else {
577 if (s->state == VM_CREATED) {
578 sleep(2);
579 return 0;
580 }
581 }
582
583 sleep(1);
584 } while (t--);
585
586 return -1;
587 }
588
acrnctl_do_reset(int argc,char * argv[])589 static int acrnctl_do_reset(int argc, char *argv[])
590 {
591 struct vmmngr_struct *s;
592 int ret = -1;
593
594 s = vmmngr_find(argv[1]);
595 if (!s) {
596 printf("Can't find vm %s\n", argv[1]);
597 return ret;
598 }
599
600 switch(s->state) {
601 case VM_STARTED:
602 case VM_SUSPENDED:
603 ret = stop_vm(argv[1], 0);
604 if (ret != 0) {
605 break;
606 }
607 if (wait_vm_stop(argv[1], STOP_TIMEOUT)) {
608 printf("Failed to stop %s in %u sec, reset failed\n", argv[1], STOP_TIMEOUT);
609 break;
610 }
611 ret = start_vm(argv[1]);
612 break;
613 default:
614 printf("%s current state: %s, can't reset\n", argv[1], state_str[s->state]);
615 }
616 return ret;
617 }
618
619 /* Default args validation function */
df_valid_args(struct acrnctl_cmd * cmd,int argc,char * argv[])620 int df_valid_args(struct acrnctl_cmd *cmd, int argc, char *argv[])
621 {
622 char df_opt[32] = "VM_NAME VM_NAME ...";
623
624 if (argc < 2 || !strcmp(argv[1], "help")) {
625 printf("acrnctl %s %s\n", cmd->cmd, df_opt);
626 return -1;
627 }
628
629 return 0;
630 }
631
valid_blkrescan_args(struct acrnctl_cmd * cmd,int argc,char * argv[])632 static int valid_blkrescan_args(struct acrnctl_cmd *cmd, int argc, char *argv[])
633 {
634 char df_opt[] = "VM_NAME slot,newpath";
635
636 if (argc != 3 || !strcmp(argv[1], "help")) {
637 printf("acrnctl %s %s\n", cmd->cmd, df_opt);
638 return -1;
639 }
640
641 return 0;
642 }
643
valid_add_args(struct acrnctl_cmd * cmd,int argc,char * argv[])644 static int valid_add_args(struct acrnctl_cmd *cmd, int argc, char *argv[])
645 {
646 char df_opt[32] = "launch_scripts options";
647
648 if (argc < 2 || !strcmp(argv[1], "help")) {
649 printf("acrnctl %s %s\n", cmd->cmd, df_opt);
650 return -1;
651 }
652
653 return 0;
654 }
655
valid_start_args(struct acrnctl_cmd * cmd,int argc,char * argv[])656 static int valid_start_args(struct acrnctl_cmd *cmd, int argc, char *argv[])
657 {
658 char df_opt[16] = "VM_NAME";
659
660 if (argc != 2 || !strcmp(argv[1], "help")) {
661 printf("acrnctl %s %s\n", cmd->cmd, df_opt);
662 return -1;
663 }
664
665 return 0;
666 }
667
valid_list_args(struct acrnctl_cmd * cmd,int argc,char * argv[])668 static int valid_list_args(struct acrnctl_cmd *cmd, int argc, char *argv[])
669 {
670 if (argc != 1) {
671 printf("acrnctl %s\n", cmd->cmd);
672 return -1;
673 }
674
675 return 0;
676 }
677
678 struct acrnctl_cmd acmds[] = {
679 ACMD("list", acrnctl_do_list, LIST_DESC, valid_list_args),
680 ACMD("start", acrnctl_do_start, START_DESC, valid_start_args),
681 ACMD("stop", acrnctl_do_stop, STOP_DESC, df_valid_args),
682 ACMD("del", acrnctl_do_del, DEL_DESC, df_valid_args),
683 ACMD("add", acrnctl_do_add, ADD_DESC, valid_add_args),
684 ACMD("reset", acrnctl_do_reset, RESET_DESC, df_valid_args),
685 ACMD("blkrescan", acrnctl_do_blkrescan, BLKRESCAN_DESC, valid_blkrescan_args),
686 };
687
688 #define NCMD (sizeof(acmds)/sizeof(struct acrnctl_cmd))
689
usage(void)690 static void usage(void)
691 {
692 int i;
693
694 printf("\nUsage: acrnctl SUB-CMD "
695 "{ VM_NAME | SCRIPTS OPTIONS | help }\n\n");
696 for (i = 0; i < NCMD; i++)
697 printf("\t%-12s%s\n", acmds[i].cmd, acmds[i].desc);
698 }
699
main(int argc,char * argv[])700 int main(int argc, char *argv[])
701 {
702 int i, err;
703 char cmd[PATH_LEN];
704
705 if (argc == 1 || !strcmp(argv[1], "help")) {
706 usage();
707 return 0;
708 }
709
710 if (getuid() != 0) {
711 printf("Please run acrnctl with root privileges. Exiting.\n");
712 return -1;
713 }
714
715 acrnctl_bin_path = argv[0];
716
717 /* Create the acrnctl conf folder if it does not exist yet */
718 if (snprintf(cmd, sizeof(cmd), "mkdir -p %s", ACRN_CONF_PATH_ADD)
719 >= sizeof(cmd)) {
720 printf("ERROR: cmd is truncated\n");
721 return -1;
722 }
723 system(cmd);
724
725 /* first check acrnctl reserved operations */
726 if (!strcmp(argv[1], "gentmpfile")) {
727 printf("\nacrnctl: %s\n", argv[argc - 1]);
728 return 0;
729 }
730
731 for (i = 0; i < NCMD; i++)
732 if (!strcmp(argv[1], acmds[i].cmd)) {
733 if (acmds[i].valid_args(&acmds[i], argc - 1, &argv[1])) {
734 return -1;
735 } else {
736 vmmngr_update();
737 err = acmds[i].func(argc - 1, &argv[1]);
738 return err;
739 }
740 }
741
742 /* Reach here means unsupported command */
743 printf("Unknown command: %s\n", argv[1]);
744 usage();
745
746 return -1;
747 }
748