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