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 "kvm 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