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> 69dba6721SSasha Levin 7*076e946eSSasha Levin #include <dirent.h> 89dba6721SSasha Levin #include <stdio.h> 99dba6721SSasha Levin #include <string.h> 109dba6721SSasha Levin #include <signal.h> 111b1577dcSSasha Levin #include <fcntl.h> 121b1577dcSSasha Levin 131b1577dcSSasha Levin #define PROCESS_NAME "kvm" 149dba6721SSasha Levin 15*076e946eSSasha Levin static bool run; 16*076e946eSSasha Levin static bool rootfs; 17*076e946eSSasha Levin 180725673aSSasha Levin static const char * const list_usage[] = { 190725673aSSasha Levin "kvm list", 200725673aSSasha Levin NULL 210725673aSSasha Levin }; 220725673aSSasha Levin 230725673aSSasha Levin static const struct option list_options[] = { 24*076e946eSSasha Levin OPT_GROUP("General options:"), 25*076e946eSSasha Levin OPT_BOOLEAN('i', "run", &run, "List running instances"), 26*076e946eSSasha Levin OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"), 270725673aSSasha Levin OPT_END() 280725673aSSasha Levin }; 290725673aSSasha Levin 300725673aSSasha Levin void kvm_list_help(void) 310725673aSSasha Levin { 320725673aSSasha Levin usage_with_options(list_usage, list_options); 330725673aSSasha Levin } 340725673aSSasha Levin 35886af5f2SLiming Wang static int print_guest(const char *name, int pid) 369dba6721SSasha Levin { 371b1577dcSSasha Levin char proc_name[PATH_MAX]; 38ebc49f06SSasha Levin char *comm = NULL; 39ebc49f06SSasha Levin FILE *fd; 401b1577dcSSasha Levin 41ebc49f06SSasha Levin sprintf(proc_name, "/proc/%d/stat", pid); 42ebc49f06SSasha Levin fd = fopen(proc_name, "r"); 43ebc49f06SSasha Levin if (fd == NULL) 441b1577dcSSasha Levin goto cleanup; 45ebc49f06SSasha Levin if (fscanf(fd, "%*u (%as)", &comm) == 0) 461b1577dcSSasha Levin goto cleanup; 471b1577dcSSasha Levin if (strncmp(comm, PROCESS_NAME, strlen(PROCESS_NAME))) 481b1577dcSSasha Levin goto cleanup; 491b1577dcSSasha Levin 508a09361dSPekka Enberg printf("%5d %s\n", pid, name); 511b1577dcSSasha Levin 52ebc49f06SSasha Levin free(comm); 53ebc49f06SSasha Levin 54ebc49f06SSasha Levin fclose(fd); 551a0ef251SSasha Levin 56886af5f2SLiming Wang return 0; 571b1577dcSSasha Levin 581b1577dcSSasha Levin cleanup: 59ebc49f06SSasha Levin if (fd) 60ebc49f06SSasha Levin fclose(fd); 61ebc49f06SSasha Levin if (comm) 62ebc49f06SSasha Levin free(comm); 63ebc49f06SSasha Levin 641b1577dcSSasha Levin kvm__remove_pidfile(name); 65886af5f2SLiming Wang return 0; 669dba6721SSasha Levin } 679dba6721SSasha Levin 68*076e946eSSasha Levin static int kvm_list_running_instances(void) 699dba6721SSasha Levin { 708a09361dSPekka Enberg printf(" PID GUEST\n"); 718a09361dSPekka Enberg 72886af5f2SLiming Wang return kvm__enumerate_instances(print_guest); 739dba6721SSasha Levin } 74*076e946eSSasha Levin 75*076e946eSSasha Levin static int kvm_list_rootfs(void) 76*076e946eSSasha Levin { 77*076e946eSSasha Levin char name[PATH_MAX]; 78*076e946eSSasha Levin DIR *dir; 79*076e946eSSasha Levin struct dirent *dirent; 80*076e946eSSasha Levin 81*076e946eSSasha Levin snprintf(name, PATH_MAX, "%s%s", HOME_DIR, KVM_PID_FILE_PATH); 82*076e946eSSasha Levin dir = opendir(name); 83*076e946eSSasha Levin if (dir == NULL) 84*076e946eSSasha Levin return -1; 85*076e946eSSasha Levin 86*076e946eSSasha Levin printf(" ROOTFS\n"); 87*076e946eSSasha Levin 88*076e946eSSasha Levin while ((dirent = readdir(dir))) { 89*076e946eSSasha Levin if (dirent->d_type == DT_DIR && 90*076e946eSSasha Levin strcmp(dirent->d_name, ".") && 91*076e946eSSasha Levin strcmp(dirent->d_name, "..")) 92*076e946eSSasha Levin printf("%s\n", dirent->d_name); 93*076e946eSSasha Levin } 94*076e946eSSasha Levin 95*076e946eSSasha Levin return 0; 96*076e946eSSasha Levin } 97*076e946eSSasha Levin 98*076e946eSSasha Levin static void parse_setup_options(int argc, const char **argv) 99*076e946eSSasha Levin { 100*076e946eSSasha Levin while (argc != 0) { 101*076e946eSSasha Levin argc = parse_options(argc, argv, list_options, list_usage, 102*076e946eSSasha Levin PARSE_OPT_STOP_AT_NON_OPTION); 103*076e946eSSasha Levin if (argc != 0) 104*076e946eSSasha Levin kvm_list_help(); 105*076e946eSSasha Levin } 106*076e946eSSasha Levin } 107*076e946eSSasha Levin 108*076e946eSSasha Levin int kvm_cmd_list(int argc, const char **argv, const char *prefix) 109*076e946eSSasha Levin { 110*076e946eSSasha Levin int r; 111*076e946eSSasha Levin 112*076e946eSSasha Levin parse_setup_options(argc, argv); 113*076e946eSSasha Levin 114*076e946eSSasha Levin if (!run && !rootfs) 115*076e946eSSasha Levin kvm_list_help(); 116*076e946eSSasha Levin 117*076e946eSSasha Levin if (run) { 118*076e946eSSasha Levin r = kvm_list_running_instances(); 119*076e946eSSasha Levin if (r < 0) 120*076e946eSSasha Levin perror("Error listing instances"); 121*076e946eSSasha Levin } 122*076e946eSSasha Levin 123*076e946eSSasha Levin if (rootfs) { 124*076e946eSSasha Levin r = kvm_list_rootfs(); 125*076e946eSSasha Levin if (r < 0) 126*076e946eSSasha Levin perror("Error listing rootfs"); 127*076e946eSSasha Levin } 128*076e946eSSasha Levin 129*076e946eSSasha Levin return 0; 130*076e946eSSasha Levin } 131