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