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