xref: /kvmtool/builtin-list.c (revision 4b1addaeed6f8c717b2b818e3f867829849d8e86)
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 	printf("  PID GUEST\n");
95 
96 	return kvm__enumerate_instances(print_guest);
97 }
98 
99 static int kvm_list_rootfs(void)
100 {
101 	char name[PATH_MAX];
102 	DIR *dir;
103 	struct dirent *dirent;
104 
105 	snprintf(name, PATH_MAX, "%s", kvm__get_dir());
106 	dir = opendir(name);
107 	if (dir == NULL)
108 		return -1;
109 
110 	printf("  ROOTFS\n");
111 
112 	while ((dirent = readdir(dir))) {
113 		if (dirent->d_type == DT_DIR &&
114 			strcmp(dirent->d_name, ".") &&
115 			strcmp(dirent->d_name, ".."))
116 			printf("%s\n", dirent->d_name);
117 	}
118 
119 	return 0;
120 }
121 
122 static void parse_setup_options(int argc, const char **argv)
123 {
124 	while (argc != 0) {
125 		argc = parse_options(argc, argv, list_options, list_usage,
126 				PARSE_OPT_STOP_AT_NON_OPTION);
127 		if (argc != 0)
128 			kvm_list_help();
129 	}
130 }
131 
132 int kvm_cmd_list(int argc, const char **argv, const char *prefix)
133 {
134 	int r;
135 
136 	parse_setup_options(argc, argv);
137 
138 	if (!run && !rootfs)
139 		kvm_list_help();
140 
141 	if (run) {
142 		r = kvm_list_running_instances();
143 		if (r < 0)
144 			perror("Error listing instances");
145 	}
146 
147 	if (rootfs) {
148 		r = kvm_list_rootfs();
149 		if (r < 0)
150 			perror("Error listing rootfs");
151 	}
152 
153 	return 0;
154 }
155