xref: /kvmtool/builtin-list.c (revision 78c684b105d60ce6b90fa16a4983460ae8f084e4)
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 #define KVM_INSTANCE_RUNNING	"running"
37 #define KVM_INSTANCE_SHUTOFF	"shut off"
38 
39 void kvm_list_help(void)
40 {
41 	usage_with_options(list_usage, list_options);
42 }
43 
44 static pid_t get_pid(int sock)
45 {
46 	struct pid_cmd cmd = {KVM_IPC_PID, 0};
47 	int r;
48 	pid_t pid;
49 
50 	r = write(sock, &cmd, sizeof(cmd));
51 	if (r < 0)
52 		return r;
53 
54 	r = read(sock, &pid, sizeof(pid));
55 	if (r < 0)
56 		return r;
57 
58 	return pid;
59 }
60 
61 static int print_guest(const char *name, int sock)
62 {
63 	char proc_name[PATH_MAX];
64 	char *comm = NULL;
65 	FILE *fd;
66 	pid_t pid = get_pid(sock);
67 
68 	sprintf(proc_name, "/proc/%d/stat", pid);
69 	fd = fopen(proc_name, "r");
70 	if (fd == NULL)
71 		goto cleanup;
72 	if (fscanf(fd, "%*u (%as)", &comm) == 0)
73 		goto cleanup;
74 	if (strncmp(comm, PROCESS_NAME, strlen(PROCESS_NAME)))
75 		goto cleanup;
76 
77 	printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_RUNNING);
78 
79 	free(comm);
80 
81 	fclose(fd);
82 
83 	return 0;
84 
85 cleanup:
86 	if (fd)
87 		fclose(fd);
88 	if (comm)
89 		free(comm);
90 
91 	kvm__remove_socket(name);
92 	return 0;
93 }
94 
95 static int kvm_list_running_instances(void)
96 {
97 	return kvm__enumerate_instances(print_guest);
98 }
99 
100 static int kvm_list_rootfs(void)
101 {
102 	char name[PATH_MAX];
103 	DIR *dir;
104 	struct dirent *dirent;
105 
106 	snprintf(name, PATH_MAX, "%s", kvm__get_dir());
107 	dir = opendir(name);
108 	if (dir == NULL)
109 		return -1;
110 
111 	while ((dirent = readdir(dir))) {
112 		if (dirent->d_type == DT_DIR &&
113 			strcmp(dirent->d_name, ".") &&
114 			strcmp(dirent->d_name, ".."))
115 			printf("%5s %-20s %s\n", "", dirent->d_name, KVM_INSTANCE_SHUTOFF);
116 	}
117 
118 	return 0;
119 }
120 
121 static void parse_setup_options(int argc, const char **argv)
122 {
123 	while (argc != 0) {
124 		argc = parse_options(argc, argv, list_options, list_usage,
125 				PARSE_OPT_STOP_AT_NON_OPTION);
126 		if (argc != 0)
127 			kvm_list_help();
128 	}
129 }
130 
131 int kvm_cmd_list(int argc, const char **argv, const char *prefix)
132 {
133 	int r;
134 
135 	parse_setup_options(argc, argv);
136 
137 	if (!run && !rootfs)
138 		run = rootfs = true;
139 
140 	printf("%6s %-20s %s\n", "PID", "NAME", "STATE");
141 	printf("------------------------------------\n");
142 
143 	if (run) {
144 		r = kvm_list_running_instances();
145 		if (r < 0)
146 			perror("Error listing instances");
147 	}
148 
149 	if (rootfs) {
150 		r = kvm_list_rootfs();
151 		if (r < 0)
152 			perror("Error listing rootfs");
153 	}
154 
155 	return 0;
156 }
157