xref: /kvmtool/builtin-list.c (revision 4b1addaeed6f8c717b2b818e3f867829849d8e86)
19dba6721SSasha Levin #include <kvm/util.h>
29dba6721SSasha Levin #include <kvm/kvm-cmd.h>
32a24f96dSSasha Levin #include <kvm/builtin-list.h>
49dba6721SSasha Levin #include <kvm/kvm.h>
50725673aSSasha Levin #include <kvm/parse-options.h>
6*4b1addaeSSasha Levin #include <kvm/kvm-ipc.h>
79dba6721SSasha Levin 
8076e946eSSasha Levin #include <dirent.h>
99dba6721SSasha Levin #include <stdio.h>
109dba6721SSasha Levin #include <string.h>
119dba6721SSasha Levin #include <signal.h>
121b1577dcSSasha Levin #include <fcntl.h>
131b1577dcSSasha Levin 
141b1577dcSSasha Levin #define PROCESS_NAME "kvm"
159dba6721SSasha Levin 
16*4b1addaeSSasha Levin struct pid_cmd {
17*4b1addaeSSasha Levin 	u32 type;
18*4b1addaeSSasha Levin 	u32 len;
19*4b1addaeSSasha Levin };
20*4b1addaeSSasha Levin 
21076e946eSSasha Levin static bool run;
22076e946eSSasha Levin static bool rootfs;
23076e946eSSasha Levin 
240725673aSSasha Levin static const char * const list_usage[] = {
250725673aSSasha Levin 	"kvm list",
260725673aSSasha Levin 	NULL
270725673aSSasha Levin };
280725673aSSasha Levin 
290725673aSSasha Levin static const struct option list_options[] = {
30076e946eSSasha Levin 	OPT_GROUP("General options:"),
31076e946eSSasha Levin 	OPT_BOOLEAN('i', "run", &run, "List running instances"),
32076e946eSSasha Levin 	OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"),
330725673aSSasha Levin 	OPT_END()
340725673aSSasha Levin };
350725673aSSasha Levin 
360725673aSSasha Levin void kvm_list_help(void)
370725673aSSasha Levin {
380725673aSSasha Levin 	usage_with_options(list_usage, list_options);
390725673aSSasha Levin }
400725673aSSasha Levin 
41*4b1addaeSSasha Levin static pid_t get_pid(int sock)
42*4b1addaeSSasha Levin {
43*4b1addaeSSasha Levin 	struct pid_cmd cmd = {KVM_IPC_PID, 0};
44*4b1addaeSSasha Levin 	int r;
45*4b1addaeSSasha Levin 	pid_t pid;
46*4b1addaeSSasha Levin 
47*4b1addaeSSasha Levin 	r = write(sock, &cmd, sizeof(cmd));
48*4b1addaeSSasha Levin 	if (r < 0)
49*4b1addaeSSasha Levin 		return r;
50*4b1addaeSSasha Levin 
51*4b1addaeSSasha Levin 	r = read(sock, &pid, sizeof(pid));
52*4b1addaeSSasha Levin 	if (r < 0)
53*4b1addaeSSasha Levin 		return r;
54*4b1addaeSSasha Levin 
55*4b1addaeSSasha Levin 	return pid;
56*4b1addaeSSasha Levin }
57*4b1addaeSSasha Levin 
58*4b1addaeSSasha Levin static int print_guest(const char *name, int sock)
599dba6721SSasha Levin {
601b1577dcSSasha Levin 	char proc_name[PATH_MAX];
61ebc49f06SSasha Levin 	char *comm = NULL;
62ebc49f06SSasha Levin 	FILE *fd;
63*4b1addaeSSasha Levin 	pid_t pid = get_pid(sock);
641b1577dcSSasha Levin 
65ebc49f06SSasha Levin 	sprintf(proc_name, "/proc/%d/stat", pid);
66ebc49f06SSasha Levin 	fd = fopen(proc_name, "r");
67ebc49f06SSasha Levin 	if (fd == NULL)
681b1577dcSSasha Levin 		goto cleanup;
69ebc49f06SSasha Levin 	if (fscanf(fd, "%*u (%as)", &comm) == 0)
701b1577dcSSasha Levin 		goto cleanup;
711b1577dcSSasha Levin 	if (strncmp(comm, PROCESS_NAME, strlen(PROCESS_NAME)))
721b1577dcSSasha Levin 		goto cleanup;
731b1577dcSSasha Levin 
748a09361dSPekka Enberg 	printf("%5d %s\n", pid, name);
751b1577dcSSasha Levin 
76ebc49f06SSasha Levin 	free(comm);
77ebc49f06SSasha Levin 
78ebc49f06SSasha Levin 	fclose(fd);
791a0ef251SSasha Levin 
80886af5f2SLiming Wang 	return 0;
811b1577dcSSasha Levin 
821b1577dcSSasha Levin cleanup:
83ebc49f06SSasha Levin 	if (fd)
84ebc49f06SSasha Levin 		fclose(fd);
85ebc49f06SSasha Levin 	if (comm)
86ebc49f06SSasha Levin 		free(comm);
87ebc49f06SSasha Levin 
88*4b1addaeSSasha Levin 	kvm__remove_socket(name);
89886af5f2SLiming Wang 	return 0;
909dba6721SSasha Levin }
919dba6721SSasha Levin 
92076e946eSSasha Levin static int kvm_list_running_instances(void)
939dba6721SSasha Levin {
948a09361dSPekka Enberg 	printf("  PID GUEST\n");
958a09361dSPekka Enberg 
96886af5f2SLiming Wang 	return kvm__enumerate_instances(print_guest);
979dba6721SSasha Levin }
98076e946eSSasha Levin 
99076e946eSSasha Levin static int kvm_list_rootfs(void)
100076e946eSSasha Levin {
101076e946eSSasha Levin 	char name[PATH_MAX];
102076e946eSSasha Levin 	DIR *dir;
103076e946eSSasha Levin 	struct dirent *dirent;
104076e946eSSasha Levin 
1059667701cSPekka Enberg 	snprintf(name, PATH_MAX, "%s", kvm__get_dir());
106076e946eSSasha Levin 	dir = opendir(name);
107076e946eSSasha Levin 	if (dir == NULL)
108076e946eSSasha Levin 		return -1;
109076e946eSSasha Levin 
110076e946eSSasha Levin 	printf("  ROOTFS\n");
111076e946eSSasha Levin 
112076e946eSSasha Levin 	while ((dirent = readdir(dir))) {
113076e946eSSasha Levin 		if (dirent->d_type == DT_DIR &&
114076e946eSSasha Levin 			strcmp(dirent->d_name, ".") &&
115076e946eSSasha Levin 			strcmp(dirent->d_name, ".."))
116076e946eSSasha Levin 			printf("%s\n", dirent->d_name);
117076e946eSSasha Levin 	}
118076e946eSSasha Levin 
119076e946eSSasha Levin 	return 0;
120076e946eSSasha Levin }
121076e946eSSasha Levin 
122076e946eSSasha Levin static void parse_setup_options(int argc, const char **argv)
123076e946eSSasha Levin {
124076e946eSSasha Levin 	while (argc != 0) {
125076e946eSSasha Levin 		argc = parse_options(argc, argv, list_options, list_usage,
126076e946eSSasha Levin 				PARSE_OPT_STOP_AT_NON_OPTION);
127076e946eSSasha Levin 		if (argc != 0)
128076e946eSSasha Levin 			kvm_list_help();
129076e946eSSasha Levin 	}
130076e946eSSasha Levin }
131076e946eSSasha Levin 
132076e946eSSasha Levin int kvm_cmd_list(int argc, const char **argv, const char *prefix)
133076e946eSSasha Levin {
134076e946eSSasha Levin 	int r;
135076e946eSSasha Levin 
136076e946eSSasha Levin 	parse_setup_options(argc, argv);
137076e946eSSasha Levin 
138076e946eSSasha Levin 	if (!run && !rootfs)
139076e946eSSasha Levin 		kvm_list_help();
140076e946eSSasha Levin 
141076e946eSSasha Levin 	if (run) {
142076e946eSSasha Levin 		r = kvm_list_running_instances();
143076e946eSSasha Levin 		if (r < 0)
144076e946eSSasha Levin 			perror("Error listing instances");
145076e946eSSasha Levin 	}
146076e946eSSasha Levin 
147076e946eSSasha Levin 	if (rootfs) {
148076e946eSSasha Levin 		r = kvm_list_rootfs();
149076e946eSSasha Levin 		if (r < 0)
150076e946eSSasha Levin 			perror("Error listing rootfs");
151076e946eSSasha Levin 	}
152076e946eSSasha Levin 
153076e946eSSasha Levin 	return 0;
154076e946eSSasha Levin }
155