xref: /kvmtool/builtin-list.c (revision 5bf27f057f78e79fe3bc08cec7cf7ad97980135c)
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 struct pid_cmd {
15 	u32 type;
16 	u32 len;
17 };
18 
19 struct vmstate_cmd {
20 	u32 type;
21 	u32 len;
22 };
23 
24 static bool run;
25 static bool rootfs;
26 
27 static const char * const list_usage[] = {
28 	"lkvm list",
29 	NULL
30 };
31 
32 static const struct option list_options[] = {
33 	OPT_GROUP("General options:"),
34 	OPT_BOOLEAN('i', "run", &run, "List running instances"),
35 	OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"),
36 	OPT_END()
37 };
38 
39 #define KVM_INSTANCE_RUNNING	"running"
40 #define KVM_INSTANCE_PAUSED	"paused"
41 #define KVM_INSTANCE_SHUTOFF	"shut off"
42 
43 void kvm_list_help(void)
44 {
45 	usage_with_options(list_usage, list_options);
46 }
47 
48 static pid_t get_pid(int sock)
49 {
50 	struct pid_cmd cmd = {KVM_IPC_PID, 0};
51 	int r;
52 	pid_t pid;
53 
54 	r = write(sock, &cmd, sizeof(cmd));
55 	if (r < 0)
56 		return r;
57 
58 	r = read(sock, &pid, sizeof(pid));
59 	if (r < 0)
60 		return r;
61 
62 	return pid;
63 }
64 
65 static int get_vmstate(int sock)
66 {
67 	struct vmstate_cmd cmd = {KVM_IPC_VMSTATE, 0};
68 	int r;
69 	int vmstate;
70 
71 	r = write(sock, &cmd, sizeof(cmd));
72 	if (r < 0)
73 		return r;
74 
75 	r = read(sock, &vmstate, sizeof(vmstate));
76 	if (r < 0)
77 		return r;
78 
79 	return vmstate;
80 
81 }
82 
83 static int print_guest(const char *name, int sock)
84 {
85 	char proc_name[PATH_MAX];
86 	char *comm = NULL;
87 	FILE *fd;
88 	pid_t pid;
89 	int vmstate;
90 
91 	pid = get_pid(sock);
92 	vmstate = get_vmstate(sock);
93 
94 	sprintf(proc_name, "/proc/%d/stat", pid);
95 	fd = fopen(proc_name, "r");
96 	if (fd == NULL)
97 		goto cleanup;
98 	if (fscanf(fd, "%*u (%as)", &comm) == 0)
99 		goto cleanup;
100 
101 	if (vmstate == KVM_VMSTATE_PAUSED)
102 		printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_PAUSED);
103 	else
104 		printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_RUNNING);
105 
106 	free(comm);
107 
108 	fclose(fd);
109 
110 	return 0;
111 
112 cleanup:
113 	if (fd)
114 		fclose(fd);
115 	if (comm)
116 		free(comm);
117 
118 	kvm__remove_socket(name);
119 	return 0;
120 }
121 
122 static int kvm_list_running_instances(void)
123 {
124 	return kvm__enumerate_instances(print_guest);
125 }
126 
127 static int kvm_list_rootfs(void)
128 {
129 	DIR *dir;
130 	struct dirent *dirent;
131 
132 	dir = opendir(kvm__get_dir());
133 	if (dir == NULL)
134 		return -1;
135 
136 	while ((dirent = readdir(dir))) {
137 		if (dirent->d_type == DT_DIR &&
138 			strcmp(dirent->d_name, ".") &&
139 			strcmp(dirent->d_name, ".."))
140 			printf("%5s %-20s %s\n", "", dirent->d_name, KVM_INSTANCE_SHUTOFF);
141 	}
142 
143 	return 0;
144 }
145 
146 static void parse_setup_options(int argc, const char **argv)
147 {
148 	while (argc != 0) {
149 		argc = parse_options(argc, argv, list_options, list_usage,
150 				PARSE_OPT_STOP_AT_NON_OPTION);
151 		if (argc != 0)
152 			kvm_list_help();
153 	}
154 }
155 
156 int kvm_cmd_list(int argc, const char **argv, const char *prefix)
157 {
158 	int r;
159 
160 	parse_setup_options(argc, argv);
161 
162 	if (!run && !rootfs)
163 		run = rootfs = true;
164 
165 	printf("%6s %-20s %s\n", "PID", "NAME", "STATE");
166 	printf("------------------------------------\n");
167 
168 	if (run) {
169 		r = kvm_list_running_instances();
170 		if (r < 0)
171 			perror("Error listing instances");
172 	}
173 
174 	if (rootfs) {
175 		r = kvm_list_rootfs();
176 		if (r < 0)
177 			perror("Error listing rootfs");
178 	}
179 
180 	return 0;
181 }
182