1 /* 2 * QEMU Guest Agent POSIX-specific command implementations 3 * 4 * Copyright IBM Corp. 2011 5 * 6 * Authors: 7 * Michael Roth <mdroth@linux.vnet.ibm.com> 8 * Michal Privoznik <mprivozn@redhat.com> 9 * 10 * This work is licensed under the terms of the GNU GPL, version 2 or later. 11 * See the COPYING file in the top-level directory. 12 */ 13 14 #include "qemu/osdep.h" 15 #include <sys/ioctl.h> 16 #include <sys/utsname.h> 17 #include <sys/wait.h> 18 #include <dirent.h> 19 #include "guest-agent-core.h" 20 #include "qga-qapi-commands.h" 21 #include "qapi/error.h" 22 #include "qapi/qmp/qerror.h" 23 #include "qemu/queue.h" 24 #include "qemu/host-utils.h" 25 #include "qemu/sockets.h" 26 #include "qemu/base64.h" 27 #include "qemu/cutils.h" 28 #include "commands-common.h" 29 #include "block/nvme.h" 30 #include "cutils.h" 31 32 #ifdef HAVE_UTMPX 33 #include <utmpx.h> 34 #endif 35 36 #if defined(__linux__) 37 #include <mntent.h> 38 #include <linux/fs.h> 39 #include <sys/statvfs.h> 40 #include <linux/nvme_ioctl.h> 41 42 #ifdef CONFIG_LIBUDEV 43 #include <libudev.h> 44 #endif 45 46 #ifdef FIFREEZE 47 #define CONFIG_FSFREEZE 48 #endif 49 #ifdef FITRIM 50 #define CONFIG_FSTRIM 51 #endif 52 #endif 53 54 #ifdef HAVE_GETIFADDRS 55 #include <arpa/inet.h> 56 #include <sys/socket.h> 57 #include <net/if.h> 58 #include <sys/types.h> 59 #include <ifaddrs.h> 60 #ifdef CONFIG_SOLARIS 61 #include <sys/sockio.h> 62 #endif 63 #endif 64 65 static void ga_wait_child(pid_t pid, int *status, Error **errp) 66 { 67 pid_t rpid; 68 69 *status = 0; 70 71 do { 72 rpid = waitpid(pid, status, 0); 73 } while (rpid == -1 && errno == EINTR); 74 75 if (rpid == -1) { 76 error_setg_errno(errp, errno, "failed to wait for child (pid: %d)", 77 pid); 78 return; 79 } 80 81 g_assert(rpid == pid); 82 } 83 84 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp) 85 { 86 const char *shutdown_flag; 87 Error *local_err = NULL; 88 pid_t pid; 89 int status; 90 91 #ifdef CONFIG_SOLARIS 92 const char *powerdown_flag = "-i5"; 93 const char *halt_flag = "-i0"; 94 const char *reboot_flag = "-i6"; 95 #else 96 const char *powerdown_flag = "-P"; 97 const char *halt_flag = "-H"; 98 const char *reboot_flag = "-r"; 99 #endif 100 101 slog("guest-shutdown called, mode: %s", mode); 102 if (!has_mode || strcmp(mode, "powerdown") == 0) { 103 shutdown_flag = powerdown_flag; 104 } else if (strcmp(mode, "halt") == 0) { 105 shutdown_flag = halt_flag; 106 } else if (strcmp(mode, "reboot") == 0) { 107 shutdown_flag = reboot_flag; 108 } else { 109 error_setg(errp, 110 "mode is invalid (valid values are: halt|powerdown|reboot"); 111 return; 112 } 113 114 pid = fork(); 115 if (pid == 0) { 116 /* child, start the shutdown */ 117 setsid(); 118 reopen_fd_to_null(0); 119 reopen_fd_to_null(1); 120 reopen_fd_to_null(2); 121 122 #ifdef CONFIG_SOLARIS 123 execl("/sbin/shutdown", "shutdown", shutdown_flag, "-g0", "-y", 124 "hypervisor initiated shutdown", (char *)NULL); 125 #else 126 execl("/sbin/shutdown", "shutdown", "-h", shutdown_flag, "+0", 127 "hypervisor initiated shutdown", (char *)NULL); 128 #endif 129 _exit(EXIT_FAILURE); 130 } else if (pid < 0) { 131 error_setg_errno(errp, errno, "failed to create child process"); 132 return; 133 } 134 135 ga_wait_child(pid, &status, &local_err); 136 if (local_err) { 137 error_propagate(errp, local_err); 138 return; 139 } 140 141 if (!WIFEXITED(status)) { 142 error_setg(errp, "child process has terminated abnormally"); 143 return; 144 } 145 146 if (WEXITSTATUS(status)) { 147 error_setg(errp, "child process has failed to shutdown"); 148 return; 149 } 150 151 /* succeeded */ 152 } 153 154 void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp) 155 { 156 int ret; 157 int status; 158 pid_t pid; 159 Error *local_err = NULL; 160 struct timeval tv; 161 static const char hwclock_path[] = "/sbin/hwclock"; 162 static int hwclock_available = -1; 163 164 if (hwclock_available < 0) { 165 hwclock_available = (access(hwclock_path, X_OK) == 0); 166 } 167 168 if (!hwclock_available) { 169 error_setg(errp, QERR_UNSUPPORTED); 170 return; 171 } 172 173 /* If user has passed a time, validate and set it. */ 174 if (has_time) { 175 GDate date = { 0, }; 176 177 /* year-2038 will overflow in case time_t is 32bit */ 178 if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) { 179 error_setg(errp, "Time %" PRId64 " is too large", time_ns); 180 return; 181 } 182 183 tv.tv_sec = time_ns / 1000000000; 184 tv.tv_usec = (time_ns % 1000000000) / 1000; 185 g_date_set_time_t(&date, tv.tv_sec); 186 if (date.year < 1970 || date.year >= 2070) { 187 error_setg_errno(errp, errno, "Invalid time"); 188 return; 189 } 190 191 ret = settimeofday(&tv, NULL); 192 if (ret < 0) { 193 error_setg_errno(errp, errno, "Failed to set time to guest"); 194 return; 195 } 196 } 197 198 /* Now, if user has passed a time to set and the system time is set, we 199 * just need to synchronize the hardware clock. However, if no time was 200 * passed, user is requesting the opposite: set the system time from the 201 * hardware clock (RTC). */ 202 pid = fork(); 203 if (pid == 0) { 204 setsid(); 205 reopen_fd_to_null(0); 206 reopen_fd_to_null(1); 207 reopen_fd_to_null(2); 208 209 /* Use '/sbin/hwclock -w' to set RTC from the system time, 210 * or '/sbin/hwclock -s' to set the system time from RTC. */ 211 execl(hwclock_path, "hwclock", has_time ? "-w" : "-s", NULL); 212 _exit(EXIT_FAILURE); 213 } else if (pid < 0) { 214 error_setg_errno(errp, errno, "failed to create child process"); 215 return; 216 } 217 218 ga_wait_child(pid, &status, &local_err); 219 if (local_err) { 220 error_propagate(errp, local_err); 221 return; 222 } 223 224 if (!WIFEXITED(status)) { 225 error_setg(errp, "child process has terminated abnormally"); 226 return; 227 } 228 229 if (WEXITSTATUS(status)) { 230 error_setg(errp, "hwclock failed to set hardware clock to system time"); 231 return; 232 } 233 } 234 235 typedef enum { 236 RW_STATE_NEW, 237 RW_STATE_READING, 238 RW_STATE_WRITING, 239 } RwState; 240 241 struct GuestFileHandle { 242 uint64_t id; 243 FILE *fh; 244 RwState state; 245 QTAILQ_ENTRY(GuestFileHandle) next; 246 }; 247 248 static struct { 249 QTAILQ_HEAD(, GuestFileHandle) filehandles; 250 } guest_file_state = { 251 .filehandles = QTAILQ_HEAD_INITIALIZER(guest_file_state.filehandles), 252 }; 253 254 static int64_t guest_file_handle_add(FILE *fh, Error **errp) 255 { 256 GuestFileHandle *gfh; 257 int64_t handle; 258 259 handle = ga_get_fd_handle(ga_state, errp); 260 if (handle < 0) { 261 return -1; 262 } 263 264 gfh = g_new0(GuestFileHandle, 1); 265 gfh->id = handle; 266 gfh->fh = fh; 267 QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next); 268 269 return handle; 270 } 271 272 GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp) 273 { 274 GuestFileHandle *gfh; 275 276 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next) 277 { 278 if (gfh->id == id) { 279 return gfh; 280 } 281 } 282 283 error_setg(errp, "handle '%" PRId64 "' has not been found", id); 284 return NULL; 285 } 286 287 typedef const char * const ccpc; 288 289 #ifndef O_BINARY 290 #define O_BINARY 0 291 #endif 292 293 /* http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html */ 294 static const struct { 295 ccpc *forms; 296 int oflag_base; 297 } guest_file_open_modes[] = { 298 { (ccpc[]){ "r", NULL }, O_RDONLY }, 299 { (ccpc[]){ "rb", NULL }, O_RDONLY | O_BINARY }, 300 { (ccpc[]){ "w", NULL }, O_WRONLY | O_CREAT | O_TRUNC }, 301 { (ccpc[]){ "wb", NULL }, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY }, 302 { (ccpc[]){ "a", NULL }, O_WRONLY | O_CREAT | O_APPEND }, 303 { (ccpc[]){ "ab", NULL }, O_WRONLY | O_CREAT | O_APPEND | O_BINARY }, 304 { (ccpc[]){ "r+", NULL }, O_RDWR }, 305 { (ccpc[]){ "rb+", "r+b", NULL }, O_RDWR | O_BINARY }, 306 { (ccpc[]){ "w+", NULL }, O_RDWR | O_CREAT | O_TRUNC }, 307 { (ccpc[]){ "wb+", "w+b", NULL }, O_RDWR | O_CREAT | O_TRUNC | O_BINARY }, 308 { (ccpc[]){ "a+", NULL }, O_RDWR | O_CREAT | O_APPEND }, 309 { (ccpc[]){ "ab+", "a+b", NULL }, O_RDWR | O_CREAT | O_APPEND | O_BINARY } 310 }; 311 312 static int 313 find_open_flag(const char *mode_str, Error **errp) 314 { 315 unsigned mode; 316 317 for (mode = 0; mode < ARRAY_SIZE(guest_file_open_modes); ++mode) { 318 ccpc *form; 319 320 form = guest_file_open_modes[mode].forms; 321 while (*form != NULL && strcmp(*form, mode_str) != 0) { 322 ++form; 323 } 324 if (*form != NULL) { 325 break; 326 } 327 } 328 329 if (mode == ARRAY_SIZE(guest_file_open_modes)) { 330 error_setg(errp, "invalid file open mode '%s'", mode_str); 331 return -1; 332 } 333 return guest_file_open_modes[mode].oflag_base | O_NOCTTY | O_NONBLOCK; 334 } 335 336 #define DEFAULT_NEW_FILE_MODE (S_IRUSR | S_IWUSR | \ 337 S_IRGRP | S_IWGRP | \ 338 S_IROTH | S_IWOTH) 339 340 static FILE * 341 safe_open_or_create(const char *path, const char *mode, Error **errp) 342 { 343 int oflag; 344 int fd = -1; 345 FILE *f = NULL; 346 347 oflag = find_open_flag(mode, errp); 348 if (oflag < 0) { 349 goto end; 350 } 351 352 /* If the caller wants / allows creation of a new file, we implement it 353 * with a two step process: open() + (open() / fchmod()). 354 * 355 * First we insist on creating the file exclusively as a new file. If 356 * that succeeds, we're free to set any file-mode bits on it. (The 357 * motivation is that we want to set those file-mode bits independently 358 * of the current umask.) 359 * 360 * If the exclusive creation fails because the file already exists 361 * (EEXIST is not possible for any other reason), we just attempt to 362 * open the file, but in this case we won't be allowed to change the 363 * file-mode bits on the preexistent file. 364 * 365 * The pathname should never disappear between the two open()s in 366 * practice. If it happens, then someone very likely tried to race us. 367 * In this case just go ahead and report the ENOENT from the second 368 * open() to the caller. 369 * 370 * If the caller wants to open a preexistent file, then the first 371 * open() is decisive and its third argument is ignored, and the second 372 * open() and the fchmod() are never called. 373 */ 374 fd = qga_open_cloexec(path, oflag | ((oflag & O_CREAT) ? O_EXCL : 0), 0); 375 if (fd == -1 && errno == EEXIST) { 376 oflag &= ~(unsigned)O_CREAT; 377 fd = qga_open_cloexec(path, oflag, 0); 378 } 379 if (fd == -1) { 380 error_setg_errno(errp, errno, 381 "failed to open file '%s' (mode: '%s')", 382 path, mode); 383 goto end; 384 } 385 386 if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) { 387 error_setg_errno(errp, errno, "failed to set permission " 388 "0%03o on new file '%s' (mode: '%s')", 389 (unsigned)DEFAULT_NEW_FILE_MODE, path, mode); 390 goto end; 391 } 392 393 f = fdopen(fd, mode); 394 if (f == NULL) { 395 error_setg_errno(errp, errno, "failed to associate stdio stream with " 396 "file descriptor %d, file '%s' (mode: '%s')", 397 fd, path, mode); 398 } 399 400 end: 401 if (f == NULL && fd != -1) { 402 close(fd); 403 if (oflag & O_CREAT) { 404 unlink(path); 405 } 406 } 407 return f; 408 } 409 410 int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, 411 Error **errp) 412 { 413 FILE *fh; 414 Error *local_err = NULL; 415 int64_t handle; 416 417 if (!has_mode) { 418 mode = "r"; 419 } 420 slog("guest-file-open called, filepath: %s, mode: %s", path, mode); 421 fh = safe_open_or_create(path, mode, &local_err); 422 if (local_err != NULL) { 423 error_propagate(errp, local_err); 424 return -1; 425 } 426 427 /* set fd non-blocking to avoid common use cases (like reading from a 428 * named pipe) from hanging the agent 429 */ 430 if (!g_unix_set_fd_nonblocking(fileno(fh), true, NULL)) { 431 fclose(fh); 432 error_setg_errno(errp, errno, "Failed to set FD nonblocking"); 433 return -1; 434 } 435 436 handle = guest_file_handle_add(fh, errp); 437 if (handle < 0) { 438 fclose(fh); 439 return -1; 440 } 441 442 slog("guest-file-open, handle: %" PRId64, handle); 443 return handle; 444 } 445 446 void qmp_guest_file_close(int64_t handle, Error **errp) 447 { 448 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 449 int ret; 450 451 slog("guest-file-close called, handle: %" PRId64, handle); 452 if (!gfh) { 453 return; 454 } 455 456 ret = fclose(gfh->fh); 457 if (ret == EOF) { 458 error_setg_errno(errp, errno, "failed to close handle"); 459 return; 460 } 461 462 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next); 463 g_free(gfh); 464 } 465 466 GuestFileRead *guest_file_read_unsafe(GuestFileHandle *gfh, 467 int64_t count, Error **errp) 468 { 469 GuestFileRead *read_data = NULL; 470 guchar *buf; 471 FILE *fh = gfh->fh; 472 size_t read_count; 473 474 /* explicitly flush when switching from writing to reading */ 475 if (gfh->state == RW_STATE_WRITING) { 476 int ret = fflush(fh); 477 if (ret == EOF) { 478 error_setg_errno(errp, errno, "failed to flush file"); 479 return NULL; 480 } 481 gfh->state = RW_STATE_NEW; 482 } 483 484 buf = g_malloc0(count + 1); 485 read_count = fread(buf, 1, count, fh); 486 if (ferror(fh)) { 487 error_setg_errno(errp, errno, "failed to read file"); 488 } else { 489 buf[read_count] = 0; 490 read_data = g_new0(GuestFileRead, 1); 491 read_data->count = read_count; 492 read_data->eof = feof(fh); 493 if (read_count) { 494 read_data->buf_b64 = g_base64_encode(buf, read_count); 495 } 496 gfh->state = RW_STATE_READING; 497 } 498 g_free(buf); 499 clearerr(fh); 500 501 return read_data; 502 } 503 504 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, 505 bool has_count, int64_t count, 506 Error **errp) 507 { 508 GuestFileWrite *write_data = NULL; 509 guchar *buf; 510 gsize buf_len; 511 int write_count; 512 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 513 FILE *fh; 514 515 if (!gfh) { 516 return NULL; 517 } 518 519 fh = gfh->fh; 520 521 if (gfh->state == RW_STATE_READING) { 522 int ret = fseek(fh, 0, SEEK_CUR); 523 if (ret == -1) { 524 error_setg_errno(errp, errno, "failed to seek file"); 525 return NULL; 526 } 527 gfh->state = RW_STATE_NEW; 528 } 529 530 buf = qbase64_decode(buf_b64, -1, &buf_len, errp); 531 if (!buf) { 532 return NULL; 533 } 534 535 if (!has_count) { 536 count = buf_len; 537 } else if (count < 0 || count > buf_len) { 538 error_setg(errp, "value '%" PRId64 "' is invalid for argument count", 539 count); 540 g_free(buf); 541 return NULL; 542 } 543 544 write_count = fwrite(buf, 1, count, fh); 545 if (ferror(fh)) { 546 error_setg_errno(errp, errno, "failed to write to file"); 547 slog("guest-file-write failed, handle: %" PRId64, handle); 548 } else { 549 write_data = g_new0(GuestFileWrite, 1); 550 write_data->count = write_count; 551 write_data->eof = feof(fh); 552 gfh->state = RW_STATE_WRITING; 553 } 554 g_free(buf); 555 clearerr(fh); 556 557 return write_data; 558 } 559 560 struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset, 561 GuestFileWhence *whence_code, 562 Error **errp) 563 { 564 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 565 GuestFileSeek *seek_data = NULL; 566 FILE *fh; 567 int ret; 568 int whence; 569 Error *err = NULL; 570 571 if (!gfh) { 572 return NULL; 573 } 574 575 /* We stupidly exposed 'whence':'int' in our qapi */ 576 whence = ga_parse_whence(whence_code, &err); 577 if (err) { 578 error_propagate(errp, err); 579 return NULL; 580 } 581 582 fh = gfh->fh; 583 ret = fseek(fh, offset, whence); 584 if (ret == -1) { 585 error_setg_errno(errp, errno, "failed to seek file"); 586 if (errno == ESPIPE) { 587 /* file is non-seekable, stdio shouldn't be buffering anyways */ 588 gfh->state = RW_STATE_NEW; 589 } 590 } else { 591 seek_data = g_new0(GuestFileSeek, 1); 592 seek_data->position = ftell(fh); 593 seek_data->eof = feof(fh); 594 gfh->state = RW_STATE_NEW; 595 } 596 clearerr(fh); 597 598 return seek_data; 599 } 600 601 void qmp_guest_file_flush(int64_t handle, Error **errp) 602 { 603 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 604 FILE *fh; 605 int ret; 606 607 if (!gfh) { 608 return; 609 } 610 611 fh = gfh->fh; 612 ret = fflush(fh); 613 if (ret == EOF) { 614 error_setg_errno(errp, errno, "failed to flush file"); 615 } else { 616 gfh->state = RW_STATE_NEW; 617 } 618 } 619 620 /* linux-specific implementations. avoid this if at all possible. */ 621 #if defined(__linux__) 622 623 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM) 624 typedef struct FsMount { 625 char *dirname; 626 char *devtype; 627 unsigned int devmajor, devminor; 628 QTAILQ_ENTRY(FsMount) next; 629 } FsMount; 630 631 typedef QTAILQ_HEAD(FsMountList, FsMount) FsMountList; 632 633 static void free_fs_mount_list(FsMountList *mounts) 634 { 635 FsMount *mount, *temp; 636 637 if (!mounts) { 638 return; 639 } 640 641 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) { 642 QTAILQ_REMOVE(mounts, mount, next); 643 g_free(mount->dirname); 644 g_free(mount->devtype); 645 g_free(mount); 646 } 647 } 648 649 static int dev_major_minor(const char *devpath, 650 unsigned int *devmajor, unsigned int *devminor) 651 { 652 struct stat st; 653 654 *devmajor = 0; 655 *devminor = 0; 656 657 if (stat(devpath, &st) < 0) { 658 slog("failed to stat device file '%s': %s", devpath, strerror(errno)); 659 return -1; 660 } 661 if (S_ISDIR(st.st_mode)) { 662 /* It is bind mount */ 663 return -2; 664 } 665 if (S_ISBLK(st.st_mode)) { 666 *devmajor = major(st.st_rdev); 667 *devminor = minor(st.st_rdev); 668 return 0; 669 } 670 return -1; 671 } 672 673 /* 674 * Walk the mount table and build a list of local file systems 675 */ 676 static bool build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp) 677 { 678 struct mntent *ment; 679 FsMount *mount; 680 char const *mtab = "/proc/self/mounts"; 681 FILE *fp; 682 unsigned int devmajor, devminor; 683 684 fp = setmntent(mtab, "r"); 685 if (!fp) { 686 error_setg(errp, "failed to open mtab file: '%s'", mtab); 687 return false; 688 } 689 690 while ((ment = getmntent(fp))) { 691 /* 692 * An entry which device name doesn't start with a '/' is 693 * either a dummy file system or a network file system. 694 * Add special handling for smbfs and cifs as is done by 695 * coreutils as well. 696 */ 697 if ((ment->mnt_fsname[0] != '/') || 698 (strcmp(ment->mnt_type, "smbfs") == 0) || 699 (strcmp(ment->mnt_type, "cifs") == 0)) { 700 continue; 701 } 702 if (dev_major_minor(ment->mnt_fsname, &devmajor, &devminor) == -2) { 703 /* Skip bind mounts */ 704 continue; 705 } 706 707 mount = g_new0(FsMount, 1); 708 mount->dirname = g_strdup(ment->mnt_dir); 709 mount->devtype = g_strdup(ment->mnt_type); 710 mount->devmajor = devmajor; 711 mount->devminor = devminor; 712 713 QTAILQ_INSERT_TAIL(mounts, mount, next); 714 } 715 716 endmntent(fp); 717 return true; 718 } 719 720 static void decode_mntname(char *name, int len) 721 { 722 int i, j = 0; 723 for (i = 0; i <= len; i++) { 724 if (name[i] != '\\') { 725 name[j++] = name[i]; 726 } else if (name[i + 1] == '\\') { 727 name[j++] = '\\'; 728 i++; 729 } else if (name[i + 1] >= '0' && name[i + 1] <= '3' && 730 name[i + 2] >= '0' && name[i + 2] <= '7' && 731 name[i + 3] >= '0' && name[i + 3] <= '7') { 732 name[j++] = (name[i + 1] - '0') * 64 + 733 (name[i + 2] - '0') * 8 + 734 (name[i + 3] - '0'); 735 i += 3; 736 } else { 737 name[j++] = name[i]; 738 } 739 } 740 } 741 742 static bool build_fs_mount_list(FsMountList *mounts, Error **errp) 743 { 744 FsMount *mount; 745 char const *mountinfo = "/proc/self/mountinfo"; 746 FILE *fp; 747 char *line = NULL, *dash; 748 size_t n; 749 char check; 750 unsigned int devmajor, devminor; 751 int ret, dir_s, dir_e, type_s, type_e, dev_s, dev_e; 752 753 fp = fopen(mountinfo, "r"); 754 if (!fp) { 755 return build_fs_mount_list_from_mtab(mounts, errp); 756 } 757 758 while (getline(&line, &n, fp) != -1) { 759 ret = sscanf(line, "%*u %*u %u:%u %*s %n%*s%n%c", 760 &devmajor, &devminor, &dir_s, &dir_e, &check); 761 if (ret < 3) { 762 continue; 763 } 764 dash = strstr(line + dir_e, " - "); 765 if (!dash) { 766 continue; 767 } 768 ret = sscanf(dash, " - %n%*s%n %n%*s%n%c", 769 &type_s, &type_e, &dev_s, &dev_e, &check); 770 if (ret < 1) { 771 continue; 772 } 773 line[dir_e] = 0; 774 dash[type_e] = 0; 775 dash[dev_e] = 0; 776 decode_mntname(line + dir_s, dir_e - dir_s); 777 decode_mntname(dash + dev_s, dev_e - dev_s); 778 if (devmajor == 0) { 779 /* btrfs reports major number = 0 */ 780 if (strcmp("btrfs", dash + type_s) != 0 || 781 dev_major_minor(dash + dev_s, &devmajor, &devminor) < 0) { 782 continue; 783 } 784 } 785 786 mount = g_new0(FsMount, 1); 787 mount->dirname = g_strdup(line + dir_s); 788 mount->devtype = g_strdup(dash + type_s); 789 mount->devmajor = devmajor; 790 mount->devminor = devminor; 791 792 QTAILQ_INSERT_TAIL(mounts, mount, next); 793 } 794 free(line); 795 796 fclose(fp); 797 return true; 798 } 799 #endif 800 801 #if defined(CONFIG_FSFREEZE) 802 803 static char *get_pci_driver(char const *syspath, int pathlen, Error **errp) 804 { 805 char *path; 806 char *dpath; 807 char *driver = NULL; 808 char buf[PATH_MAX]; 809 ssize_t len; 810 811 path = g_strndup(syspath, pathlen); 812 dpath = g_strdup_printf("%s/driver", path); 813 len = readlink(dpath, buf, sizeof(buf) - 1); 814 if (len != -1) { 815 buf[len] = 0; 816 driver = g_path_get_basename(buf); 817 } 818 g_free(dpath); 819 g_free(path); 820 return driver; 821 } 822 823 static int compare_uint(const void *_a, const void *_b) 824 { 825 unsigned int a = *(unsigned int *)_a; 826 unsigned int b = *(unsigned int *)_b; 827 828 return a < b ? -1 : a > b ? 1 : 0; 829 } 830 831 /* Walk the specified sysfs and build a sorted list of host or ata numbers */ 832 static int build_hosts(char const *syspath, char const *host, bool ata, 833 unsigned int *hosts, int hosts_max, Error **errp) 834 { 835 char *path; 836 DIR *dir; 837 struct dirent *entry; 838 int i = 0; 839 840 path = g_strndup(syspath, host - syspath); 841 dir = opendir(path); 842 if (!dir) { 843 error_setg_errno(errp, errno, "opendir(\"%s\")", path); 844 g_free(path); 845 return -1; 846 } 847 848 while (i < hosts_max) { 849 entry = readdir(dir); 850 if (!entry) { 851 break; 852 } 853 if (ata && sscanf(entry->d_name, "ata%d", hosts + i) == 1) { 854 ++i; 855 } else if (!ata && sscanf(entry->d_name, "host%d", hosts + i) == 1) { 856 ++i; 857 } 858 } 859 860 qsort(hosts, i, sizeof(hosts[0]), compare_uint); 861 862 g_free(path); 863 closedir(dir); 864 return i; 865 } 866 867 /* 868 * Store disk device info for devices on the PCI bus. 869 * Returns true if information has been stored, or false for failure. 870 */ 871 static bool build_guest_fsinfo_for_pci_dev(char const *syspath, 872 GuestDiskAddress *disk, 873 Error **errp) 874 { 875 unsigned int pci[4], host, hosts[8], tgt[3]; 876 int i, nhosts = 0, pcilen; 877 GuestPCIAddress *pciaddr = disk->pci_controller; 878 bool has_ata = false, has_host = false, has_tgt = false; 879 char *p, *q, *driver = NULL; 880 bool ret = false; 881 882 p = strstr(syspath, "/devices/pci"); 883 if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n", 884 pci, pci + 1, pci + 2, pci + 3, &pcilen) < 4) { 885 g_debug("only pci device is supported: sysfs path '%s'", syspath); 886 return false; 887 } 888 889 p += 12 + pcilen; 890 while (true) { 891 driver = get_pci_driver(syspath, p - syspath, errp); 892 if (driver && (g_str_equal(driver, "ata_piix") || 893 g_str_equal(driver, "sym53c8xx") || 894 g_str_equal(driver, "virtio-pci") || 895 g_str_equal(driver, "ahci") || 896 g_str_equal(driver, "nvme"))) { 897 break; 898 } 899 900 g_free(driver); 901 if (sscanf(p, "/%x:%x:%x.%x%n", 902 pci, pci + 1, pci + 2, pci + 3, &pcilen) == 4) { 903 p += pcilen; 904 continue; 905 } 906 907 g_debug("unsupported driver or sysfs path '%s'", syspath); 908 return false; 909 } 910 911 p = strstr(syspath, "/target"); 912 if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u", 913 tgt, tgt + 1, tgt + 2) == 3) { 914 has_tgt = true; 915 } 916 917 p = strstr(syspath, "/ata"); 918 if (p) { 919 q = p + 4; 920 has_ata = true; 921 } else { 922 p = strstr(syspath, "/host"); 923 q = p + 5; 924 } 925 if (p && sscanf(q, "%u", &host) == 1) { 926 has_host = true; 927 nhosts = build_hosts(syspath, p, has_ata, hosts, 928 ARRAY_SIZE(hosts), errp); 929 if (nhosts < 0) { 930 goto cleanup; 931 } 932 } 933 934 pciaddr->domain = pci[0]; 935 pciaddr->bus = pci[1]; 936 pciaddr->slot = pci[2]; 937 pciaddr->function = pci[3]; 938 939 if (strcmp(driver, "ata_piix") == 0) { 940 /* a host per ide bus, target*:0:<unit>:0 */ 941 if (!has_host || !has_tgt) { 942 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 943 goto cleanup; 944 } 945 for (i = 0; i < nhosts; i++) { 946 if (host == hosts[i]) { 947 disk->bus_type = GUEST_DISK_BUS_TYPE_IDE; 948 disk->bus = i; 949 disk->unit = tgt[1]; 950 break; 951 } 952 } 953 if (i >= nhosts) { 954 g_debug("no host for '%s' (driver '%s')", syspath, driver); 955 goto cleanup; 956 } 957 } else if (strcmp(driver, "sym53c8xx") == 0) { 958 /* scsi(LSI Logic): target*:0:<unit>:0 */ 959 if (!has_tgt) { 960 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 961 goto cleanup; 962 } 963 disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI; 964 disk->unit = tgt[1]; 965 } else if (strcmp(driver, "virtio-pci") == 0) { 966 if (has_tgt) { 967 /* virtio-scsi: target*:0:0:<unit> */ 968 disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI; 969 disk->unit = tgt[2]; 970 } else { 971 /* virtio-blk: 1 disk per 1 device */ 972 disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO; 973 } 974 } else if (strcmp(driver, "ahci") == 0) { 975 /* ahci: 1 host per 1 unit */ 976 if (!has_host || !has_tgt) { 977 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 978 goto cleanup; 979 } 980 for (i = 0; i < nhosts; i++) { 981 if (host == hosts[i]) { 982 disk->unit = i; 983 disk->bus_type = GUEST_DISK_BUS_TYPE_SATA; 984 break; 985 } 986 } 987 if (i >= nhosts) { 988 g_debug("no host for '%s' (driver '%s')", syspath, driver); 989 goto cleanup; 990 } 991 } else if (strcmp(driver, "nvme") == 0) { 992 disk->bus_type = GUEST_DISK_BUS_TYPE_NVME; 993 } else { 994 g_debug("unknown driver '%s' (sysfs path '%s')", driver, syspath); 995 goto cleanup; 996 } 997 998 ret = true; 999 1000 cleanup: 1001 g_free(driver); 1002 return ret; 1003 } 1004 1005 /* 1006 * Store disk device info for non-PCI virtio devices (for example s390x 1007 * channel I/O devices). Returns true if information has been stored, or 1008 * false for failure. 1009 */ 1010 static bool build_guest_fsinfo_for_nonpci_virtio(char const *syspath, 1011 GuestDiskAddress *disk, 1012 Error **errp) 1013 { 1014 unsigned int tgt[3]; 1015 char *p; 1016 1017 if (!strstr(syspath, "/virtio") || !strstr(syspath, "/block")) { 1018 g_debug("Unsupported virtio device '%s'", syspath); 1019 return false; 1020 } 1021 1022 p = strstr(syspath, "/target"); 1023 if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u", 1024 &tgt[0], &tgt[1], &tgt[2]) == 3) { 1025 /* virtio-scsi: target*:0:<target>:<unit> */ 1026 disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI; 1027 disk->bus = tgt[0]; 1028 disk->target = tgt[1]; 1029 disk->unit = tgt[2]; 1030 } else { 1031 /* virtio-blk: 1 disk per 1 device */ 1032 disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO; 1033 } 1034 1035 return true; 1036 } 1037 1038 /* 1039 * Store disk device info for CCW devices (s390x channel I/O devices). 1040 * Returns true if information has been stored, or false for failure. 1041 */ 1042 static bool build_guest_fsinfo_for_ccw_dev(char const *syspath, 1043 GuestDiskAddress *disk, 1044 Error **errp) 1045 { 1046 unsigned int cssid, ssid, subchno, devno; 1047 char *p; 1048 1049 p = strstr(syspath, "/devices/css"); 1050 if (!p || sscanf(p + 12, "%*x/%x.%x.%x/%*x.%*x.%x/", 1051 &cssid, &ssid, &subchno, &devno) < 4) { 1052 g_debug("could not parse ccw device sysfs path: %s", syspath); 1053 return false; 1054 } 1055 1056 disk->has_ccw_address = true; 1057 disk->ccw_address = g_new0(GuestCCWAddress, 1); 1058 disk->ccw_address->cssid = cssid; 1059 disk->ccw_address->ssid = ssid; 1060 disk->ccw_address->subchno = subchno; 1061 disk->ccw_address->devno = devno; 1062 1063 if (strstr(p, "/virtio")) { 1064 build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp); 1065 } 1066 1067 return true; 1068 } 1069 1070 /* Store disk device info specified by @sysfs into @fs */ 1071 static void build_guest_fsinfo_for_real_device(char const *syspath, 1072 GuestFilesystemInfo *fs, 1073 Error **errp) 1074 { 1075 GuestDiskAddress *disk; 1076 GuestPCIAddress *pciaddr; 1077 bool has_hwinf; 1078 #ifdef CONFIG_LIBUDEV 1079 struct udev *udev = NULL; 1080 struct udev_device *udevice = NULL; 1081 #endif 1082 1083 pciaddr = g_new0(GuestPCIAddress, 1); 1084 pciaddr->domain = -1; /* -1 means field is invalid */ 1085 pciaddr->bus = -1; 1086 pciaddr->slot = -1; 1087 pciaddr->function = -1; 1088 1089 disk = g_new0(GuestDiskAddress, 1); 1090 disk->pci_controller = pciaddr; 1091 disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN; 1092 1093 #ifdef CONFIG_LIBUDEV 1094 udev = udev_new(); 1095 udevice = udev_device_new_from_syspath(udev, syspath); 1096 if (udev == NULL || udevice == NULL) { 1097 g_debug("failed to query udev"); 1098 } else { 1099 const char *devnode, *serial; 1100 devnode = udev_device_get_devnode(udevice); 1101 if (devnode != NULL) { 1102 disk->dev = g_strdup(devnode); 1103 disk->has_dev = true; 1104 } 1105 serial = udev_device_get_property_value(udevice, "ID_SERIAL"); 1106 if (serial != NULL && *serial != 0) { 1107 disk->serial = g_strdup(serial); 1108 disk->has_serial = true; 1109 } 1110 } 1111 1112 udev_unref(udev); 1113 udev_device_unref(udevice); 1114 #endif 1115 1116 if (strstr(syspath, "/devices/pci")) { 1117 has_hwinf = build_guest_fsinfo_for_pci_dev(syspath, disk, errp); 1118 } else if (strstr(syspath, "/devices/css")) { 1119 has_hwinf = build_guest_fsinfo_for_ccw_dev(syspath, disk, errp); 1120 } else if (strstr(syspath, "/virtio")) { 1121 has_hwinf = build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp); 1122 } else { 1123 g_debug("Unsupported device type for '%s'", syspath); 1124 has_hwinf = false; 1125 } 1126 1127 if (has_hwinf || disk->has_dev || disk->has_serial) { 1128 QAPI_LIST_PREPEND(fs->disk, disk); 1129 } else { 1130 qapi_free_GuestDiskAddress(disk); 1131 } 1132 } 1133 1134 static void build_guest_fsinfo_for_device(char const *devpath, 1135 GuestFilesystemInfo *fs, 1136 Error **errp); 1137 1138 /* Store a list of slave devices of virtual volume specified by @syspath into 1139 * @fs */ 1140 static void build_guest_fsinfo_for_virtual_device(char const *syspath, 1141 GuestFilesystemInfo *fs, 1142 Error **errp) 1143 { 1144 Error *err = NULL; 1145 DIR *dir; 1146 char *dirpath; 1147 struct dirent *entry; 1148 1149 dirpath = g_strdup_printf("%s/slaves", syspath); 1150 dir = opendir(dirpath); 1151 if (!dir) { 1152 if (errno != ENOENT) { 1153 error_setg_errno(errp, errno, "opendir(\"%s\")", dirpath); 1154 } 1155 g_free(dirpath); 1156 return; 1157 } 1158 1159 for (;;) { 1160 errno = 0; 1161 entry = readdir(dir); 1162 if (entry == NULL) { 1163 if (errno) { 1164 error_setg_errno(errp, errno, "readdir(\"%s\")", dirpath); 1165 } 1166 break; 1167 } 1168 1169 if (entry->d_type == DT_LNK) { 1170 char *path; 1171 1172 g_debug(" slave device '%s'", entry->d_name); 1173 path = g_strdup_printf("%s/slaves/%s", syspath, entry->d_name); 1174 build_guest_fsinfo_for_device(path, fs, &err); 1175 g_free(path); 1176 1177 if (err) { 1178 error_propagate(errp, err); 1179 break; 1180 } 1181 } 1182 } 1183 1184 g_free(dirpath); 1185 closedir(dir); 1186 } 1187 1188 static bool is_disk_virtual(const char *devpath, Error **errp) 1189 { 1190 g_autofree char *syspath = realpath(devpath, NULL); 1191 1192 if (!syspath) { 1193 error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); 1194 return false; 1195 } 1196 return strstr(syspath, "/devices/virtual/block/") != NULL; 1197 } 1198 1199 /* Dispatch to functions for virtual/real device */ 1200 static void build_guest_fsinfo_for_device(char const *devpath, 1201 GuestFilesystemInfo *fs, 1202 Error **errp) 1203 { 1204 ERRP_GUARD(); 1205 g_autofree char *syspath = NULL; 1206 bool is_virtual = false; 1207 1208 syspath = realpath(devpath, NULL); 1209 if (!syspath) { 1210 if (errno != ENOENT) { 1211 error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); 1212 return; 1213 } 1214 1215 /* ENOENT: This devpath may not exist because of container config */ 1216 if (!fs->name) { 1217 fs->name = g_path_get_basename(devpath); 1218 } 1219 return; 1220 } 1221 1222 if (!fs->name) { 1223 fs->name = g_path_get_basename(syspath); 1224 } 1225 1226 g_debug(" parse sysfs path '%s'", syspath); 1227 is_virtual = is_disk_virtual(syspath, errp); 1228 if (*errp != NULL) { 1229 return; 1230 } 1231 if (is_virtual) { 1232 build_guest_fsinfo_for_virtual_device(syspath, fs, errp); 1233 } else { 1234 build_guest_fsinfo_for_real_device(syspath, fs, errp); 1235 } 1236 } 1237 1238 #ifdef CONFIG_LIBUDEV 1239 1240 /* 1241 * Wrapper around build_guest_fsinfo_for_device() for getting just 1242 * the disk address. 1243 */ 1244 static GuestDiskAddress *get_disk_address(const char *syspath, Error **errp) 1245 { 1246 g_autoptr(GuestFilesystemInfo) fs = NULL; 1247 1248 fs = g_new0(GuestFilesystemInfo, 1); 1249 build_guest_fsinfo_for_device(syspath, fs, errp); 1250 if (fs->disk != NULL) { 1251 return g_steal_pointer(&fs->disk->value); 1252 } 1253 return NULL; 1254 } 1255 1256 static char *get_alias_for_syspath(const char *syspath) 1257 { 1258 struct udev *udev = NULL; 1259 struct udev_device *udevice = NULL; 1260 char *ret = NULL; 1261 1262 udev = udev_new(); 1263 if (udev == NULL) { 1264 g_debug("failed to query udev"); 1265 goto out; 1266 } 1267 udevice = udev_device_new_from_syspath(udev, syspath); 1268 if (udevice == NULL) { 1269 g_debug("failed to query udev for path: %s", syspath); 1270 goto out; 1271 } else { 1272 const char *alias = udev_device_get_property_value( 1273 udevice, "DM_NAME"); 1274 /* 1275 * NULL means there was an error and empty string means there is no 1276 * alias. In case of no alias we return NULL instead of empty string. 1277 */ 1278 if (alias == NULL) { 1279 g_debug("failed to query udev for device alias for: %s", 1280 syspath); 1281 } else if (*alias != 0) { 1282 ret = g_strdup(alias); 1283 } 1284 } 1285 1286 out: 1287 udev_unref(udev); 1288 udev_device_unref(udevice); 1289 return ret; 1290 } 1291 1292 static char *get_device_for_syspath(const char *syspath) 1293 { 1294 struct udev *udev = NULL; 1295 struct udev_device *udevice = NULL; 1296 char *ret = NULL; 1297 1298 udev = udev_new(); 1299 if (udev == NULL) { 1300 g_debug("failed to query udev"); 1301 goto out; 1302 } 1303 udevice = udev_device_new_from_syspath(udev, syspath); 1304 if (udevice == NULL) { 1305 g_debug("failed to query udev for path: %s", syspath); 1306 goto out; 1307 } else { 1308 ret = g_strdup(udev_device_get_devnode(udevice)); 1309 } 1310 1311 out: 1312 udev_unref(udev); 1313 udev_device_unref(udevice); 1314 return ret; 1315 } 1316 1317 static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk) 1318 { 1319 g_autofree char *deps_dir = NULL; 1320 const gchar *dep; 1321 GDir *dp_deps = NULL; 1322 1323 /* List dependent disks */ 1324 deps_dir = g_strdup_printf("%s/slaves", disk_dir); 1325 g_debug(" listing entries in: %s", deps_dir); 1326 dp_deps = g_dir_open(deps_dir, 0, NULL); 1327 if (dp_deps == NULL) { 1328 g_debug("failed to list entries in %s", deps_dir); 1329 return; 1330 } 1331 disk->has_dependencies = true; 1332 while ((dep = g_dir_read_name(dp_deps)) != NULL) { 1333 g_autofree char *dep_dir = NULL; 1334 char *dev_name; 1335 1336 /* Add dependent disks */ 1337 dep_dir = g_strdup_printf("%s/%s", deps_dir, dep); 1338 dev_name = get_device_for_syspath(dep_dir); 1339 if (dev_name != NULL) { 1340 g_debug(" adding dependent device: %s", dev_name); 1341 QAPI_LIST_PREPEND(disk->dependencies, dev_name); 1342 } 1343 } 1344 g_dir_close(dp_deps); 1345 } 1346 1347 /* 1348 * Detect partitions subdirectory, name is "<disk_name><number>" or 1349 * "<disk_name>p<number>" 1350 * 1351 * @disk_name -- last component of /sys path (e.g. sda) 1352 * @disk_dir -- sys path of the disk (e.g. /sys/block/sda) 1353 * @disk_dev -- device node of the disk (e.g. /dev/sda) 1354 */ 1355 static GuestDiskInfoList *get_disk_partitions( 1356 GuestDiskInfoList *list, 1357 const char *disk_name, const char *disk_dir, 1358 const char *disk_dev) 1359 { 1360 GuestDiskInfoList *ret = list; 1361 struct dirent *de_disk; 1362 DIR *dp_disk = NULL; 1363 size_t len = strlen(disk_name); 1364 1365 dp_disk = opendir(disk_dir); 1366 while ((de_disk = readdir(dp_disk)) != NULL) { 1367 g_autofree char *partition_dir = NULL; 1368 char *dev_name; 1369 GuestDiskInfo *partition; 1370 1371 if (!(de_disk->d_type & DT_DIR)) { 1372 continue; 1373 } 1374 1375 if (!(strncmp(disk_name, de_disk->d_name, len) == 0 && 1376 ((*(de_disk->d_name + len) == 'p' && 1377 isdigit(*(de_disk->d_name + len + 1))) || 1378 isdigit(*(de_disk->d_name + len))))) { 1379 continue; 1380 } 1381 1382 partition_dir = g_strdup_printf("%s/%s", 1383 disk_dir, de_disk->d_name); 1384 dev_name = get_device_for_syspath(partition_dir); 1385 if (dev_name == NULL) { 1386 g_debug("Failed to get device name for syspath: %s", 1387 disk_dir); 1388 continue; 1389 } 1390 partition = g_new0(GuestDiskInfo, 1); 1391 partition->name = dev_name; 1392 partition->partition = true; 1393 partition->has_dependencies = true; 1394 /* Add parent disk as dependent for easier tracking of hierarchy */ 1395 QAPI_LIST_PREPEND(partition->dependencies, g_strdup(disk_dev)); 1396 1397 QAPI_LIST_PREPEND(ret, partition); 1398 } 1399 closedir(dp_disk); 1400 1401 return ret; 1402 } 1403 1404 static void get_nvme_smart(GuestDiskInfo *disk) 1405 { 1406 int fd; 1407 GuestNVMeSmart *smart; 1408 NvmeSmartLog log = {0}; 1409 struct nvme_admin_cmd cmd = { 1410 .opcode = NVME_ADM_CMD_GET_LOG_PAGE, 1411 .nsid = NVME_NSID_BROADCAST, 1412 .addr = (uintptr_t)&log, 1413 .data_len = sizeof(log), 1414 .cdw10 = NVME_LOG_SMART_INFO | (1 << 15) /* RAE bit */ 1415 | (((sizeof(log) >> 2) - 1) << 16) 1416 }; 1417 1418 fd = qga_open_cloexec(disk->name, O_RDONLY, 0); 1419 if (fd == -1) { 1420 g_debug("Failed to open device: %s: %s", disk->name, g_strerror(errno)); 1421 return; 1422 } 1423 1424 if (ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd)) { 1425 g_debug("Failed to get smart: %s: %s", disk->name, g_strerror(errno)); 1426 close(fd); 1427 return; 1428 } 1429 1430 disk->has_smart = true; 1431 disk->smart = g_new0(GuestDiskSmart, 1); 1432 disk->smart->type = GUEST_DISK_BUS_TYPE_NVME; 1433 1434 smart = &disk->smart->u.nvme; 1435 smart->critical_warning = log.critical_warning; 1436 smart->temperature = lduw_le_p(&log.temperature); /* unaligned field */ 1437 smart->available_spare = log.available_spare; 1438 smart->available_spare_threshold = log.available_spare_threshold; 1439 smart->percentage_used = log.percentage_used; 1440 smart->data_units_read_lo = le64_to_cpu(log.data_units_read[0]); 1441 smart->data_units_read_hi = le64_to_cpu(log.data_units_read[1]); 1442 smart->data_units_written_lo = le64_to_cpu(log.data_units_written[0]); 1443 smart->data_units_written_hi = le64_to_cpu(log.data_units_written[1]); 1444 smart->host_read_commands_lo = le64_to_cpu(log.host_read_commands[0]); 1445 smart->host_read_commands_hi = le64_to_cpu(log.host_read_commands[1]); 1446 smart->host_write_commands_lo = le64_to_cpu(log.host_write_commands[0]); 1447 smart->host_write_commands_hi = le64_to_cpu(log.host_write_commands[1]); 1448 smart->controller_busy_time_lo = le64_to_cpu(log.controller_busy_time[0]); 1449 smart->controller_busy_time_hi = le64_to_cpu(log.controller_busy_time[1]); 1450 smart->power_cycles_lo = le64_to_cpu(log.power_cycles[0]); 1451 smart->power_cycles_hi = le64_to_cpu(log.power_cycles[1]); 1452 smart->power_on_hours_lo = le64_to_cpu(log.power_on_hours[0]); 1453 smart->power_on_hours_hi = le64_to_cpu(log.power_on_hours[1]); 1454 smart->unsafe_shutdowns_lo = le64_to_cpu(log.unsafe_shutdowns[0]); 1455 smart->unsafe_shutdowns_hi = le64_to_cpu(log.unsafe_shutdowns[1]); 1456 smart->media_errors_lo = le64_to_cpu(log.media_errors[0]); 1457 smart->media_errors_hi = le64_to_cpu(log.media_errors[1]); 1458 smart->number_of_error_log_entries_lo = 1459 le64_to_cpu(log.number_of_error_log_entries[0]); 1460 smart->number_of_error_log_entries_hi = 1461 le64_to_cpu(log.number_of_error_log_entries[1]); 1462 1463 close(fd); 1464 } 1465 1466 static void get_disk_smart(GuestDiskInfo *disk) 1467 { 1468 if (disk->has_address 1469 && (disk->address->bus_type == GUEST_DISK_BUS_TYPE_NVME)) { 1470 get_nvme_smart(disk); 1471 } 1472 } 1473 1474 GuestDiskInfoList *qmp_guest_get_disks(Error **errp) 1475 { 1476 GuestDiskInfoList *ret = NULL; 1477 GuestDiskInfo *disk; 1478 DIR *dp = NULL; 1479 struct dirent *de = NULL; 1480 1481 g_debug("listing /sys/block directory"); 1482 dp = opendir("/sys/block"); 1483 if (dp == NULL) { 1484 error_setg_errno(errp, errno, "Can't open directory \"/sys/block\""); 1485 return NULL; 1486 } 1487 while ((de = readdir(dp)) != NULL) { 1488 g_autofree char *disk_dir = NULL, *line = NULL, 1489 *size_path = NULL; 1490 char *dev_name; 1491 Error *local_err = NULL; 1492 if (de->d_type != DT_LNK) { 1493 g_debug(" skipping entry: %s", de->d_name); 1494 continue; 1495 } 1496 1497 /* Check size and skip zero-sized disks */ 1498 g_debug(" checking disk size"); 1499 size_path = g_strdup_printf("/sys/block/%s/size", de->d_name); 1500 if (!g_file_get_contents(size_path, &line, NULL, NULL)) { 1501 g_debug(" failed to read disk size"); 1502 continue; 1503 } 1504 if (g_strcmp0(line, "0\n") == 0) { 1505 g_debug(" skipping zero-sized disk"); 1506 continue; 1507 } 1508 1509 g_debug(" adding %s", de->d_name); 1510 disk_dir = g_strdup_printf("/sys/block/%s", de->d_name); 1511 dev_name = get_device_for_syspath(disk_dir); 1512 if (dev_name == NULL) { 1513 g_debug("Failed to get device name for syspath: %s", 1514 disk_dir); 1515 continue; 1516 } 1517 disk = g_new0(GuestDiskInfo, 1); 1518 disk->name = dev_name; 1519 disk->partition = false; 1520 disk->alias = get_alias_for_syspath(disk_dir); 1521 disk->has_alias = (disk->alias != NULL); 1522 QAPI_LIST_PREPEND(ret, disk); 1523 1524 /* Get address for non-virtual devices */ 1525 bool is_virtual = is_disk_virtual(disk_dir, &local_err); 1526 if (local_err != NULL) { 1527 g_debug(" failed to check disk path, ignoring error: %s", 1528 error_get_pretty(local_err)); 1529 error_free(local_err); 1530 local_err = NULL; 1531 /* Don't try to get the address */ 1532 is_virtual = true; 1533 } 1534 if (!is_virtual) { 1535 disk->address = get_disk_address(disk_dir, &local_err); 1536 if (local_err != NULL) { 1537 g_debug(" failed to get device info, ignoring error: %s", 1538 error_get_pretty(local_err)); 1539 error_free(local_err); 1540 local_err = NULL; 1541 } else if (disk->address != NULL) { 1542 disk->has_address = true; 1543 } 1544 } 1545 1546 get_disk_deps(disk_dir, disk); 1547 get_disk_smart(disk); 1548 ret = get_disk_partitions(ret, de->d_name, disk_dir, dev_name); 1549 } 1550 1551 closedir(dp); 1552 1553 return ret; 1554 } 1555 1556 #else 1557 1558 GuestDiskInfoList *qmp_guest_get_disks(Error **errp) 1559 { 1560 error_setg(errp, QERR_UNSUPPORTED); 1561 return NULL; 1562 } 1563 1564 #endif 1565 1566 /* Return a list of the disk device(s)' info which @mount lies on */ 1567 static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount, 1568 Error **errp) 1569 { 1570 GuestFilesystemInfo *fs = g_malloc0(sizeof(*fs)); 1571 struct statvfs buf; 1572 unsigned long used, nonroot_total, fr_size; 1573 char *devpath = g_strdup_printf("/sys/dev/block/%u:%u", 1574 mount->devmajor, mount->devminor); 1575 1576 fs->mountpoint = g_strdup(mount->dirname); 1577 fs->type = g_strdup(mount->devtype); 1578 build_guest_fsinfo_for_device(devpath, fs, errp); 1579 1580 if (statvfs(fs->mountpoint, &buf) == 0) { 1581 fr_size = buf.f_frsize; 1582 used = buf.f_blocks - buf.f_bfree; 1583 nonroot_total = used + buf.f_bavail; 1584 fs->used_bytes = used * fr_size; 1585 fs->total_bytes = nonroot_total * fr_size; 1586 1587 fs->has_total_bytes = true; 1588 fs->has_used_bytes = true; 1589 } 1590 1591 g_free(devpath); 1592 1593 return fs; 1594 } 1595 1596 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 1597 { 1598 FsMountList mounts; 1599 struct FsMount *mount; 1600 GuestFilesystemInfoList *ret = NULL; 1601 Error *local_err = NULL; 1602 1603 QTAILQ_INIT(&mounts); 1604 if (!build_fs_mount_list(&mounts, &local_err)) { 1605 error_propagate(errp, local_err); 1606 return NULL; 1607 } 1608 1609 QTAILQ_FOREACH(mount, &mounts, next) { 1610 g_debug("Building guest fsinfo for '%s'", mount->dirname); 1611 1612 QAPI_LIST_PREPEND(ret, build_guest_fsinfo(mount, &local_err)); 1613 if (local_err) { 1614 error_propagate(errp, local_err); 1615 qapi_free_GuestFilesystemInfoList(ret); 1616 ret = NULL; 1617 break; 1618 } 1619 } 1620 1621 free_fs_mount_list(&mounts); 1622 return ret; 1623 } 1624 1625 1626 typedef enum { 1627 FSFREEZE_HOOK_THAW = 0, 1628 FSFREEZE_HOOK_FREEZE, 1629 } FsfreezeHookArg; 1630 1631 static const char *fsfreeze_hook_arg_string[] = { 1632 "thaw", 1633 "freeze", 1634 }; 1635 1636 static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **errp) 1637 { 1638 int status; 1639 pid_t pid; 1640 const char *hook; 1641 const char *arg_str = fsfreeze_hook_arg_string[arg]; 1642 Error *local_err = NULL; 1643 1644 hook = ga_fsfreeze_hook(ga_state); 1645 if (!hook) { 1646 return; 1647 } 1648 if (access(hook, X_OK) != 0) { 1649 error_setg_errno(errp, errno, "can't access fsfreeze hook '%s'", hook); 1650 return; 1651 } 1652 1653 slog("executing fsfreeze hook with arg '%s'", arg_str); 1654 pid = fork(); 1655 if (pid == 0) { 1656 setsid(); 1657 reopen_fd_to_null(0); 1658 reopen_fd_to_null(1); 1659 reopen_fd_to_null(2); 1660 1661 execl(hook, hook, arg_str, NULL); 1662 _exit(EXIT_FAILURE); 1663 } else if (pid < 0) { 1664 error_setg_errno(errp, errno, "failed to create child process"); 1665 return; 1666 } 1667 1668 ga_wait_child(pid, &status, &local_err); 1669 if (local_err) { 1670 error_propagate(errp, local_err); 1671 return; 1672 } 1673 1674 if (!WIFEXITED(status)) { 1675 error_setg(errp, "fsfreeze hook has terminated abnormally"); 1676 return; 1677 } 1678 1679 status = WEXITSTATUS(status); 1680 if (status) { 1681 error_setg(errp, "fsfreeze hook has failed with status %d", status); 1682 return; 1683 } 1684 } 1685 1686 /* 1687 * Return status of freeze/thaw 1688 */ 1689 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 1690 { 1691 if (ga_is_frozen(ga_state)) { 1692 return GUEST_FSFREEZE_STATUS_FROZEN; 1693 } 1694 1695 return GUEST_FSFREEZE_STATUS_THAWED; 1696 } 1697 1698 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 1699 { 1700 return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); 1701 } 1702 1703 /* 1704 * Walk list of mounted file systems in the guest, and freeze the ones which 1705 * are real local file systems. 1706 */ 1707 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 1708 strList *mountpoints, 1709 Error **errp) 1710 { 1711 int ret = 0, i = 0; 1712 strList *list; 1713 FsMountList mounts; 1714 struct FsMount *mount; 1715 Error *local_err = NULL; 1716 int fd; 1717 1718 slog("guest-fsfreeze called"); 1719 1720 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); 1721 if (local_err) { 1722 error_propagate(errp, local_err); 1723 return -1; 1724 } 1725 1726 QTAILQ_INIT(&mounts); 1727 if (!build_fs_mount_list(&mounts, &local_err)) { 1728 error_propagate(errp, local_err); 1729 return -1; 1730 } 1731 1732 /* cannot risk guest agent blocking itself on a write in this state */ 1733 ga_set_frozen(ga_state); 1734 1735 QTAILQ_FOREACH_REVERSE(mount, &mounts, next) { 1736 /* To issue fsfreeze in the reverse order of mounts, check if the 1737 * mount is listed in the list here */ 1738 if (has_mountpoints) { 1739 for (list = mountpoints; list; list = list->next) { 1740 if (strcmp(list->value, mount->dirname) == 0) { 1741 break; 1742 } 1743 } 1744 if (!list) { 1745 continue; 1746 } 1747 } 1748 1749 fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0); 1750 if (fd == -1) { 1751 error_setg_errno(errp, errno, "failed to open %s", mount->dirname); 1752 goto error; 1753 } 1754 1755 /* we try to cull filesystems we know won't work in advance, but other 1756 * filesystems may not implement fsfreeze for less obvious reasons. 1757 * these will report EOPNOTSUPP. we simply ignore these when tallying 1758 * the number of frozen filesystems. 1759 * if a filesystem is mounted more than once (aka bind mount) a 1760 * consecutive attempt to freeze an already frozen filesystem will 1761 * return EBUSY. 1762 * 1763 * any other error means a failure to freeze a filesystem we 1764 * expect to be freezable, so return an error in those cases 1765 * and return system to thawed state. 1766 */ 1767 ret = ioctl(fd, FIFREEZE); 1768 if (ret == -1) { 1769 if (errno != EOPNOTSUPP && errno != EBUSY) { 1770 error_setg_errno(errp, errno, "failed to freeze %s", 1771 mount->dirname); 1772 close(fd); 1773 goto error; 1774 } 1775 } else { 1776 i++; 1777 } 1778 close(fd); 1779 } 1780 1781 free_fs_mount_list(&mounts); 1782 /* We may not issue any FIFREEZE here. 1783 * Just unset ga_state here and ready for the next call. 1784 */ 1785 if (i == 0) { 1786 ga_unset_frozen(ga_state); 1787 } 1788 return i; 1789 1790 error: 1791 free_fs_mount_list(&mounts); 1792 qmp_guest_fsfreeze_thaw(NULL); 1793 return 0; 1794 } 1795 1796 /* 1797 * Walk list of frozen file systems in the guest, and thaw them. 1798 */ 1799 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 1800 { 1801 int ret; 1802 FsMountList mounts; 1803 FsMount *mount; 1804 int fd, i = 0, logged; 1805 Error *local_err = NULL; 1806 1807 QTAILQ_INIT(&mounts); 1808 if (!build_fs_mount_list(&mounts, &local_err)) { 1809 error_propagate(errp, local_err); 1810 return 0; 1811 } 1812 1813 QTAILQ_FOREACH(mount, &mounts, next) { 1814 logged = false; 1815 fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0); 1816 if (fd == -1) { 1817 continue; 1818 } 1819 /* we have no way of knowing whether a filesystem was actually unfrozen 1820 * as a result of a successful call to FITHAW, only that if an error 1821 * was returned the filesystem was *not* unfrozen by that particular 1822 * call. 1823 * 1824 * since multiple preceding FIFREEZEs require multiple calls to FITHAW 1825 * to unfreeze, continuing issuing FITHAW until an error is returned, 1826 * in which case either the filesystem is in an unfreezable state, or, 1827 * more likely, it was thawed previously (and remains so afterward). 1828 * 1829 * also, since the most recent successful call is the one that did 1830 * the actual unfreeze, we can use this to provide an accurate count 1831 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which 1832 * may * be useful for determining whether a filesystem was unfrozen 1833 * during the freeze/thaw phase by a process other than qemu-ga. 1834 */ 1835 do { 1836 ret = ioctl(fd, FITHAW); 1837 if (ret == 0 && !logged) { 1838 i++; 1839 logged = true; 1840 } 1841 } while (ret == 0); 1842 close(fd); 1843 } 1844 1845 ga_unset_frozen(ga_state); 1846 free_fs_mount_list(&mounts); 1847 1848 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, errp); 1849 1850 return i; 1851 } 1852 1853 static void guest_fsfreeze_cleanup(void) 1854 { 1855 Error *err = NULL; 1856 1857 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 1858 qmp_guest_fsfreeze_thaw(&err); 1859 if (err) { 1860 slog("failed to clean up frozen filesystems: %s", 1861 error_get_pretty(err)); 1862 error_free(err); 1863 } 1864 } 1865 } 1866 #endif /* CONFIG_FSFREEZE */ 1867 1868 #if defined(CONFIG_FSTRIM) 1869 /* 1870 * Walk list of mounted file systems in the guest, and trim them. 1871 */ 1872 GuestFilesystemTrimResponse * 1873 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 1874 { 1875 GuestFilesystemTrimResponse *response; 1876 GuestFilesystemTrimResult *result; 1877 int ret = 0; 1878 FsMountList mounts; 1879 struct FsMount *mount; 1880 int fd; 1881 struct fstrim_range r; 1882 1883 slog("guest-fstrim called"); 1884 1885 QTAILQ_INIT(&mounts); 1886 if (!build_fs_mount_list(&mounts, errp)) { 1887 return NULL; 1888 } 1889 1890 response = g_malloc0(sizeof(*response)); 1891 1892 QTAILQ_FOREACH(mount, &mounts, next) { 1893 result = g_malloc0(sizeof(*result)); 1894 result->path = g_strdup(mount->dirname); 1895 1896 QAPI_LIST_PREPEND(response->paths, result); 1897 1898 fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0); 1899 if (fd == -1) { 1900 result->error = g_strdup_printf("failed to open: %s", 1901 strerror(errno)); 1902 result->has_error = true; 1903 continue; 1904 } 1905 1906 /* We try to cull filesystems we know won't work in advance, but other 1907 * filesystems may not implement fstrim for less obvious reasons. 1908 * These will report EOPNOTSUPP; while in some other cases ENOTTY 1909 * will be reported (e.g. CD-ROMs). 1910 * Any other error means an unexpected error. 1911 */ 1912 r.start = 0; 1913 r.len = -1; 1914 r.minlen = has_minimum ? minimum : 0; 1915 ret = ioctl(fd, FITRIM, &r); 1916 if (ret == -1) { 1917 result->has_error = true; 1918 if (errno == ENOTTY || errno == EOPNOTSUPP) { 1919 result->error = g_strdup("trim not supported"); 1920 } else { 1921 result->error = g_strdup_printf("failed to trim: %s", 1922 strerror(errno)); 1923 } 1924 close(fd); 1925 continue; 1926 } 1927 1928 result->has_minimum = true; 1929 result->minimum = r.minlen; 1930 result->has_trimmed = true; 1931 result->trimmed = r.len; 1932 close(fd); 1933 } 1934 1935 free_fs_mount_list(&mounts); 1936 return response; 1937 } 1938 #endif /* CONFIG_FSTRIM */ 1939 1940 1941 #define LINUX_SYS_STATE_FILE "/sys/power/state" 1942 #define SUSPEND_SUPPORTED 0 1943 #define SUSPEND_NOT_SUPPORTED 1 1944 1945 typedef enum { 1946 SUSPEND_MODE_DISK = 0, 1947 SUSPEND_MODE_RAM = 1, 1948 SUSPEND_MODE_HYBRID = 2, 1949 } SuspendMode; 1950 1951 /* 1952 * Executes a command in a child process using g_spawn_sync, 1953 * returning an int >= 0 representing the exit status of the 1954 * process. 1955 * 1956 * If the program wasn't found in path, returns -1. 1957 * 1958 * If a problem happened when creating the child process, 1959 * returns -1 and errp is set. 1960 */ 1961 static int run_process_child(const char *command[], Error **errp) 1962 { 1963 int exit_status, spawn_flag; 1964 GError *g_err = NULL; 1965 bool success; 1966 1967 spawn_flag = G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | 1968 G_SPAWN_STDERR_TO_DEV_NULL; 1969 1970 success = g_spawn_sync(NULL, (char **)command, NULL, spawn_flag, 1971 NULL, NULL, NULL, NULL, 1972 &exit_status, &g_err); 1973 1974 if (success) { 1975 return WEXITSTATUS(exit_status); 1976 } 1977 1978 if (g_err && (g_err->code != G_SPAWN_ERROR_NOENT)) { 1979 error_setg(errp, "failed to create child process, error '%s'", 1980 g_err->message); 1981 } 1982 1983 g_error_free(g_err); 1984 return -1; 1985 } 1986 1987 static bool systemd_supports_mode(SuspendMode mode, Error **errp) 1988 { 1989 const char *systemctl_args[3] = {"systemd-hibernate", "systemd-suspend", 1990 "systemd-hybrid-sleep"}; 1991 const char *cmd[4] = {"systemctl", "status", systemctl_args[mode], NULL}; 1992 int status; 1993 1994 status = run_process_child(cmd, errp); 1995 1996 /* 1997 * systemctl status uses LSB return codes so we can expect 1998 * status > 0 and be ok. To assert if the guest has support 1999 * for the selected suspend mode, status should be < 4. 4 is 2000 * the code for unknown service status, the return value when 2001 * the service does not exist. A common value is status = 3 2002 * (program is not running). 2003 */ 2004 if (status > 0 && status < 4) { 2005 return true; 2006 } 2007 2008 return false; 2009 } 2010 2011 static void systemd_suspend(SuspendMode mode, Error **errp) 2012 { 2013 Error *local_err = NULL; 2014 const char *systemctl_args[3] = {"hibernate", "suspend", "hybrid-sleep"}; 2015 const char *cmd[3] = {"systemctl", systemctl_args[mode], NULL}; 2016 int status; 2017 2018 status = run_process_child(cmd, &local_err); 2019 2020 if (status == 0) { 2021 return; 2022 } 2023 2024 if ((status == -1) && !local_err) { 2025 error_setg(errp, "the helper program 'systemctl %s' was not found", 2026 systemctl_args[mode]); 2027 return; 2028 } 2029 2030 if (local_err) { 2031 error_propagate(errp, local_err); 2032 } else { 2033 error_setg(errp, "the helper program 'systemctl %s' returned an " 2034 "unexpected exit status code (%d)", 2035 systemctl_args[mode], status); 2036 } 2037 } 2038 2039 static bool pmutils_supports_mode(SuspendMode mode, Error **errp) 2040 { 2041 Error *local_err = NULL; 2042 const char *pmutils_args[3] = {"--hibernate", "--suspend", 2043 "--suspend-hybrid"}; 2044 const char *cmd[3] = {"pm-is-supported", pmutils_args[mode], NULL}; 2045 int status; 2046 2047 status = run_process_child(cmd, &local_err); 2048 2049 if (status == SUSPEND_SUPPORTED) { 2050 return true; 2051 } 2052 2053 if ((status == -1) && !local_err) { 2054 return false; 2055 } 2056 2057 if (local_err) { 2058 error_propagate(errp, local_err); 2059 } else { 2060 error_setg(errp, 2061 "the helper program '%s' returned an unexpected exit" 2062 " status code (%d)", "pm-is-supported", status); 2063 } 2064 2065 return false; 2066 } 2067 2068 static void pmutils_suspend(SuspendMode mode, Error **errp) 2069 { 2070 Error *local_err = NULL; 2071 const char *pmutils_binaries[3] = {"pm-hibernate", "pm-suspend", 2072 "pm-suspend-hybrid"}; 2073 const char *cmd[2] = {pmutils_binaries[mode], NULL}; 2074 int status; 2075 2076 status = run_process_child(cmd, &local_err); 2077 2078 if (status == 0) { 2079 return; 2080 } 2081 2082 if ((status == -1) && !local_err) { 2083 error_setg(errp, "the helper program '%s' was not found", 2084 pmutils_binaries[mode]); 2085 return; 2086 } 2087 2088 if (local_err) { 2089 error_propagate(errp, local_err); 2090 } else { 2091 error_setg(errp, 2092 "the helper program '%s' returned an unexpected exit" 2093 " status code (%d)", pmutils_binaries[mode], status); 2094 } 2095 } 2096 2097 static bool linux_sys_state_supports_mode(SuspendMode mode, Error **errp) 2098 { 2099 const char *sysfile_strs[3] = {"disk", "mem", NULL}; 2100 const char *sysfile_str = sysfile_strs[mode]; 2101 char buf[32]; /* hopefully big enough */ 2102 int fd; 2103 ssize_t ret; 2104 2105 if (!sysfile_str) { 2106 error_setg(errp, "unknown guest suspend mode"); 2107 return false; 2108 } 2109 2110 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY); 2111 if (fd < 0) { 2112 return false; 2113 } 2114 2115 ret = read(fd, buf, sizeof(buf) - 1); 2116 close(fd); 2117 if (ret <= 0) { 2118 return false; 2119 } 2120 buf[ret] = '\0'; 2121 2122 if (strstr(buf, sysfile_str)) { 2123 return true; 2124 } 2125 return false; 2126 } 2127 2128 static void linux_sys_state_suspend(SuspendMode mode, Error **errp) 2129 { 2130 Error *local_err = NULL; 2131 const char *sysfile_strs[3] = {"disk", "mem", NULL}; 2132 const char *sysfile_str = sysfile_strs[mode]; 2133 pid_t pid; 2134 int status; 2135 2136 if (!sysfile_str) { 2137 error_setg(errp, "unknown guest suspend mode"); 2138 return; 2139 } 2140 2141 pid = fork(); 2142 if (!pid) { 2143 /* child */ 2144 int fd; 2145 2146 setsid(); 2147 reopen_fd_to_null(0); 2148 reopen_fd_to_null(1); 2149 reopen_fd_to_null(2); 2150 2151 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); 2152 if (fd < 0) { 2153 _exit(EXIT_FAILURE); 2154 } 2155 2156 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) { 2157 _exit(EXIT_FAILURE); 2158 } 2159 2160 _exit(EXIT_SUCCESS); 2161 } else if (pid < 0) { 2162 error_setg_errno(errp, errno, "failed to create child process"); 2163 return; 2164 } 2165 2166 ga_wait_child(pid, &status, &local_err); 2167 if (local_err) { 2168 error_propagate(errp, local_err); 2169 return; 2170 } 2171 2172 if (WEXITSTATUS(status)) { 2173 error_setg(errp, "child process has failed to suspend"); 2174 } 2175 2176 } 2177 2178 static void guest_suspend(SuspendMode mode, Error **errp) 2179 { 2180 Error *local_err = NULL; 2181 bool mode_supported = false; 2182 2183 if (systemd_supports_mode(mode, &local_err)) { 2184 mode_supported = true; 2185 systemd_suspend(mode, &local_err); 2186 } 2187 2188 if (!local_err) { 2189 return; 2190 } 2191 2192 error_free(local_err); 2193 local_err = NULL; 2194 2195 if (pmutils_supports_mode(mode, &local_err)) { 2196 mode_supported = true; 2197 pmutils_suspend(mode, &local_err); 2198 } 2199 2200 if (!local_err) { 2201 return; 2202 } 2203 2204 error_free(local_err); 2205 local_err = NULL; 2206 2207 if (linux_sys_state_supports_mode(mode, &local_err)) { 2208 mode_supported = true; 2209 linux_sys_state_suspend(mode, &local_err); 2210 } 2211 2212 if (!mode_supported) { 2213 error_free(local_err); 2214 error_setg(errp, 2215 "the requested suspend mode is not supported by the guest"); 2216 } else { 2217 error_propagate(errp, local_err); 2218 } 2219 } 2220 2221 void qmp_guest_suspend_disk(Error **errp) 2222 { 2223 guest_suspend(SUSPEND_MODE_DISK, errp); 2224 } 2225 2226 void qmp_guest_suspend_ram(Error **errp) 2227 { 2228 guest_suspend(SUSPEND_MODE_RAM, errp); 2229 } 2230 2231 void qmp_guest_suspend_hybrid(Error **errp) 2232 { 2233 guest_suspend(SUSPEND_MODE_HYBRID, errp); 2234 } 2235 2236 /* Transfer online/offline status between @vcpu and the guest system. 2237 * 2238 * On input either @errp or *@errp must be NULL. 2239 * 2240 * In system-to-@vcpu direction, the following @vcpu fields are accessed: 2241 * - R: vcpu->logical_id 2242 * - W: vcpu->online 2243 * - W: vcpu->can_offline 2244 * 2245 * In @vcpu-to-system direction, the following @vcpu fields are accessed: 2246 * - R: vcpu->logical_id 2247 * - R: vcpu->online 2248 * 2249 * Written members remain unmodified on error. 2250 */ 2251 static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu, 2252 char *dirpath, Error **errp) 2253 { 2254 int fd; 2255 int res; 2256 int dirfd; 2257 static const char fn[] = "online"; 2258 2259 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2260 if (dirfd == -1) { 2261 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2262 return; 2263 } 2264 2265 fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); 2266 if (fd == -1) { 2267 if (errno != ENOENT) { 2268 error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn); 2269 } else if (sys2vcpu) { 2270 vcpu->online = true; 2271 vcpu->can_offline = false; 2272 } else if (!vcpu->online) { 2273 error_setg(errp, "logical processor #%" PRId64 " can't be " 2274 "offlined", vcpu->logical_id); 2275 } /* otherwise pretend successful re-onlining */ 2276 } else { 2277 unsigned char status; 2278 2279 res = pread(fd, &status, 1, 0); 2280 if (res == -1) { 2281 error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn); 2282 } else if (res == 0) { 2283 error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, 2284 fn); 2285 } else if (sys2vcpu) { 2286 vcpu->online = (status != '0'); 2287 vcpu->can_offline = true; 2288 } else if (vcpu->online != (status != '0')) { 2289 status = '0' + vcpu->online; 2290 if (pwrite(fd, &status, 1, 0) == -1) { 2291 error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath, 2292 fn); 2293 } 2294 } /* otherwise pretend successful re-(on|off)-lining */ 2295 2296 res = close(fd); 2297 g_assert(res == 0); 2298 } 2299 2300 res = close(dirfd); 2301 g_assert(res == 0); 2302 } 2303 2304 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 2305 { 2306 GuestLogicalProcessorList *head, **tail; 2307 const char *cpu_dir = "/sys/devices/system/cpu"; 2308 const gchar *line; 2309 g_autoptr(GDir) cpu_gdir = NULL; 2310 Error *local_err = NULL; 2311 2312 head = NULL; 2313 tail = &head; 2314 cpu_gdir = g_dir_open(cpu_dir, 0, NULL); 2315 2316 if (cpu_gdir == NULL) { 2317 error_setg_errno(errp, errno, "failed to list entries: %s", cpu_dir); 2318 return NULL; 2319 } 2320 2321 while (local_err == NULL && (line = g_dir_read_name(cpu_gdir)) != NULL) { 2322 GuestLogicalProcessor *vcpu; 2323 int64_t id; 2324 if (sscanf(line, "cpu%" PRId64, &id)) { 2325 g_autofree char *path = g_strdup_printf("/sys/devices/system/cpu/" 2326 "cpu%" PRId64 "/", id); 2327 vcpu = g_malloc0(sizeof *vcpu); 2328 vcpu->logical_id = id; 2329 vcpu->has_can_offline = true; /* lolspeak ftw */ 2330 transfer_vcpu(vcpu, true, path, &local_err); 2331 QAPI_LIST_APPEND(tail, vcpu); 2332 } 2333 } 2334 2335 if (local_err == NULL) { 2336 /* there's no guest with zero VCPUs */ 2337 g_assert(head != NULL); 2338 return head; 2339 } 2340 2341 qapi_free_GuestLogicalProcessorList(head); 2342 error_propagate(errp, local_err); 2343 return NULL; 2344 } 2345 2346 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 2347 { 2348 int64_t processed; 2349 Error *local_err = NULL; 2350 2351 processed = 0; 2352 while (vcpus != NULL) { 2353 char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", 2354 vcpus->value->logical_id); 2355 2356 transfer_vcpu(vcpus->value, false, path, &local_err); 2357 g_free(path); 2358 if (local_err != NULL) { 2359 break; 2360 } 2361 ++processed; 2362 vcpus = vcpus->next; 2363 } 2364 2365 if (local_err != NULL) { 2366 if (processed == 0) { 2367 error_propagate(errp, local_err); 2368 } else { 2369 error_free(local_err); 2370 } 2371 } 2372 2373 return processed; 2374 } 2375 2376 void qmp_guest_set_user_password(const char *username, 2377 const char *password, 2378 bool crypted, 2379 Error **errp) 2380 { 2381 Error *local_err = NULL; 2382 char *passwd_path = NULL; 2383 pid_t pid; 2384 int status; 2385 int datafd[2] = { -1, -1 }; 2386 char *rawpasswddata = NULL; 2387 size_t rawpasswdlen; 2388 char *chpasswddata = NULL; 2389 size_t chpasswdlen; 2390 2391 rawpasswddata = (char *)qbase64_decode(password, -1, &rawpasswdlen, errp); 2392 if (!rawpasswddata) { 2393 return; 2394 } 2395 rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1); 2396 rawpasswddata[rawpasswdlen] = '\0'; 2397 2398 if (strchr(rawpasswddata, '\n')) { 2399 error_setg(errp, "forbidden characters in raw password"); 2400 goto out; 2401 } 2402 2403 if (strchr(username, '\n') || 2404 strchr(username, ':')) { 2405 error_setg(errp, "forbidden characters in username"); 2406 goto out; 2407 } 2408 2409 chpasswddata = g_strdup_printf("%s:%s\n", username, rawpasswddata); 2410 chpasswdlen = strlen(chpasswddata); 2411 2412 passwd_path = g_find_program_in_path("chpasswd"); 2413 2414 if (!passwd_path) { 2415 error_setg(errp, "cannot find 'passwd' program in PATH"); 2416 goto out; 2417 } 2418 2419 if (!g_unix_open_pipe(datafd, FD_CLOEXEC, NULL)) { 2420 error_setg(errp, "cannot create pipe FDs"); 2421 goto out; 2422 } 2423 2424 pid = fork(); 2425 if (pid == 0) { 2426 close(datafd[1]); 2427 /* child */ 2428 setsid(); 2429 dup2(datafd[0], 0); 2430 reopen_fd_to_null(1); 2431 reopen_fd_to_null(2); 2432 2433 if (crypted) { 2434 execl(passwd_path, "chpasswd", "-e", NULL); 2435 } else { 2436 execl(passwd_path, "chpasswd", NULL); 2437 } 2438 _exit(EXIT_FAILURE); 2439 } else if (pid < 0) { 2440 error_setg_errno(errp, errno, "failed to create child process"); 2441 goto out; 2442 } 2443 close(datafd[0]); 2444 datafd[0] = -1; 2445 2446 if (qemu_write_full(datafd[1], chpasswddata, chpasswdlen) != chpasswdlen) { 2447 error_setg_errno(errp, errno, "cannot write new account password"); 2448 goto out; 2449 } 2450 close(datafd[1]); 2451 datafd[1] = -1; 2452 2453 ga_wait_child(pid, &status, &local_err); 2454 if (local_err) { 2455 error_propagate(errp, local_err); 2456 goto out; 2457 } 2458 2459 if (!WIFEXITED(status)) { 2460 error_setg(errp, "child process has terminated abnormally"); 2461 goto out; 2462 } 2463 2464 if (WEXITSTATUS(status)) { 2465 error_setg(errp, "child process has failed to set user password"); 2466 goto out; 2467 } 2468 2469 out: 2470 g_free(chpasswddata); 2471 g_free(rawpasswddata); 2472 g_free(passwd_path); 2473 if (datafd[0] != -1) { 2474 close(datafd[0]); 2475 } 2476 if (datafd[1] != -1) { 2477 close(datafd[1]); 2478 } 2479 } 2480 2481 static void ga_read_sysfs_file(int dirfd, const char *pathname, char *buf, 2482 int size, Error **errp) 2483 { 2484 int fd; 2485 int res; 2486 2487 errno = 0; 2488 fd = openat(dirfd, pathname, O_RDONLY); 2489 if (fd == -1) { 2490 error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname); 2491 return; 2492 } 2493 2494 res = pread(fd, buf, size, 0); 2495 if (res == -1) { 2496 error_setg_errno(errp, errno, "pread sysfs file \"%s\"", pathname); 2497 } else if (res == 0) { 2498 error_setg(errp, "pread sysfs file \"%s\": unexpected EOF", pathname); 2499 } 2500 close(fd); 2501 } 2502 2503 static void ga_write_sysfs_file(int dirfd, const char *pathname, 2504 const char *buf, int size, Error **errp) 2505 { 2506 int fd; 2507 2508 errno = 0; 2509 fd = openat(dirfd, pathname, O_WRONLY); 2510 if (fd == -1) { 2511 error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname); 2512 return; 2513 } 2514 2515 if (pwrite(fd, buf, size, 0) == -1) { 2516 error_setg_errno(errp, errno, "pwrite sysfs file \"%s\"", pathname); 2517 } 2518 2519 close(fd); 2520 } 2521 2522 /* Transfer online/offline status between @mem_blk and the guest system. 2523 * 2524 * On input either @errp or *@errp must be NULL. 2525 * 2526 * In system-to-@mem_blk direction, the following @mem_blk fields are accessed: 2527 * - R: mem_blk->phys_index 2528 * - W: mem_blk->online 2529 * - W: mem_blk->can_offline 2530 * 2531 * In @mem_blk-to-system direction, the following @mem_blk fields are accessed: 2532 * - R: mem_blk->phys_index 2533 * - R: mem_blk->online 2534 *- R: mem_blk->can_offline 2535 * Written members remain unmodified on error. 2536 */ 2537 static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk, 2538 GuestMemoryBlockResponse *result, 2539 Error **errp) 2540 { 2541 char *dirpath; 2542 int dirfd; 2543 char *status; 2544 Error *local_err = NULL; 2545 2546 if (!sys2memblk) { 2547 DIR *dp; 2548 2549 if (!result) { 2550 error_setg(errp, "Internal error, 'result' should not be NULL"); 2551 return; 2552 } 2553 errno = 0; 2554 dp = opendir("/sys/devices/system/memory/"); 2555 /* if there is no 'memory' directory in sysfs, 2556 * we think this VM does not support online/offline memory block, 2557 * any other solution? 2558 */ 2559 if (!dp) { 2560 if (errno == ENOENT) { 2561 result->response = 2562 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED; 2563 } 2564 goto out1; 2565 } 2566 closedir(dp); 2567 } 2568 2569 dirpath = g_strdup_printf("/sys/devices/system/memory/memory%" PRId64 "/", 2570 mem_blk->phys_index); 2571 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2572 if (dirfd == -1) { 2573 if (sys2memblk) { 2574 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2575 } else { 2576 if (errno == ENOENT) { 2577 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_NOT_FOUND; 2578 } else { 2579 result->response = 2580 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2581 } 2582 } 2583 g_free(dirpath); 2584 goto out1; 2585 } 2586 g_free(dirpath); 2587 2588 status = g_malloc0(10); 2589 ga_read_sysfs_file(dirfd, "state", status, 10, &local_err); 2590 if (local_err) { 2591 /* treat with sysfs file that not exist in old kernel */ 2592 if (errno == ENOENT) { 2593 error_free(local_err); 2594 if (sys2memblk) { 2595 mem_blk->online = true; 2596 mem_blk->can_offline = false; 2597 } else if (!mem_blk->online) { 2598 result->response = 2599 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED; 2600 } 2601 } else { 2602 if (sys2memblk) { 2603 error_propagate(errp, local_err); 2604 } else { 2605 error_free(local_err); 2606 result->response = 2607 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2608 } 2609 } 2610 goto out2; 2611 } 2612 2613 if (sys2memblk) { 2614 char removable = '0'; 2615 2616 mem_blk->online = (strncmp(status, "online", 6) == 0); 2617 2618 ga_read_sysfs_file(dirfd, "removable", &removable, 1, &local_err); 2619 if (local_err) { 2620 /* if no 'removable' file, it doesn't support offline mem blk */ 2621 if (errno == ENOENT) { 2622 error_free(local_err); 2623 mem_blk->can_offline = false; 2624 } else { 2625 error_propagate(errp, local_err); 2626 } 2627 } else { 2628 mem_blk->can_offline = (removable != '0'); 2629 } 2630 } else { 2631 if (mem_blk->online != (strncmp(status, "online", 6) == 0)) { 2632 const char *new_state = mem_blk->online ? "online" : "offline"; 2633 2634 ga_write_sysfs_file(dirfd, "state", new_state, strlen(new_state), 2635 &local_err); 2636 if (local_err) { 2637 error_free(local_err); 2638 result->response = 2639 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2640 goto out2; 2641 } 2642 2643 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_SUCCESS; 2644 result->has_error_code = false; 2645 } /* otherwise pretend successful re-(on|off)-lining */ 2646 } 2647 g_free(status); 2648 close(dirfd); 2649 return; 2650 2651 out2: 2652 g_free(status); 2653 close(dirfd); 2654 out1: 2655 if (!sys2memblk) { 2656 result->has_error_code = true; 2657 result->error_code = errno; 2658 } 2659 } 2660 2661 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 2662 { 2663 GuestMemoryBlockList *head, **tail; 2664 Error *local_err = NULL; 2665 struct dirent *de; 2666 DIR *dp; 2667 2668 head = NULL; 2669 tail = &head; 2670 2671 dp = opendir("/sys/devices/system/memory/"); 2672 if (!dp) { 2673 /* it's ok if this happens to be a system that doesn't expose 2674 * memory blocks via sysfs, but otherwise we should report 2675 * an error 2676 */ 2677 if (errno != ENOENT) { 2678 error_setg_errno(errp, errno, "Can't open directory" 2679 "\"/sys/devices/system/memory/\""); 2680 } 2681 return NULL; 2682 } 2683 2684 /* Note: the phys_index of memory block may be discontinuous, 2685 * this is because a memblk is the unit of the Sparse Memory design, which 2686 * allows discontinuous memory ranges (ex. NUMA), so here we should 2687 * traverse the memory block directory. 2688 */ 2689 while ((de = readdir(dp)) != NULL) { 2690 GuestMemoryBlock *mem_blk; 2691 2692 if ((strncmp(de->d_name, "memory", 6) != 0) || 2693 !(de->d_type & DT_DIR)) { 2694 continue; 2695 } 2696 2697 mem_blk = g_malloc0(sizeof *mem_blk); 2698 /* The d_name is "memoryXXX", phys_index is block id, same as XXX */ 2699 mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10); 2700 mem_blk->has_can_offline = true; /* lolspeak ftw */ 2701 transfer_memory_block(mem_blk, true, NULL, &local_err); 2702 if (local_err) { 2703 break; 2704 } 2705 2706 QAPI_LIST_APPEND(tail, mem_blk); 2707 } 2708 2709 closedir(dp); 2710 if (local_err == NULL) { 2711 /* there's no guest with zero memory blocks */ 2712 if (head == NULL) { 2713 error_setg(errp, "guest reported zero memory blocks!"); 2714 } 2715 return head; 2716 } 2717 2718 qapi_free_GuestMemoryBlockList(head); 2719 error_propagate(errp, local_err); 2720 return NULL; 2721 } 2722 2723 GuestMemoryBlockResponseList * 2724 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 2725 { 2726 GuestMemoryBlockResponseList *head, **tail; 2727 Error *local_err = NULL; 2728 2729 head = NULL; 2730 tail = &head; 2731 2732 while (mem_blks != NULL) { 2733 GuestMemoryBlockResponse *result; 2734 GuestMemoryBlock *current_mem_blk = mem_blks->value; 2735 2736 result = g_malloc0(sizeof(*result)); 2737 result->phys_index = current_mem_blk->phys_index; 2738 transfer_memory_block(current_mem_blk, false, result, &local_err); 2739 if (local_err) { /* should never happen */ 2740 goto err; 2741 } 2742 2743 QAPI_LIST_APPEND(tail, result); 2744 mem_blks = mem_blks->next; 2745 } 2746 2747 return head; 2748 err: 2749 qapi_free_GuestMemoryBlockResponseList(head); 2750 error_propagate(errp, local_err); 2751 return NULL; 2752 } 2753 2754 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 2755 { 2756 Error *local_err = NULL; 2757 char *dirpath; 2758 int dirfd; 2759 char *buf; 2760 GuestMemoryBlockInfo *info; 2761 2762 dirpath = g_strdup_printf("/sys/devices/system/memory/"); 2763 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2764 if (dirfd == -1) { 2765 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2766 g_free(dirpath); 2767 return NULL; 2768 } 2769 g_free(dirpath); 2770 2771 buf = g_malloc0(20); 2772 ga_read_sysfs_file(dirfd, "block_size_bytes", buf, 20, &local_err); 2773 close(dirfd); 2774 if (local_err) { 2775 g_free(buf); 2776 error_propagate(errp, local_err); 2777 return NULL; 2778 } 2779 2780 info = g_new0(GuestMemoryBlockInfo, 1); 2781 info->size = strtol(buf, NULL, 16); /* the unit is bytes */ 2782 2783 g_free(buf); 2784 2785 return info; 2786 } 2787 2788 #define MAX_NAME_LEN 128 2789 static GuestDiskStatsInfoList *guest_get_diskstats(Error **errp) 2790 { 2791 #ifdef CONFIG_LINUX 2792 GuestDiskStatsInfoList *head = NULL, **tail = &head; 2793 const char *diskstats = "/proc/diskstats"; 2794 FILE *fp; 2795 size_t n; 2796 char *line = NULL; 2797 2798 fp = fopen(diskstats, "r"); 2799 if (fp == NULL) { 2800 error_setg_errno(errp, errno, "open(\"%s\")", diskstats); 2801 return NULL; 2802 } 2803 2804 while (getline(&line, &n, fp) != -1) { 2805 g_autofree GuestDiskStatsInfo *diskstatinfo = NULL; 2806 g_autofree GuestDiskStats *diskstat = NULL; 2807 char dev_name[MAX_NAME_LEN]; 2808 unsigned int ios_pgr, tot_ticks, rq_ticks, wr_ticks, dc_ticks, fl_ticks; 2809 unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios; 2810 unsigned long wr_merges, rd_sec_or_wr_ios, wr_sec; 2811 unsigned long dc_ios, dc_merges, dc_sec, fl_ios; 2812 unsigned int major, minor; 2813 int i; 2814 2815 i = sscanf(line, "%u %u %s %lu %lu %lu" 2816 "%lu %lu %lu %lu %u %u %u %u" 2817 "%lu %lu %lu %u %lu %u", 2818 &major, &minor, dev_name, 2819 &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios, 2820 &rd_ticks_or_wr_sec, &wr_ios, &wr_merges, &wr_sec, 2821 &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks, 2822 &dc_ios, &dc_merges, &dc_sec, &dc_ticks, 2823 &fl_ios, &fl_ticks); 2824 2825 if (i < 7) { 2826 continue; 2827 } 2828 2829 diskstatinfo = g_new0(GuestDiskStatsInfo, 1); 2830 diskstatinfo->name = g_strdup(dev_name); 2831 diskstatinfo->major = major; 2832 diskstatinfo->minor = minor; 2833 2834 diskstat = g_new0(GuestDiskStats, 1); 2835 if (i == 7) { 2836 diskstat->has_read_ios = true; 2837 diskstat->read_ios = rd_ios; 2838 diskstat->has_read_sectors = true; 2839 diskstat->read_sectors = rd_merges_or_rd_sec; 2840 diskstat->has_write_ios = true; 2841 diskstat->write_ios = rd_sec_or_wr_ios; 2842 diskstat->has_write_sectors = true; 2843 diskstat->write_sectors = rd_ticks_or_wr_sec; 2844 } 2845 if (i >= 14) { 2846 diskstat->has_read_ios = true; 2847 diskstat->read_ios = rd_ios; 2848 diskstat->has_read_sectors = true; 2849 diskstat->read_sectors = rd_sec_or_wr_ios; 2850 diskstat->has_read_merges = true; 2851 diskstat->read_merges = rd_merges_or_rd_sec; 2852 diskstat->has_read_ticks = true; 2853 diskstat->read_ticks = rd_ticks_or_wr_sec; 2854 diskstat->has_write_ios = true; 2855 diskstat->write_ios = wr_ios; 2856 diskstat->has_write_sectors = true; 2857 diskstat->write_sectors = wr_sec; 2858 diskstat->has_write_merges = true; 2859 diskstat->write_merges = wr_merges; 2860 diskstat->has_write_ticks = true; 2861 diskstat->write_ticks = wr_ticks; 2862 diskstat->has_ios_pgr = true; 2863 diskstat->ios_pgr = ios_pgr; 2864 diskstat->has_total_ticks = true; 2865 diskstat->total_ticks = tot_ticks; 2866 diskstat->has_weight_ticks = true; 2867 diskstat->weight_ticks = rq_ticks; 2868 } 2869 if (i >= 18) { 2870 diskstat->has_discard_ios = true; 2871 diskstat->discard_ios = dc_ios; 2872 diskstat->has_discard_merges = true; 2873 diskstat->discard_merges = dc_merges; 2874 diskstat->has_discard_sectors = true; 2875 diskstat->discard_sectors = dc_sec; 2876 diskstat->has_discard_ticks = true; 2877 diskstat->discard_ticks = dc_ticks; 2878 } 2879 if (i >= 20) { 2880 diskstat->has_flush_ios = true; 2881 diskstat->flush_ios = fl_ios; 2882 diskstat->has_flush_ticks = true; 2883 diskstat->flush_ticks = fl_ticks; 2884 } 2885 2886 diskstatinfo->stats = g_steal_pointer(&diskstat); 2887 QAPI_LIST_APPEND(tail, diskstatinfo); 2888 diskstatinfo = NULL; 2889 } 2890 free(line); 2891 fclose(fp); 2892 return head; 2893 #else 2894 g_debug("disk stats reporting available only for Linux"); 2895 return NULL; 2896 #endif 2897 } 2898 2899 GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp) 2900 { 2901 return guest_get_diskstats(errp); 2902 } 2903 2904 GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp) 2905 { 2906 GuestCpuStatsList *head = NULL, **tail = &head; 2907 const char *cpustats = "/proc/stat"; 2908 int clk_tck = sysconf(_SC_CLK_TCK); 2909 FILE *fp; 2910 size_t n; 2911 char *line = NULL; 2912 2913 fp = fopen(cpustats, "r"); 2914 if (fp == NULL) { 2915 error_setg_errno(errp, errno, "open(\"%s\")", cpustats); 2916 return NULL; 2917 } 2918 2919 while (getline(&line, &n, fp) != -1) { 2920 GuestCpuStats *cpustat = NULL; 2921 GuestLinuxCpuStats *linuxcpustat; 2922 int i; 2923 unsigned long user, system, idle, iowait, irq, softirq, steal, guest; 2924 unsigned long nice, guest_nice; 2925 char name[64]; 2926 2927 i = sscanf(line, "%s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", 2928 name, &user, &nice, &system, &idle, &iowait, &irq, &softirq, 2929 &steal, &guest, &guest_nice); 2930 2931 /* drop "cpu 1 2 3 ...", get "cpuX 1 2 3 ..." only */ 2932 if ((i == EOF) || strncmp(name, "cpu", 3) || (name[3] == '\0')) { 2933 continue; 2934 } 2935 2936 if (i < 5) { 2937 slog("Parsing cpu stat from %s failed, see \"man proc\"", cpustats); 2938 break; 2939 } 2940 2941 cpustat = g_new0(GuestCpuStats, 1); 2942 cpustat->type = GUEST_CPU_STATS_TYPE_LINUX; 2943 2944 linuxcpustat = &cpustat->u.q_linux; 2945 linuxcpustat->cpu = atoi(&name[3]); 2946 linuxcpustat->user = user * 1000 / clk_tck; 2947 linuxcpustat->nice = nice * 1000 / clk_tck; 2948 linuxcpustat->system = system * 1000 / clk_tck; 2949 linuxcpustat->idle = idle * 1000 / clk_tck; 2950 2951 if (i > 5) { 2952 linuxcpustat->has_iowait = true; 2953 linuxcpustat->iowait = iowait * 1000 / clk_tck; 2954 } 2955 2956 if (i > 6) { 2957 linuxcpustat->has_irq = true; 2958 linuxcpustat->irq = irq * 1000 / clk_tck; 2959 linuxcpustat->has_softirq = true; 2960 linuxcpustat->softirq = softirq * 1000 / clk_tck; 2961 } 2962 2963 if (i > 8) { 2964 linuxcpustat->has_steal = true; 2965 linuxcpustat->steal = steal * 1000 / clk_tck; 2966 } 2967 2968 if (i > 9) { 2969 linuxcpustat->has_guest = true; 2970 linuxcpustat->guest = guest * 1000 / clk_tck; 2971 } 2972 2973 if (i > 10) { 2974 linuxcpustat->has_guest = true; 2975 linuxcpustat->guest = guest * 1000 / clk_tck; 2976 linuxcpustat->has_guestnice = true; 2977 linuxcpustat->guestnice = guest_nice * 1000 / clk_tck; 2978 } 2979 2980 QAPI_LIST_APPEND(tail, cpustat); 2981 } 2982 2983 free(line); 2984 fclose(fp); 2985 return head; 2986 } 2987 2988 #else /* defined(__linux__) */ 2989 2990 void qmp_guest_suspend_disk(Error **errp) 2991 { 2992 error_setg(errp, QERR_UNSUPPORTED); 2993 } 2994 2995 void qmp_guest_suspend_ram(Error **errp) 2996 { 2997 error_setg(errp, QERR_UNSUPPORTED); 2998 } 2999 3000 void qmp_guest_suspend_hybrid(Error **errp) 3001 { 3002 error_setg(errp, QERR_UNSUPPORTED); 3003 } 3004 3005 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 3006 { 3007 error_setg(errp, QERR_UNSUPPORTED); 3008 return NULL; 3009 } 3010 3011 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 3012 { 3013 error_setg(errp, QERR_UNSUPPORTED); 3014 return -1; 3015 } 3016 3017 void qmp_guest_set_user_password(const char *username, 3018 const char *password, 3019 bool crypted, 3020 Error **errp) 3021 { 3022 error_setg(errp, QERR_UNSUPPORTED); 3023 } 3024 3025 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 3026 { 3027 error_setg(errp, QERR_UNSUPPORTED); 3028 return NULL; 3029 } 3030 3031 GuestMemoryBlockResponseList * 3032 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 3033 { 3034 error_setg(errp, QERR_UNSUPPORTED); 3035 return NULL; 3036 } 3037 3038 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 3039 { 3040 error_setg(errp, QERR_UNSUPPORTED); 3041 return NULL; 3042 } 3043 3044 #endif 3045 3046 #ifdef HAVE_GETIFADDRS 3047 static GuestNetworkInterface * 3048 guest_find_interface(GuestNetworkInterfaceList *head, 3049 const char *name) 3050 { 3051 for (; head; head = head->next) { 3052 if (strcmp(head->value->name, name) == 0) { 3053 return head->value; 3054 } 3055 } 3056 3057 return NULL; 3058 } 3059 3060 static int guest_get_network_stats(const char *name, 3061 GuestNetworkInterfaceStat *stats) 3062 { 3063 #ifdef CONFIG_LINUX 3064 int name_len; 3065 char const *devinfo = "/proc/net/dev"; 3066 FILE *fp; 3067 char *line = NULL, *colon; 3068 size_t n = 0; 3069 fp = fopen(devinfo, "r"); 3070 if (!fp) { 3071 g_debug("failed to open network stats %s: %s", devinfo, 3072 g_strerror(errno)); 3073 return -1; 3074 } 3075 name_len = strlen(name); 3076 while (getline(&line, &n, fp) != -1) { 3077 long long dummy; 3078 long long rx_bytes; 3079 long long rx_packets; 3080 long long rx_errs; 3081 long long rx_dropped; 3082 long long tx_bytes; 3083 long long tx_packets; 3084 long long tx_errs; 3085 long long tx_dropped; 3086 char *trim_line; 3087 trim_line = g_strchug(line); 3088 if (trim_line[0] == '\0') { 3089 continue; 3090 } 3091 colon = strchr(trim_line, ':'); 3092 if (!colon) { 3093 continue; 3094 } 3095 if (colon - name_len == trim_line && 3096 strncmp(trim_line, name, name_len) == 0) { 3097 if (sscanf(colon + 1, 3098 "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", 3099 &rx_bytes, &rx_packets, &rx_errs, &rx_dropped, 3100 &dummy, &dummy, &dummy, &dummy, 3101 &tx_bytes, &tx_packets, &tx_errs, &tx_dropped, 3102 &dummy, &dummy, &dummy, &dummy) != 16) { 3103 continue; 3104 } 3105 stats->rx_bytes = rx_bytes; 3106 stats->rx_packets = rx_packets; 3107 stats->rx_errs = rx_errs; 3108 stats->rx_dropped = rx_dropped; 3109 stats->tx_bytes = tx_bytes; 3110 stats->tx_packets = tx_packets; 3111 stats->tx_errs = tx_errs; 3112 stats->tx_dropped = tx_dropped; 3113 fclose(fp); 3114 g_free(line); 3115 return 0; 3116 } 3117 } 3118 fclose(fp); 3119 g_free(line); 3120 g_debug("/proc/net/dev: Interface '%s' not found", name); 3121 #else /* !CONFIG_LINUX */ 3122 g_debug("Network stats reporting available only for Linux"); 3123 #endif /* !CONFIG_LINUX */ 3124 return -1; 3125 } 3126 3127 /* 3128 * Build information about guest interfaces 3129 */ 3130 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 3131 { 3132 GuestNetworkInterfaceList *head = NULL, **tail = &head; 3133 struct ifaddrs *ifap, *ifa; 3134 3135 if (getifaddrs(&ifap) < 0) { 3136 error_setg_errno(errp, errno, "getifaddrs failed"); 3137 goto error; 3138 } 3139 3140 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 3141 GuestNetworkInterface *info; 3142 GuestIpAddressList **address_tail; 3143 GuestIpAddress *address_item = NULL; 3144 GuestNetworkInterfaceStat *interface_stat = NULL; 3145 char addr4[INET_ADDRSTRLEN]; 3146 char addr6[INET6_ADDRSTRLEN]; 3147 int sock; 3148 struct ifreq ifr; 3149 unsigned char *mac_addr; 3150 void *p; 3151 3152 g_debug("Processing %s interface", ifa->ifa_name); 3153 3154 info = guest_find_interface(head, ifa->ifa_name); 3155 3156 if (!info) { 3157 info = g_malloc0(sizeof(*info)); 3158 info->name = g_strdup(ifa->ifa_name); 3159 3160 QAPI_LIST_APPEND(tail, info); 3161 } 3162 3163 if (!info->has_hardware_address) { 3164 /* we haven't obtained HW address yet */ 3165 sock = socket(PF_INET, SOCK_STREAM, 0); 3166 if (sock == -1) { 3167 error_setg_errno(errp, errno, "failed to create socket"); 3168 goto error; 3169 } 3170 3171 memset(&ifr, 0, sizeof(ifr)); 3172 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->name); 3173 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { 3174 /* 3175 * We can't get the hw addr of this interface, but that's not a 3176 * fatal error. Don't set info->hardware_address, but keep 3177 * going. 3178 */ 3179 if (errno == EADDRNOTAVAIL) { 3180 /* The interface doesn't have a hw addr (e.g. loopback). */ 3181 g_debug("failed to get MAC address of %s: %s", 3182 ifa->ifa_name, strerror(errno)); 3183 } else{ 3184 g_warning("failed to get MAC address of %s: %s", 3185 ifa->ifa_name, strerror(errno)); 3186 } 3187 3188 } else { 3189 #ifdef CONFIG_SOLARIS 3190 mac_addr = (unsigned char *) &ifr.ifr_addr.sa_data; 3191 #else 3192 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 3193 #endif 3194 info->hardware_address = 3195 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", 3196 (int) mac_addr[0], (int) mac_addr[1], 3197 (int) mac_addr[2], (int) mac_addr[3], 3198 (int) mac_addr[4], (int) mac_addr[5]); 3199 3200 info->has_hardware_address = true; 3201 } 3202 close(sock); 3203 } 3204 3205 if (ifa->ifa_addr && 3206 ifa->ifa_addr->sa_family == AF_INET) { 3207 /* interface with IPv4 address */ 3208 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; 3209 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) { 3210 error_setg_errno(errp, errno, "inet_ntop failed"); 3211 goto error; 3212 } 3213 3214 address_item = g_malloc0(sizeof(*address_item)); 3215 address_item->ip_address = g_strdup(addr4); 3216 address_item->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4; 3217 3218 if (ifa->ifa_netmask) { 3219 /* Count the number of set bits in netmask. 3220 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 3221 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; 3222 address_item->prefix = ctpop32(((uint32_t *) p)[0]); 3223 } 3224 } else if (ifa->ifa_addr && 3225 ifa->ifa_addr->sa_family == AF_INET6) { 3226 /* interface with IPv6 address */ 3227 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; 3228 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) { 3229 error_setg_errno(errp, errno, "inet_ntop failed"); 3230 goto error; 3231 } 3232 3233 address_item = g_malloc0(sizeof(*address_item)); 3234 address_item->ip_address = g_strdup(addr6); 3235 address_item->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6; 3236 3237 if (ifa->ifa_netmask) { 3238 /* Count the number of set bits in netmask. 3239 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 3240 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; 3241 address_item->prefix = 3242 ctpop32(((uint32_t *) p)[0]) + 3243 ctpop32(((uint32_t *) p)[1]) + 3244 ctpop32(((uint32_t *) p)[2]) + 3245 ctpop32(((uint32_t *) p)[3]); 3246 } 3247 } 3248 3249 if (!address_item) { 3250 continue; 3251 } 3252 3253 address_tail = &info->ip_addresses; 3254 while (*address_tail) { 3255 address_tail = &(*address_tail)->next; 3256 } 3257 QAPI_LIST_APPEND(address_tail, address_item); 3258 3259 info->has_ip_addresses = true; 3260 3261 if (!info->has_statistics) { 3262 interface_stat = g_malloc0(sizeof(*interface_stat)); 3263 if (guest_get_network_stats(info->name, interface_stat) == -1) { 3264 info->has_statistics = false; 3265 g_free(interface_stat); 3266 } else { 3267 info->statistics = interface_stat; 3268 info->has_statistics = true; 3269 } 3270 } 3271 } 3272 3273 freeifaddrs(ifap); 3274 return head; 3275 3276 error: 3277 freeifaddrs(ifap); 3278 qapi_free_GuestNetworkInterfaceList(head); 3279 return NULL; 3280 } 3281 3282 #else 3283 3284 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 3285 { 3286 error_setg(errp, QERR_UNSUPPORTED); 3287 return NULL; 3288 } 3289 3290 #endif /* HAVE_GETIFADDRS */ 3291 3292 #if !defined(CONFIG_FSFREEZE) 3293 3294 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 3295 { 3296 error_setg(errp, QERR_UNSUPPORTED); 3297 return NULL; 3298 } 3299 3300 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 3301 { 3302 error_setg(errp, QERR_UNSUPPORTED); 3303 3304 return 0; 3305 } 3306 3307 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 3308 { 3309 error_setg(errp, QERR_UNSUPPORTED); 3310 3311 return 0; 3312 } 3313 3314 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 3315 strList *mountpoints, 3316 Error **errp) 3317 { 3318 error_setg(errp, QERR_UNSUPPORTED); 3319 3320 return 0; 3321 } 3322 3323 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 3324 { 3325 error_setg(errp, QERR_UNSUPPORTED); 3326 3327 return 0; 3328 } 3329 3330 GuestDiskInfoList *qmp_guest_get_disks(Error **errp) 3331 { 3332 error_setg(errp, QERR_UNSUPPORTED); 3333 return NULL; 3334 } 3335 3336 GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp) 3337 { 3338 error_setg(errp, QERR_UNSUPPORTED); 3339 return NULL; 3340 } 3341 3342 GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp) 3343 { 3344 error_setg(errp, QERR_UNSUPPORTED); 3345 return NULL; 3346 } 3347 3348 #endif /* CONFIG_FSFREEZE */ 3349 3350 #if !defined(CONFIG_FSTRIM) 3351 GuestFilesystemTrimResponse * 3352 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 3353 { 3354 error_setg(errp, QERR_UNSUPPORTED); 3355 return NULL; 3356 } 3357 #endif 3358 3359 /* add unsupported commands to the blacklist */ 3360 GList *ga_command_blacklist_init(GList *blacklist) 3361 { 3362 #if !defined(__linux__) 3363 { 3364 const char *list[] = { 3365 "guest-suspend-disk", "guest-suspend-ram", 3366 "guest-suspend-hybrid", "guest-get-vcpus", "guest-set-vcpus", 3367 "guest-get-memory-blocks", "guest-set-memory-blocks", 3368 "guest-get-memory-block-size", "guest-get-memory-block-info", 3369 NULL}; 3370 char **p = (char **)list; 3371 3372 while (*p) { 3373 blacklist = g_list_append(blacklist, g_strdup(*p++)); 3374 } 3375 } 3376 #endif 3377 3378 #if !defined(HAVE_GETIFADDRS) 3379 blacklist = g_list_append(blacklist, 3380 g_strdup("guest-network-get-interfaces")); 3381 #endif 3382 3383 #if !defined(CONFIG_FSFREEZE) 3384 { 3385 const char *list[] = { 3386 "guest-get-fsinfo", "guest-fsfreeze-status", 3387 "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list", 3388 "guest-fsfreeze-thaw", "guest-get-fsinfo", 3389 "guest-get-disks", NULL}; 3390 char **p = (char **)list; 3391 3392 while (*p) { 3393 blacklist = g_list_append(blacklist, g_strdup(*p++)); 3394 } 3395 } 3396 #endif 3397 3398 #if !defined(CONFIG_FSTRIM) 3399 blacklist = g_list_append(blacklist, g_strdup("guest-fstrim")); 3400 #endif 3401 3402 blacklist = g_list_append(blacklist, g_strdup("guest-get-devices")); 3403 3404 return blacklist; 3405 } 3406 3407 /* register init/cleanup routines for stateful command groups */ 3408 void ga_command_state_init(GAState *s, GACommandState *cs) 3409 { 3410 #if defined(CONFIG_FSFREEZE) 3411 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); 3412 #endif 3413 } 3414 3415 #ifdef HAVE_UTMPX 3416 3417 #define QGA_MICRO_SECOND_TO_SECOND 1000000 3418 3419 static double ga_get_login_time(struct utmpx *user_info) 3420 { 3421 double seconds = (double)user_info->ut_tv.tv_sec; 3422 double useconds = (double)user_info->ut_tv.tv_usec; 3423 useconds /= QGA_MICRO_SECOND_TO_SECOND; 3424 return seconds + useconds; 3425 } 3426 3427 GuestUserList *qmp_guest_get_users(Error **errp) 3428 { 3429 GHashTable *cache = NULL; 3430 GuestUserList *head = NULL, **tail = &head; 3431 struct utmpx *user_info = NULL; 3432 gpointer value = NULL; 3433 GuestUser *user = NULL; 3434 double login_time = 0; 3435 3436 cache = g_hash_table_new(g_str_hash, g_str_equal); 3437 setutxent(); 3438 3439 for (;;) { 3440 user_info = getutxent(); 3441 if (user_info == NULL) { 3442 break; 3443 } else if (user_info->ut_type != USER_PROCESS) { 3444 continue; 3445 } else if (g_hash_table_contains(cache, user_info->ut_user)) { 3446 value = g_hash_table_lookup(cache, user_info->ut_user); 3447 user = (GuestUser *)value; 3448 login_time = ga_get_login_time(user_info); 3449 /* We're ensuring the earliest login time to be sent */ 3450 if (login_time < user->login_time) { 3451 user->login_time = login_time; 3452 } 3453 continue; 3454 } 3455 3456 user = g_new0(GuestUser, 1); 3457 user->user = g_strdup(user_info->ut_user); 3458 user->login_time = ga_get_login_time(user_info); 3459 3460 g_hash_table_insert(cache, user->user, user); 3461 3462 QAPI_LIST_APPEND(tail, user); 3463 } 3464 endutxent(); 3465 g_hash_table_destroy(cache); 3466 return head; 3467 } 3468 3469 #else 3470 3471 GuestUserList *qmp_guest_get_users(Error **errp) 3472 { 3473 error_setg(errp, QERR_UNSUPPORTED); 3474 return NULL; 3475 } 3476 3477 #endif 3478 3479 /* Replace escaped special characters with theire real values. The replacement 3480 * is done in place -- returned value is in the original string. 3481 */ 3482 static void ga_osrelease_replace_special(gchar *value) 3483 { 3484 gchar *p, *p2, quote; 3485 3486 /* Trim the string at first space or semicolon if it is not enclosed in 3487 * single or double quotes. */ 3488 if ((value[0] != '"') || (value[0] == '\'')) { 3489 p = strchr(value, ' '); 3490 if (p != NULL) { 3491 *p = 0; 3492 } 3493 p = strchr(value, ';'); 3494 if (p != NULL) { 3495 *p = 0; 3496 } 3497 return; 3498 } 3499 3500 quote = value[0]; 3501 p2 = value; 3502 p = value + 1; 3503 while (*p != 0) { 3504 if (*p == '\\') { 3505 p++; 3506 switch (*p) { 3507 case '$': 3508 case '\'': 3509 case '"': 3510 case '\\': 3511 case '`': 3512 break; 3513 default: 3514 /* Keep literal backslash followed by whatever is there */ 3515 p--; 3516 break; 3517 } 3518 } else if (*p == quote) { 3519 *p2 = 0; 3520 break; 3521 } 3522 *(p2++) = *(p++); 3523 } 3524 } 3525 3526 static GKeyFile *ga_parse_osrelease(const char *fname) 3527 { 3528 gchar *content = NULL; 3529 gchar *content2 = NULL; 3530 GError *err = NULL; 3531 GKeyFile *keys = g_key_file_new(); 3532 const char *group = "[os-release]\n"; 3533 3534 if (!g_file_get_contents(fname, &content, NULL, &err)) { 3535 slog("failed to read '%s', error: %s", fname, err->message); 3536 goto fail; 3537 } 3538 3539 if (!g_utf8_validate(content, -1, NULL)) { 3540 slog("file is not utf-8 encoded: %s", fname); 3541 goto fail; 3542 } 3543 content2 = g_strdup_printf("%s%s", group, content); 3544 3545 if (!g_key_file_load_from_data(keys, content2, -1, G_KEY_FILE_NONE, 3546 &err)) { 3547 slog("failed to parse file '%s', error: %s", fname, err->message); 3548 goto fail; 3549 } 3550 3551 g_free(content); 3552 g_free(content2); 3553 return keys; 3554 3555 fail: 3556 g_error_free(err); 3557 g_free(content); 3558 g_free(content2); 3559 g_key_file_free(keys); 3560 return NULL; 3561 } 3562 3563 GuestOSInfo *qmp_guest_get_osinfo(Error **errp) 3564 { 3565 GuestOSInfo *info = NULL; 3566 struct utsname kinfo; 3567 GKeyFile *osrelease = NULL; 3568 const char *qga_os_release = g_getenv("QGA_OS_RELEASE"); 3569 3570 info = g_new0(GuestOSInfo, 1); 3571 3572 if (uname(&kinfo) != 0) { 3573 error_setg_errno(errp, errno, "uname failed"); 3574 } else { 3575 info->has_kernel_version = true; 3576 info->kernel_version = g_strdup(kinfo.version); 3577 info->has_kernel_release = true; 3578 info->kernel_release = g_strdup(kinfo.release); 3579 info->has_machine = true; 3580 info->machine = g_strdup(kinfo.machine); 3581 } 3582 3583 if (qga_os_release != NULL) { 3584 osrelease = ga_parse_osrelease(qga_os_release); 3585 } else { 3586 osrelease = ga_parse_osrelease("/etc/os-release"); 3587 if (osrelease == NULL) { 3588 osrelease = ga_parse_osrelease("/usr/lib/os-release"); 3589 } 3590 } 3591 3592 if (osrelease != NULL) { 3593 char *value; 3594 3595 #define GET_FIELD(field, osfield) do { \ 3596 value = g_key_file_get_value(osrelease, "os-release", osfield, NULL); \ 3597 if (value != NULL) { \ 3598 ga_osrelease_replace_special(value); \ 3599 info->has_ ## field = true; \ 3600 info->field = value; \ 3601 } \ 3602 } while (0) 3603 GET_FIELD(id, "ID"); 3604 GET_FIELD(name, "NAME"); 3605 GET_FIELD(pretty_name, "PRETTY_NAME"); 3606 GET_FIELD(version, "VERSION"); 3607 GET_FIELD(version_id, "VERSION_ID"); 3608 GET_FIELD(variant, "VARIANT"); 3609 GET_FIELD(variant_id, "VARIANT_ID"); 3610 #undef GET_FIELD 3611 3612 g_key_file_free(osrelease); 3613 } 3614 3615 return info; 3616 } 3617 3618 GuestDeviceInfoList *qmp_guest_get_devices(Error **errp) 3619 { 3620 error_setg(errp, QERR_UNSUPPORTED); 3621 3622 return NULL; 3623 } 3624 3625 #ifndef HOST_NAME_MAX 3626 # ifdef _POSIX_HOST_NAME_MAX 3627 # define HOST_NAME_MAX _POSIX_HOST_NAME_MAX 3628 # else 3629 # define HOST_NAME_MAX 255 3630 # endif 3631 #endif 3632 3633 char *qga_get_host_name(Error **errp) 3634 { 3635 long len = -1; 3636 g_autofree char *hostname = NULL; 3637 3638 #ifdef _SC_HOST_NAME_MAX 3639 len = sysconf(_SC_HOST_NAME_MAX); 3640 #endif /* _SC_HOST_NAME_MAX */ 3641 3642 if (len < 0) { 3643 len = HOST_NAME_MAX; 3644 } 3645 3646 /* Unfortunately, gethostname() below does not guarantee a 3647 * NULL terminated string. Therefore, allocate one byte more 3648 * to be sure. */ 3649 hostname = g_new0(char, len + 1); 3650 3651 if (gethostname(hostname, len) < 0) { 3652 error_setg_errno(errp, errno, 3653 "cannot get hostname"); 3654 return NULL; 3655 } 3656 3657 return g_steal_pointer(&hostname); 3658 } 3659