xref: /kvmtool/builtin-list.c (revision 84e1040433f2c88fcfe18fba1482e2a1708910cc)
1 #include <kvm/util.h>
2 #include <kvm/kvm-cmd.h>
3 #include <kvm/builtin-list.h>
4 #include <kvm/kvm.h>
5 #include <kvm/parse-options.h>
6 #include <kvm/kvm-ipc.h>
7 
8 #include <dirent.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <signal.h>
12 #include <fcntl.h>
13 
14 #define PROCESS_NAME "kvm"
15 
16 struct pid_cmd {
17 	u32 type;
18 	u32 len;
19 };
20 
21 static bool run;
22 static bool rootfs;
23 
24 static const char * const list_usage[] = {
25 	"kvm list",
26 	NULL
27 };
28 
29 static const struct option list_options[] = {
30 	OPT_GROUP("General options:"),
31 	OPT_BOOLEAN('i', "run", &run, "List running instances"),
32 	OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"),
33 	OPT_END()
34 };
35 
36 void kvm_list_help(void)
37 {
38 	usage_with_options(list_usage, list_options);
39 }
40 
41 static pid_t get_pid(int sock)
42 {
43 	struct pid_cmd cmd = {KVM_IPC_PID, 0};
44 	int r;
45 	pid_t pid;
46 
47 	r = write(sock, &cmd, sizeof(cmd));
48 	if (r < 0)
49 		return r;
50 
51 	r = read(sock, &pid, sizeof(pid));
52 	if (r < 0)
53 		return r;
54 
55 	return pid;
56 }
57 
58 static int print_guest(const char *name, int sock)
59 {
60 	char proc_name[PATH_MAX];
61 	char *comm = NULL;
62 	FILE *fd;
63 	pid_t pid = get_pid(sock);
64 
65 	sprintf(proc_name, "/proc/%d/stat", pid);
66 	fd = fopen(proc_name, "r");
67 	if (fd == NULL)
68 		goto cleanup;
69 	if (fscanf(fd, "%*u (%as)", &comm) == 0)
70 		goto cleanup;
71 	if (strncmp(comm, PROCESS_NAME, strlen(PROCESS_NAME)))
72 		goto cleanup;
73 
74 	printf("%5d %s\n", pid, name);
75 
76 	free(comm);
77 
78 	fclose(fd);
79 
80 	return 0;
81 
82 cleanup:
83 	if (fd)
84 		fclose(fd);
85 	if (comm)
86 		free(comm);
87 
88 	kvm__remove_socket(name);
89 	return 0;
90 }
91 
92 static int kvm_list_running_instances(void)
93 {
94 	return kvm__enumerate_instances(print_guest);
95 }
96 
97 static int kvm_list_rootfs(void)
98 {
99 	char name[PATH_MAX];
100 	DIR *dir;
101 	struct dirent *dirent;
102 
103 	snprintf(name, PATH_MAX, "%s", kvm__get_dir());
104 	dir = opendir(name);
105 	if (dir == NULL)
106 		return -1;
107 
108 	while ((dirent = readdir(dir))) {
109 		if (dirent->d_type == DT_DIR &&
110 			strcmp(dirent->d_name, ".") &&
111 			strcmp(dirent->d_name, ".."))
112 			printf("      %s (not running)\n", dirent->d_name);
113 	}
114 
115 	return 0;
116 }
117 
118 static void parse_setup_options(int argc, const char **argv)
119 {
120 	while (argc != 0) {
121 		argc = parse_options(argc, argv, list_options, list_usage,
122 				PARSE_OPT_STOP_AT_NON_OPTION);
123 		if (argc != 0)
124 			kvm_list_help();
125 	}
126 }
127 
128 int kvm_cmd_list(int argc, const char **argv, const char *prefix)
129 {
130 	int r;
131 
132 	parse_setup_options(argc, argv);
133 
134 	if (!run && !rootfs)
135 		run = rootfs = true;
136 
137 	printf("  PID GUEST\n");
138 
139 	if (run) {
140 		r = kvm_list_running_instances();
141 		if (r < 0)
142 			perror("Error listing instances");
143 	}
144 
145 	if (rootfs) {
146 		r = kvm_list_rootfs();
147 		if (r < 0)
148 			perror("Error listing rootfs");
149 	}
150 
151 	return 0;
152 }
153