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 error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); 1211 return; 1212 } 1213 1214 if (!fs->name) { 1215 fs->name = g_path_get_basename(syspath); 1216 } 1217 1218 g_debug(" parse sysfs path '%s'", syspath); 1219 is_virtual = is_disk_virtual(syspath, errp); 1220 if (*errp != NULL) { 1221 return; 1222 } 1223 if (is_virtual) { 1224 build_guest_fsinfo_for_virtual_device(syspath, fs, errp); 1225 } else { 1226 build_guest_fsinfo_for_real_device(syspath, fs, errp); 1227 } 1228 } 1229 1230 #ifdef CONFIG_LIBUDEV 1231 1232 /* 1233 * Wrapper around build_guest_fsinfo_for_device() for getting just 1234 * the disk address. 1235 */ 1236 static GuestDiskAddress *get_disk_address(const char *syspath, Error **errp) 1237 { 1238 g_autoptr(GuestFilesystemInfo) fs = NULL; 1239 1240 fs = g_new0(GuestFilesystemInfo, 1); 1241 build_guest_fsinfo_for_device(syspath, fs, errp); 1242 if (fs->disk != NULL) { 1243 return g_steal_pointer(&fs->disk->value); 1244 } 1245 return NULL; 1246 } 1247 1248 static char *get_alias_for_syspath(const char *syspath) 1249 { 1250 struct udev *udev = NULL; 1251 struct udev_device *udevice = NULL; 1252 char *ret = NULL; 1253 1254 udev = udev_new(); 1255 if (udev == NULL) { 1256 g_debug("failed to query udev"); 1257 goto out; 1258 } 1259 udevice = udev_device_new_from_syspath(udev, syspath); 1260 if (udevice == NULL) { 1261 g_debug("failed to query udev for path: %s", syspath); 1262 goto out; 1263 } else { 1264 const char *alias = udev_device_get_property_value( 1265 udevice, "DM_NAME"); 1266 /* 1267 * NULL means there was an error and empty string means there is no 1268 * alias. In case of no alias we return NULL instead of empty string. 1269 */ 1270 if (alias == NULL) { 1271 g_debug("failed to query udev for device alias for: %s", 1272 syspath); 1273 } else if (*alias != 0) { 1274 ret = g_strdup(alias); 1275 } 1276 } 1277 1278 out: 1279 udev_unref(udev); 1280 udev_device_unref(udevice); 1281 return ret; 1282 } 1283 1284 static char *get_device_for_syspath(const char *syspath) 1285 { 1286 struct udev *udev = NULL; 1287 struct udev_device *udevice = NULL; 1288 char *ret = NULL; 1289 1290 udev = udev_new(); 1291 if (udev == NULL) { 1292 g_debug("failed to query udev"); 1293 goto out; 1294 } 1295 udevice = udev_device_new_from_syspath(udev, syspath); 1296 if (udevice == NULL) { 1297 g_debug("failed to query udev for path: %s", syspath); 1298 goto out; 1299 } else { 1300 ret = g_strdup(udev_device_get_devnode(udevice)); 1301 } 1302 1303 out: 1304 udev_unref(udev); 1305 udev_device_unref(udevice); 1306 return ret; 1307 } 1308 1309 static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk) 1310 { 1311 g_autofree char *deps_dir = NULL; 1312 const gchar *dep; 1313 GDir *dp_deps = NULL; 1314 1315 /* List dependent disks */ 1316 deps_dir = g_strdup_printf("%s/slaves", disk_dir); 1317 g_debug(" listing entries in: %s", deps_dir); 1318 dp_deps = g_dir_open(deps_dir, 0, NULL); 1319 if (dp_deps == NULL) { 1320 g_debug("failed to list entries in %s", deps_dir); 1321 return; 1322 } 1323 disk->has_dependencies = true; 1324 while ((dep = g_dir_read_name(dp_deps)) != NULL) { 1325 g_autofree char *dep_dir = NULL; 1326 char *dev_name; 1327 1328 /* Add dependent disks */ 1329 dep_dir = g_strdup_printf("%s/%s", deps_dir, dep); 1330 dev_name = get_device_for_syspath(dep_dir); 1331 if (dev_name != NULL) { 1332 g_debug(" adding dependent device: %s", dev_name); 1333 QAPI_LIST_PREPEND(disk->dependencies, dev_name); 1334 } 1335 } 1336 g_dir_close(dp_deps); 1337 } 1338 1339 /* 1340 * Detect partitions subdirectory, name is "<disk_name><number>" or 1341 * "<disk_name>p<number>" 1342 * 1343 * @disk_name -- last component of /sys path (e.g. sda) 1344 * @disk_dir -- sys path of the disk (e.g. /sys/block/sda) 1345 * @disk_dev -- device node of the disk (e.g. /dev/sda) 1346 */ 1347 static GuestDiskInfoList *get_disk_partitions( 1348 GuestDiskInfoList *list, 1349 const char *disk_name, const char *disk_dir, 1350 const char *disk_dev) 1351 { 1352 GuestDiskInfoList *ret = list; 1353 struct dirent *de_disk; 1354 DIR *dp_disk = NULL; 1355 size_t len = strlen(disk_name); 1356 1357 dp_disk = opendir(disk_dir); 1358 while ((de_disk = readdir(dp_disk)) != NULL) { 1359 g_autofree char *partition_dir = NULL; 1360 char *dev_name; 1361 GuestDiskInfo *partition; 1362 1363 if (!(de_disk->d_type & DT_DIR)) { 1364 continue; 1365 } 1366 1367 if (!(strncmp(disk_name, de_disk->d_name, len) == 0 && 1368 ((*(de_disk->d_name + len) == 'p' && 1369 isdigit(*(de_disk->d_name + len + 1))) || 1370 isdigit(*(de_disk->d_name + len))))) { 1371 continue; 1372 } 1373 1374 partition_dir = g_strdup_printf("%s/%s", 1375 disk_dir, de_disk->d_name); 1376 dev_name = get_device_for_syspath(partition_dir); 1377 if (dev_name == NULL) { 1378 g_debug("Failed to get device name for syspath: %s", 1379 disk_dir); 1380 continue; 1381 } 1382 partition = g_new0(GuestDiskInfo, 1); 1383 partition->name = dev_name; 1384 partition->partition = true; 1385 partition->has_dependencies = true; 1386 /* Add parent disk as dependent for easier tracking of hierarchy */ 1387 QAPI_LIST_PREPEND(partition->dependencies, g_strdup(disk_dev)); 1388 1389 QAPI_LIST_PREPEND(ret, partition); 1390 } 1391 closedir(dp_disk); 1392 1393 return ret; 1394 } 1395 1396 static void get_nvme_smart(GuestDiskInfo *disk) 1397 { 1398 int fd; 1399 GuestNVMeSmart *smart; 1400 NvmeSmartLog log = {0}; 1401 struct nvme_admin_cmd cmd = { 1402 .opcode = NVME_ADM_CMD_GET_LOG_PAGE, 1403 .nsid = NVME_NSID_BROADCAST, 1404 .addr = (uintptr_t)&log, 1405 .data_len = sizeof(log), 1406 .cdw10 = NVME_LOG_SMART_INFO | (1 << 15) /* RAE bit */ 1407 | (((sizeof(log) >> 2) - 1) << 16) 1408 }; 1409 1410 fd = qga_open_cloexec(disk->name, O_RDONLY, 0); 1411 if (fd == -1) { 1412 g_debug("Failed to open device: %s: %s", disk->name, g_strerror(errno)); 1413 return; 1414 } 1415 1416 if (ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd)) { 1417 g_debug("Failed to get smart: %s: %s", disk->name, g_strerror(errno)); 1418 close(fd); 1419 return; 1420 } 1421 1422 disk->has_smart = true; 1423 disk->smart = g_new0(GuestDiskSmart, 1); 1424 disk->smart->type = GUEST_DISK_BUS_TYPE_NVME; 1425 1426 smart = &disk->smart->u.nvme; 1427 smart->critical_warning = log.critical_warning; 1428 smart->temperature = lduw_le_p(&log.temperature); /* unaligned field */ 1429 smart->available_spare = log.available_spare; 1430 smart->available_spare_threshold = log.available_spare_threshold; 1431 smart->percentage_used = log.percentage_used; 1432 smart->data_units_read_lo = le64_to_cpu(log.data_units_read[0]); 1433 smart->data_units_read_hi = le64_to_cpu(log.data_units_read[1]); 1434 smart->data_units_written_lo = le64_to_cpu(log.data_units_written[0]); 1435 smart->data_units_written_hi = le64_to_cpu(log.data_units_written[1]); 1436 smart->host_read_commands_lo = le64_to_cpu(log.host_read_commands[0]); 1437 smart->host_read_commands_hi = le64_to_cpu(log.host_read_commands[1]); 1438 smart->host_write_commands_lo = le64_to_cpu(log.host_write_commands[0]); 1439 smart->host_write_commands_hi = le64_to_cpu(log.host_write_commands[1]); 1440 smart->controller_busy_time_lo = le64_to_cpu(log.controller_busy_time[0]); 1441 smart->controller_busy_time_hi = le64_to_cpu(log.controller_busy_time[1]); 1442 smart->power_cycles_lo = le64_to_cpu(log.power_cycles[0]); 1443 smart->power_cycles_hi = le64_to_cpu(log.power_cycles[1]); 1444 smart->power_on_hours_lo = le64_to_cpu(log.power_on_hours[0]); 1445 smart->power_on_hours_hi = le64_to_cpu(log.power_on_hours[1]); 1446 smart->unsafe_shutdowns_lo = le64_to_cpu(log.unsafe_shutdowns[0]); 1447 smart->unsafe_shutdowns_hi = le64_to_cpu(log.unsafe_shutdowns[1]); 1448 smart->media_errors_lo = le64_to_cpu(log.media_errors[0]); 1449 smart->media_errors_hi = le64_to_cpu(log.media_errors[1]); 1450 smart->number_of_error_log_entries_lo = 1451 le64_to_cpu(log.number_of_error_log_entries[0]); 1452 smart->number_of_error_log_entries_hi = 1453 le64_to_cpu(log.number_of_error_log_entries[1]); 1454 1455 close(fd); 1456 } 1457 1458 static void get_disk_smart(GuestDiskInfo *disk) 1459 { 1460 if (disk->has_address 1461 && (disk->address->bus_type == GUEST_DISK_BUS_TYPE_NVME)) { 1462 get_nvme_smart(disk); 1463 } 1464 } 1465 1466 GuestDiskInfoList *qmp_guest_get_disks(Error **errp) 1467 { 1468 GuestDiskInfoList *ret = NULL; 1469 GuestDiskInfo *disk; 1470 DIR *dp = NULL; 1471 struct dirent *de = NULL; 1472 1473 g_debug("listing /sys/block directory"); 1474 dp = opendir("/sys/block"); 1475 if (dp == NULL) { 1476 error_setg_errno(errp, errno, "Can't open directory \"/sys/block\""); 1477 return NULL; 1478 } 1479 while ((de = readdir(dp)) != NULL) { 1480 g_autofree char *disk_dir = NULL, *line = NULL, 1481 *size_path = NULL; 1482 char *dev_name; 1483 Error *local_err = NULL; 1484 if (de->d_type != DT_LNK) { 1485 g_debug(" skipping entry: %s", de->d_name); 1486 continue; 1487 } 1488 1489 /* Check size and skip zero-sized disks */ 1490 g_debug(" checking disk size"); 1491 size_path = g_strdup_printf("/sys/block/%s/size", de->d_name); 1492 if (!g_file_get_contents(size_path, &line, NULL, NULL)) { 1493 g_debug(" failed to read disk size"); 1494 continue; 1495 } 1496 if (g_strcmp0(line, "0\n") == 0) { 1497 g_debug(" skipping zero-sized disk"); 1498 continue; 1499 } 1500 1501 g_debug(" adding %s", de->d_name); 1502 disk_dir = g_strdup_printf("/sys/block/%s", de->d_name); 1503 dev_name = get_device_for_syspath(disk_dir); 1504 if (dev_name == NULL) { 1505 g_debug("Failed to get device name for syspath: %s", 1506 disk_dir); 1507 continue; 1508 } 1509 disk = g_new0(GuestDiskInfo, 1); 1510 disk->name = dev_name; 1511 disk->partition = false; 1512 disk->alias = get_alias_for_syspath(disk_dir); 1513 disk->has_alias = (disk->alias != NULL); 1514 QAPI_LIST_PREPEND(ret, disk); 1515 1516 /* Get address for non-virtual devices */ 1517 bool is_virtual = is_disk_virtual(disk_dir, &local_err); 1518 if (local_err != NULL) { 1519 g_debug(" failed to check disk path, ignoring error: %s", 1520 error_get_pretty(local_err)); 1521 error_free(local_err); 1522 local_err = NULL; 1523 /* Don't try to get the address */ 1524 is_virtual = true; 1525 } 1526 if (!is_virtual) { 1527 disk->address = get_disk_address(disk_dir, &local_err); 1528 if (local_err != NULL) { 1529 g_debug(" failed to get device info, ignoring error: %s", 1530 error_get_pretty(local_err)); 1531 error_free(local_err); 1532 local_err = NULL; 1533 } else if (disk->address != NULL) { 1534 disk->has_address = true; 1535 } 1536 } 1537 1538 get_disk_deps(disk_dir, disk); 1539 get_disk_smart(disk); 1540 ret = get_disk_partitions(ret, de->d_name, disk_dir, dev_name); 1541 } 1542 1543 closedir(dp); 1544 1545 return ret; 1546 } 1547 1548 #else 1549 1550 GuestDiskInfoList *qmp_guest_get_disks(Error **errp) 1551 { 1552 error_setg(errp, QERR_UNSUPPORTED); 1553 return NULL; 1554 } 1555 1556 #endif 1557 1558 /* Return a list of the disk device(s)' info which @mount lies on */ 1559 static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount, 1560 Error **errp) 1561 { 1562 GuestFilesystemInfo *fs = g_malloc0(sizeof(*fs)); 1563 struct statvfs buf; 1564 unsigned long used, nonroot_total, fr_size; 1565 char *devpath = g_strdup_printf("/sys/dev/block/%u:%u", 1566 mount->devmajor, mount->devminor); 1567 1568 fs->mountpoint = g_strdup(mount->dirname); 1569 fs->type = g_strdup(mount->devtype); 1570 build_guest_fsinfo_for_device(devpath, fs, errp); 1571 1572 if (statvfs(fs->mountpoint, &buf) == 0) { 1573 fr_size = buf.f_frsize; 1574 used = buf.f_blocks - buf.f_bfree; 1575 nonroot_total = used + buf.f_bavail; 1576 fs->used_bytes = used * fr_size; 1577 fs->total_bytes = nonroot_total * fr_size; 1578 1579 fs->has_total_bytes = true; 1580 fs->has_used_bytes = true; 1581 } 1582 1583 g_free(devpath); 1584 1585 return fs; 1586 } 1587 1588 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 1589 { 1590 FsMountList mounts; 1591 struct FsMount *mount; 1592 GuestFilesystemInfoList *ret = NULL; 1593 Error *local_err = NULL; 1594 1595 QTAILQ_INIT(&mounts); 1596 if (!build_fs_mount_list(&mounts, &local_err)) { 1597 error_propagate(errp, local_err); 1598 return NULL; 1599 } 1600 1601 QTAILQ_FOREACH(mount, &mounts, next) { 1602 g_debug("Building guest fsinfo for '%s'", mount->dirname); 1603 1604 QAPI_LIST_PREPEND(ret, build_guest_fsinfo(mount, &local_err)); 1605 if (local_err) { 1606 error_propagate(errp, local_err); 1607 qapi_free_GuestFilesystemInfoList(ret); 1608 ret = NULL; 1609 break; 1610 } 1611 } 1612 1613 free_fs_mount_list(&mounts); 1614 return ret; 1615 } 1616 1617 1618 typedef enum { 1619 FSFREEZE_HOOK_THAW = 0, 1620 FSFREEZE_HOOK_FREEZE, 1621 } FsfreezeHookArg; 1622 1623 static const char *fsfreeze_hook_arg_string[] = { 1624 "thaw", 1625 "freeze", 1626 }; 1627 1628 static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **errp) 1629 { 1630 int status; 1631 pid_t pid; 1632 const char *hook; 1633 const char *arg_str = fsfreeze_hook_arg_string[arg]; 1634 Error *local_err = NULL; 1635 1636 hook = ga_fsfreeze_hook(ga_state); 1637 if (!hook) { 1638 return; 1639 } 1640 if (access(hook, X_OK) != 0) { 1641 error_setg_errno(errp, errno, "can't access fsfreeze hook '%s'", hook); 1642 return; 1643 } 1644 1645 slog("executing fsfreeze hook with arg '%s'", arg_str); 1646 pid = fork(); 1647 if (pid == 0) { 1648 setsid(); 1649 reopen_fd_to_null(0); 1650 reopen_fd_to_null(1); 1651 reopen_fd_to_null(2); 1652 1653 execl(hook, hook, arg_str, NULL); 1654 _exit(EXIT_FAILURE); 1655 } else if (pid < 0) { 1656 error_setg_errno(errp, errno, "failed to create child process"); 1657 return; 1658 } 1659 1660 ga_wait_child(pid, &status, &local_err); 1661 if (local_err) { 1662 error_propagate(errp, local_err); 1663 return; 1664 } 1665 1666 if (!WIFEXITED(status)) { 1667 error_setg(errp, "fsfreeze hook has terminated abnormally"); 1668 return; 1669 } 1670 1671 status = WEXITSTATUS(status); 1672 if (status) { 1673 error_setg(errp, "fsfreeze hook has failed with status %d", status); 1674 return; 1675 } 1676 } 1677 1678 /* 1679 * Return status of freeze/thaw 1680 */ 1681 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 1682 { 1683 if (ga_is_frozen(ga_state)) { 1684 return GUEST_FSFREEZE_STATUS_FROZEN; 1685 } 1686 1687 return GUEST_FSFREEZE_STATUS_THAWED; 1688 } 1689 1690 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 1691 { 1692 return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); 1693 } 1694 1695 /* 1696 * Walk list of mounted file systems in the guest, and freeze the ones which 1697 * are real local file systems. 1698 */ 1699 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 1700 strList *mountpoints, 1701 Error **errp) 1702 { 1703 int ret = 0, i = 0; 1704 strList *list; 1705 FsMountList mounts; 1706 struct FsMount *mount; 1707 Error *local_err = NULL; 1708 int fd; 1709 1710 slog("guest-fsfreeze called"); 1711 1712 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); 1713 if (local_err) { 1714 error_propagate(errp, local_err); 1715 return -1; 1716 } 1717 1718 QTAILQ_INIT(&mounts); 1719 if (!build_fs_mount_list(&mounts, &local_err)) { 1720 error_propagate(errp, local_err); 1721 return -1; 1722 } 1723 1724 /* cannot risk guest agent blocking itself on a write in this state */ 1725 ga_set_frozen(ga_state); 1726 1727 QTAILQ_FOREACH_REVERSE(mount, &mounts, next) { 1728 /* To issue fsfreeze in the reverse order of mounts, check if the 1729 * mount is listed in the list here */ 1730 if (has_mountpoints) { 1731 for (list = mountpoints; list; list = list->next) { 1732 if (strcmp(list->value, mount->dirname) == 0) { 1733 break; 1734 } 1735 } 1736 if (!list) { 1737 continue; 1738 } 1739 } 1740 1741 fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0); 1742 if (fd == -1) { 1743 error_setg_errno(errp, errno, "failed to open %s", mount->dirname); 1744 goto error; 1745 } 1746 1747 /* we try to cull filesystems we know won't work in advance, but other 1748 * filesystems may not implement fsfreeze for less obvious reasons. 1749 * these will report EOPNOTSUPP. we simply ignore these when tallying 1750 * the number of frozen filesystems. 1751 * if a filesystem is mounted more than once (aka bind mount) a 1752 * consecutive attempt to freeze an already frozen filesystem will 1753 * return EBUSY. 1754 * 1755 * any other error means a failure to freeze a filesystem we 1756 * expect to be freezable, so return an error in those cases 1757 * and return system to thawed state. 1758 */ 1759 ret = ioctl(fd, FIFREEZE); 1760 if (ret == -1) { 1761 if (errno != EOPNOTSUPP && errno != EBUSY) { 1762 error_setg_errno(errp, errno, "failed to freeze %s", 1763 mount->dirname); 1764 close(fd); 1765 goto error; 1766 } 1767 } else { 1768 i++; 1769 } 1770 close(fd); 1771 } 1772 1773 free_fs_mount_list(&mounts); 1774 /* We may not issue any FIFREEZE here. 1775 * Just unset ga_state here and ready for the next call. 1776 */ 1777 if (i == 0) { 1778 ga_unset_frozen(ga_state); 1779 } 1780 return i; 1781 1782 error: 1783 free_fs_mount_list(&mounts); 1784 qmp_guest_fsfreeze_thaw(NULL); 1785 return 0; 1786 } 1787 1788 /* 1789 * Walk list of frozen file systems in the guest, and thaw them. 1790 */ 1791 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 1792 { 1793 int ret; 1794 FsMountList mounts; 1795 FsMount *mount; 1796 int fd, i = 0, logged; 1797 Error *local_err = NULL; 1798 1799 QTAILQ_INIT(&mounts); 1800 if (!build_fs_mount_list(&mounts, &local_err)) { 1801 error_propagate(errp, local_err); 1802 return 0; 1803 } 1804 1805 QTAILQ_FOREACH(mount, &mounts, next) { 1806 logged = false; 1807 fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0); 1808 if (fd == -1) { 1809 continue; 1810 } 1811 /* we have no way of knowing whether a filesystem was actually unfrozen 1812 * as a result of a successful call to FITHAW, only that if an error 1813 * was returned the filesystem was *not* unfrozen by that particular 1814 * call. 1815 * 1816 * since multiple preceding FIFREEZEs require multiple calls to FITHAW 1817 * to unfreeze, continuing issuing FITHAW until an error is returned, 1818 * in which case either the filesystem is in an unfreezable state, or, 1819 * more likely, it was thawed previously (and remains so afterward). 1820 * 1821 * also, since the most recent successful call is the one that did 1822 * the actual unfreeze, we can use this to provide an accurate count 1823 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which 1824 * may * be useful for determining whether a filesystem was unfrozen 1825 * during the freeze/thaw phase by a process other than qemu-ga. 1826 */ 1827 do { 1828 ret = ioctl(fd, FITHAW); 1829 if (ret == 0 && !logged) { 1830 i++; 1831 logged = true; 1832 } 1833 } while (ret == 0); 1834 close(fd); 1835 } 1836 1837 ga_unset_frozen(ga_state); 1838 free_fs_mount_list(&mounts); 1839 1840 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, errp); 1841 1842 return i; 1843 } 1844 1845 static void guest_fsfreeze_cleanup(void) 1846 { 1847 Error *err = NULL; 1848 1849 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 1850 qmp_guest_fsfreeze_thaw(&err); 1851 if (err) { 1852 slog("failed to clean up frozen filesystems: %s", 1853 error_get_pretty(err)); 1854 error_free(err); 1855 } 1856 } 1857 } 1858 #endif /* CONFIG_FSFREEZE */ 1859 1860 #if defined(CONFIG_FSTRIM) 1861 /* 1862 * Walk list of mounted file systems in the guest, and trim them. 1863 */ 1864 GuestFilesystemTrimResponse * 1865 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 1866 { 1867 GuestFilesystemTrimResponse *response; 1868 GuestFilesystemTrimResult *result; 1869 int ret = 0; 1870 FsMountList mounts; 1871 struct FsMount *mount; 1872 int fd; 1873 struct fstrim_range r; 1874 1875 slog("guest-fstrim called"); 1876 1877 QTAILQ_INIT(&mounts); 1878 if (!build_fs_mount_list(&mounts, errp)) { 1879 return NULL; 1880 } 1881 1882 response = g_malloc0(sizeof(*response)); 1883 1884 QTAILQ_FOREACH(mount, &mounts, next) { 1885 result = g_malloc0(sizeof(*result)); 1886 result->path = g_strdup(mount->dirname); 1887 1888 QAPI_LIST_PREPEND(response->paths, result); 1889 1890 fd = qga_open_cloexec(mount->dirname, O_RDONLY, 0); 1891 if (fd == -1) { 1892 result->error = g_strdup_printf("failed to open: %s", 1893 strerror(errno)); 1894 result->has_error = true; 1895 continue; 1896 } 1897 1898 /* We try to cull filesystems we know won't work in advance, but other 1899 * filesystems may not implement fstrim for less obvious reasons. 1900 * These will report EOPNOTSUPP; while in some other cases ENOTTY 1901 * will be reported (e.g. CD-ROMs). 1902 * Any other error means an unexpected error. 1903 */ 1904 r.start = 0; 1905 r.len = -1; 1906 r.minlen = has_minimum ? minimum : 0; 1907 ret = ioctl(fd, FITRIM, &r); 1908 if (ret == -1) { 1909 result->has_error = true; 1910 if (errno == ENOTTY || errno == EOPNOTSUPP) { 1911 result->error = g_strdup("trim not supported"); 1912 } else { 1913 result->error = g_strdup_printf("failed to trim: %s", 1914 strerror(errno)); 1915 } 1916 close(fd); 1917 continue; 1918 } 1919 1920 result->has_minimum = true; 1921 result->minimum = r.minlen; 1922 result->has_trimmed = true; 1923 result->trimmed = r.len; 1924 close(fd); 1925 } 1926 1927 free_fs_mount_list(&mounts); 1928 return response; 1929 } 1930 #endif /* CONFIG_FSTRIM */ 1931 1932 1933 #define LINUX_SYS_STATE_FILE "/sys/power/state" 1934 #define SUSPEND_SUPPORTED 0 1935 #define SUSPEND_NOT_SUPPORTED 1 1936 1937 typedef enum { 1938 SUSPEND_MODE_DISK = 0, 1939 SUSPEND_MODE_RAM = 1, 1940 SUSPEND_MODE_HYBRID = 2, 1941 } SuspendMode; 1942 1943 /* 1944 * Executes a command in a child process using g_spawn_sync, 1945 * returning an int >= 0 representing the exit status of the 1946 * process. 1947 * 1948 * If the program wasn't found in path, returns -1. 1949 * 1950 * If a problem happened when creating the child process, 1951 * returns -1 and errp is set. 1952 */ 1953 static int run_process_child(const char *command[], Error **errp) 1954 { 1955 int exit_status, spawn_flag; 1956 GError *g_err = NULL; 1957 bool success; 1958 1959 spawn_flag = G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | 1960 G_SPAWN_STDERR_TO_DEV_NULL; 1961 1962 success = g_spawn_sync(NULL, (char **)command, NULL, spawn_flag, 1963 NULL, NULL, NULL, NULL, 1964 &exit_status, &g_err); 1965 1966 if (success) { 1967 return WEXITSTATUS(exit_status); 1968 } 1969 1970 if (g_err && (g_err->code != G_SPAWN_ERROR_NOENT)) { 1971 error_setg(errp, "failed to create child process, error '%s'", 1972 g_err->message); 1973 } 1974 1975 g_error_free(g_err); 1976 return -1; 1977 } 1978 1979 static bool systemd_supports_mode(SuspendMode mode, Error **errp) 1980 { 1981 const char *systemctl_args[3] = {"systemd-hibernate", "systemd-suspend", 1982 "systemd-hybrid-sleep"}; 1983 const char *cmd[4] = {"systemctl", "status", systemctl_args[mode], NULL}; 1984 int status; 1985 1986 status = run_process_child(cmd, errp); 1987 1988 /* 1989 * systemctl status uses LSB return codes so we can expect 1990 * status > 0 and be ok. To assert if the guest has support 1991 * for the selected suspend mode, status should be < 4. 4 is 1992 * the code for unknown service status, the return value when 1993 * the service does not exist. A common value is status = 3 1994 * (program is not running). 1995 */ 1996 if (status > 0 && status < 4) { 1997 return true; 1998 } 1999 2000 return false; 2001 } 2002 2003 static void systemd_suspend(SuspendMode mode, Error **errp) 2004 { 2005 Error *local_err = NULL; 2006 const char *systemctl_args[3] = {"hibernate", "suspend", "hybrid-sleep"}; 2007 const char *cmd[3] = {"systemctl", systemctl_args[mode], NULL}; 2008 int status; 2009 2010 status = run_process_child(cmd, &local_err); 2011 2012 if (status == 0) { 2013 return; 2014 } 2015 2016 if ((status == -1) && !local_err) { 2017 error_setg(errp, "the helper program 'systemctl %s' was not found", 2018 systemctl_args[mode]); 2019 return; 2020 } 2021 2022 if (local_err) { 2023 error_propagate(errp, local_err); 2024 } else { 2025 error_setg(errp, "the helper program 'systemctl %s' returned an " 2026 "unexpected exit status code (%d)", 2027 systemctl_args[mode], status); 2028 } 2029 } 2030 2031 static bool pmutils_supports_mode(SuspendMode mode, Error **errp) 2032 { 2033 Error *local_err = NULL; 2034 const char *pmutils_args[3] = {"--hibernate", "--suspend", 2035 "--suspend-hybrid"}; 2036 const char *cmd[3] = {"pm-is-supported", pmutils_args[mode], NULL}; 2037 int status; 2038 2039 status = run_process_child(cmd, &local_err); 2040 2041 if (status == SUSPEND_SUPPORTED) { 2042 return true; 2043 } 2044 2045 if ((status == -1) && !local_err) { 2046 return false; 2047 } 2048 2049 if (local_err) { 2050 error_propagate(errp, local_err); 2051 } else { 2052 error_setg(errp, 2053 "the helper program '%s' returned an unexpected exit" 2054 " status code (%d)", "pm-is-supported", status); 2055 } 2056 2057 return false; 2058 } 2059 2060 static void pmutils_suspend(SuspendMode mode, Error **errp) 2061 { 2062 Error *local_err = NULL; 2063 const char *pmutils_binaries[3] = {"pm-hibernate", "pm-suspend", 2064 "pm-suspend-hybrid"}; 2065 const char *cmd[2] = {pmutils_binaries[mode], NULL}; 2066 int status; 2067 2068 status = run_process_child(cmd, &local_err); 2069 2070 if (status == 0) { 2071 return; 2072 } 2073 2074 if ((status == -1) && !local_err) { 2075 error_setg(errp, "the helper program '%s' was not found", 2076 pmutils_binaries[mode]); 2077 return; 2078 } 2079 2080 if (local_err) { 2081 error_propagate(errp, local_err); 2082 } else { 2083 error_setg(errp, 2084 "the helper program '%s' returned an unexpected exit" 2085 " status code (%d)", pmutils_binaries[mode], status); 2086 } 2087 } 2088 2089 static bool linux_sys_state_supports_mode(SuspendMode mode, Error **errp) 2090 { 2091 const char *sysfile_strs[3] = {"disk", "mem", NULL}; 2092 const char *sysfile_str = sysfile_strs[mode]; 2093 char buf[32]; /* hopefully big enough */ 2094 int fd; 2095 ssize_t ret; 2096 2097 if (!sysfile_str) { 2098 error_setg(errp, "unknown guest suspend mode"); 2099 return false; 2100 } 2101 2102 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY); 2103 if (fd < 0) { 2104 return false; 2105 } 2106 2107 ret = read(fd, buf, sizeof(buf) - 1); 2108 close(fd); 2109 if (ret <= 0) { 2110 return false; 2111 } 2112 buf[ret] = '\0'; 2113 2114 if (strstr(buf, sysfile_str)) { 2115 return true; 2116 } 2117 return false; 2118 } 2119 2120 static void linux_sys_state_suspend(SuspendMode mode, Error **errp) 2121 { 2122 Error *local_err = NULL; 2123 const char *sysfile_strs[3] = {"disk", "mem", NULL}; 2124 const char *sysfile_str = sysfile_strs[mode]; 2125 pid_t pid; 2126 int status; 2127 2128 if (!sysfile_str) { 2129 error_setg(errp, "unknown guest suspend mode"); 2130 return; 2131 } 2132 2133 pid = fork(); 2134 if (!pid) { 2135 /* child */ 2136 int fd; 2137 2138 setsid(); 2139 reopen_fd_to_null(0); 2140 reopen_fd_to_null(1); 2141 reopen_fd_to_null(2); 2142 2143 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); 2144 if (fd < 0) { 2145 _exit(EXIT_FAILURE); 2146 } 2147 2148 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) { 2149 _exit(EXIT_FAILURE); 2150 } 2151 2152 _exit(EXIT_SUCCESS); 2153 } else if (pid < 0) { 2154 error_setg_errno(errp, errno, "failed to create child process"); 2155 return; 2156 } 2157 2158 ga_wait_child(pid, &status, &local_err); 2159 if (local_err) { 2160 error_propagate(errp, local_err); 2161 return; 2162 } 2163 2164 if (WEXITSTATUS(status)) { 2165 error_setg(errp, "child process has failed to suspend"); 2166 } 2167 2168 } 2169 2170 static void guest_suspend(SuspendMode mode, Error **errp) 2171 { 2172 Error *local_err = NULL; 2173 bool mode_supported = false; 2174 2175 if (systemd_supports_mode(mode, &local_err)) { 2176 mode_supported = true; 2177 systemd_suspend(mode, &local_err); 2178 } 2179 2180 if (!local_err) { 2181 return; 2182 } 2183 2184 error_free(local_err); 2185 local_err = NULL; 2186 2187 if (pmutils_supports_mode(mode, &local_err)) { 2188 mode_supported = true; 2189 pmutils_suspend(mode, &local_err); 2190 } 2191 2192 if (!local_err) { 2193 return; 2194 } 2195 2196 error_free(local_err); 2197 local_err = NULL; 2198 2199 if (linux_sys_state_supports_mode(mode, &local_err)) { 2200 mode_supported = true; 2201 linux_sys_state_suspend(mode, &local_err); 2202 } 2203 2204 if (!mode_supported) { 2205 error_free(local_err); 2206 error_setg(errp, 2207 "the requested suspend mode is not supported by the guest"); 2208 } else { 2209 error_propagate(errp, local_err); 2210 } 2211 } 2212 2213 void qmp_guest_suspend_disk(Error **errp) 2214 { 2215 guest_suspend(SUSPEND_MODE_DISK, errp); 2216 } 2217 2218 void qmp_guest_suspend_ram(Error **errp) 2219 { 2220 guest_suspend(SUSPEND_MODE_RAM, errp); 2221 } 2222 2223 void qmp_guest_suspend_hybrid(Error **errp) 2224 { 2225 guest_suspend(SUSPEND_MODE_HYBRID, errp); 2226 } 2227 2228 /* Transfer online/offline status between @vcpu and the guest system. 2229 * 2230 * On input either @errp or *@errp must be NULL. 2231 * 2232 * In system-to-@vcpu direction, the following @vcpu fields are accessed: 2233 * - R: vcpu->logical_id 2234 * - W: vcpu->online 2235 * - W: vcpu->can_offline 2236 * 2237 * In @vcpu-to-system direction, the following @vcpu fields are accessed: 2238 * - R: vcpu->logical_id 2239 * - R: vcpu->online 2240 * 2241 * Written members remain unmodified on error. 2242 */ 2243 static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu, 2244 char *dirpath, Error **errp) 2245 { 2246 int fd; 2247 int res; 2248 int dirfd; 2249 static const char fn[] = "online"; 2250 2251 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2252 if (dirfd == -1) { 2253 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2254 return; 2255 } 2256 2257 fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); 2258 if (fd == -1) { 2259 if (errno != ENOENT) { 2260 error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn); 2261 } else if (sys2vcpu) { 2262 vcpu->online = true; 2263 vcpu->can_offline = false; 2264 } else if (!vcpu->online) { 2265 error_setg(errp, "logical processor #%" PRId64 " can't be " 2266 "offlined", vcpu->logical_id); 2267 } /* otherwise pretend successful re-onlining */ 2268 } else { 2269 unsigned char status; 2270 2271 res = pread(fd, &status, 1, 0); 2272 if (res == -1) { 2273 error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn); 2274 } else if (res == 0) { 2275 error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, 2276 fn); 2277 } else if (sys2vcpu) { 2278 vcpu->online = (status != '0'); 2279 vcpu->can_offline = true; 2280 } else if (vcpu->online != (status != '0')) { 2281 status = '0' + vcpu->online; 2282 if (pwrite(fd, &status, 1, 0) == -1) { 2283 error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath, 2284 fn); 2285 } 2286 } /* otherwise pretend successful re-(on|off)-lining */ 2287 2288 res = close(fd); 2289 g_assert(res == 0); 2290 } 2291 2292 res = close(dirfd); 2293 g_assert(res == 0); 2294 } 2295 2296 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 2297 { 2298 GuestLogicalProcessorList *head, **tail; 2299 const char *cpu_dir = "/sys/devices/system/cpu"; 2300 const gchar *line; 2301 g_autoptr(GDir) cpu_gdir = NULL; 2302 Error *local_err = NULL; 2303 2304 head = NULL; 2305 tail = &head; 2306 cpu_gdir = g_dir_open(cpu_dir, 0, NULL); 2307 2308 if (cpu_gdir == NULL) { 2309 error_setg_errno(errp, errno, "failed to list entries: %s", cpu_dir); 2310 return NULL; 2311 } 2312 2313 while (local_err == NULL && (line = g_dir_read_name(cpu_gdir)) != NULL) { 2314 GuestLogicalProcessor *vcpu; 2315 int64_t id; 2316 if (sscanf(line, "cpu%" PRId64, &id)) { 2317 g_autofree char *path = g_strdup_printf("/sys/devices/system/cpu/" 2318 "cpu%" PRId64 "/", id); 2319 vcpu = g_malloc0(sizeof *vcpu); 2320 vcpu->logical_id = id; 2321 vcpu->has_can_offline = true; /* lolspeak ftw */ 2322 transfer_vcpu(vcpu, true, path, &local_err); 2323 QAPI_LIST_APPEND(tail, vcpu); 2324 } 2325 } 2326 2327 if (local_err == NULL) { 2328 /* there's no guest with zero VCPUs */ 2329 g_assert(head != NULL); 2330 return head; 2331 } 2332 2333 qapi_free_GuestLogicalProcessorList(head); 2334 error_propagate(errp, local_err); 2335 return NULL; 2336 } 2337 2338 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 2339 { 2340 int64_t processed; 2341 Error *local_err = NULL; 2342 2343 processed = 0; 2344 while (vcpus != NULL) { 2345 char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", 2346 vcpus->value->logical_id); 2347 2348 transfer_vcpu(vcpus->value, false, path, &local_err); 2349 g_free(path); 2350 if (local_err != NULL) { 2351 break; 2352 } 2353 ++processed; 2354 vcpus = vcpus->next; 2355 } 2356 2357 if (local_err != NULL) { 2358 if (processed == 0) { 2359 error_propagate(errp, local_err); 2360 } else { 2361 error_free(local_err); 2362 } 2363 } 2364 2365 return processed; 2366 } 2367 2368 void qmp_guest_set_user_password(const char *username, 2369 const char *password, 2370 bool crypted, 2371 Error **errp) 2372 { 2373 Error *local_err = NULL; 2374 char *passwd_path = NULL; 2375 pid_t pid; 2376 int status; 2377 int datafd[2] = { -1, -1 }; 2378 char *rawpasswddata = NULL; 2379 size_t rawpasswdlen; 2380 char *chpasswddata = NULL; 2381 size_t chpasswdlen; 2382 2383 rawpasswddata = (char *)qbase64_decode(password, -1, &rawpasswdlen, errp); 2384 if (!rawpasswddata) { 2385 return; 2386 } 2387 rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1); 2388 rawpasswddata[rawpasswdlen] = '\0'; 2389 2390 if (strchr(rawpasswddata, '\n')) { 2391 error_setg(errp, "forbidden characters in raw password"); 2392 goto out; 2393 } 2394 2395 if (strchr(username, '\n') || 2396 strchr(username, ':')) { 2397 error_setg(errp, "forbidden characters in username"); 2398 goto out; 2399 } 2400 2401 chpasswddata = g_strdup_printf("%s:%s\n", username, rawpasswddata); 2402 chpasswdlen = strlen(chpasswddata); 2403 2404 passwd_path = g_find_program_in_path("chpasswd"); 2405 2406 if (!passwd_path) { 2407 error_setg(errp, "cannot find 'passwd' program in PATH"); 2408 goto out; 2409 } 2410 2411 if (!g_unix_open_pipe(datafd, FD_CLOEXEC, NULL)) { 2412 error_setg(errp, "cannot create pipe FDs"); 2413 goto out; 2414 } 2415 2416 pid = fork(); 2417 if (pid == 0) { 2418 close(datafd[1]); 2419 /* child */ 2420 setsid(); 2421 dup2(datafd[0], 0); 2422 reopen_fd_to_null(1); 2423 reopen_fd_to_null(2); 2424 2425 if (crypted) { 2426 execl(passwd_path, "chpasswd", "-e", NULL); 2427 } else { 2428 execl(passwd_path, "chpasswd", NULL); 2429 } 2430 _exit(EXIT_FAILURE); 2431 } else if (pid < 0) { 2432 error_setg_errno(errp, errno, "failed to create child process"); 2433 goto out; 2434 } 2435 close(datafd[0]); 2436 datafd[0] = -1; 2437 2438 if (qemu_write_full(datafd[1], chpasswddata, chpasswdlen) != chpasswdlen) { 2439 error_setg_errno(errp, errno, "cannot write new account password"); 2440 goto out; 2441 } 2442 close(datafd[1]); 2443 datafd[1] = -1; 2444 2445 ga_wait_child(pid, &status, &local_err); 2446 if (local_err) { 2447 error_propagate(errp, local_err); 2448 goto out; 2449 } 2450 2451 if (!WIFEXITED(status)) { 2452 error_setg(errp, "child process has terminated abnormally"); 2453 goto out; 2454 } 2455 2456 if (WEXITSTATUS(status)) { 2457 error_setg(errp, "child process has failed to set user password"); 2458 goto out; 2459 } 2460 2461 out: 2462 g_free(chpasswddata); 2463 g_free(rawpasswddata); 2464 g_free(passwd_path); 2465 if (datafd[0] != -1) { 2466 close(datafd[0]); 2467 } 2468 if (datafd[1] != -1) { 2469 close(datafd[1]); 2470 } 2471 } 2472 2473 static void ga_read_sysfs_file(int dirfd, const char *pathname, char *buf, 2474 int size, Error **errp) 2475 { 2476 int fd; 2477 int res; 2478 2479 errno = 0; 2480 fd = openat(dirfd, pathname, O_RDONLY); 2481 if (fd == -1) { 2482 error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname); 2483 return; 2484 } 2485 2486 res = pread(fd, buf, size, 0); 2487 if (res == -1) { 2488 error_setg_errno(errp, errno, "pread sysfs file \"%s\"", pathname); 2489 } else if (res == 0) { 2490 error_setg(errp, "pread sysfs file \"%s\": unexpected EOF", pathname); 2491 } 2492 close(fd); 2493 } 2494 2495 static void ga_write_sysfs_file(int dirfd, const char *pathname, 2496 const char *buf, int size, Error **errp) 2497 { 2498 int fd; 2499 2500 errno = 0; 2501 fd = openat(dirfd, pathname, O_WRONLY); 2502 if (fd == -1) { 2503 error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname); 2504 return; 2505 } 2506 2507 if (pwrite(fd, buf, size, 0) == -1) { 2508 error_setg_errno(errp, errno, "pwrite sysfs file \"%s\"", pathname); 2509 } 2510 2511 close(fd); 2512 } 2513 2514 /* Transfer online/offline status between @mem_blk and the guest system. 2515 * 2516 * On input either @errp or *@errp must be NULL. 2517 * 2518 * In system-to-@mem_blk direction, the following @mem_blk fields are accessed: 2519 * - R: mem_blk->phys_index 2520 * - W: mem_blk->online 2521 * - W: mem_blk->can_offline 2522 * 2523 * In @mem_blk-to-system direction, the following @mem_blk fields are accessed: 2524 * - R: mem_blk->phys_index 2525 * - R: mem_blk->online 2526 *- R: mem_blk->can_offline 2527 * Written members remain unmodified on error. 2528 */ 2529 static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk, 2530 GuestMemoryBlockResponse *result, 2531 Error **errp) 2532 { 2533 char *dirpath; 2534 int dirfd; 2535 char *status; 2536 Error *local_err = NULL; 2537 2538 if (!sys2memblk) { 2539 DIR *dp; 2540 2541 if (!result) { 2542 error_setg(errp, "Internal error, 'result' should not be NULL"); 2543 return; 2544 } 2545 errno = 0; 2546 dp = opendir("/sys/devices/system/memory/"); 2547 /* if there is no 'memory' directory in sysfs, 2548 * we think this VM does not support online/offline memory block, 2549 * any other solution? 2550 */ 2551 if (!dp) { 2552 if (errno == ENOENT) { 2553 result->response = 2554 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED; 2555 } 2556 goto out1; 2557 } 2558 closedir(dp); 2559 } 2560 2561 dirpath = g_strdup_printf("/sys/devices/system/memory/memory%" PRId64 "/", 2562 mem_blk->phys_index); 2563 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2564 if (dirfd == -1) { 2565 if (sys2memblk) { 2566 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2567 } else { 2568 if (errno == ENOENT) { 2569 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_NOT_FOUND; 2570 } else { 2571 result->response = 2572 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2573 } 2574 } 2575 g_free(dirpath); 2576 goto out1; 2577 } 2578 g_free(dirpath); 2579 2580 status = g_malloc0(10); 2581 ga_read_sysfs_file(dirfd, "state", status, 10, &local_err); 2582 if (local_err) { 2583 /* treat with sysfs file that not exist in old kernel */ 2584 if (errno == ENOENT) { 2585 error_free(local_err); 2586 if (sys2memblk) { 2587 mem_blk->online = true; 2588 mem_blk->can_offline = false; 2589 } else if (!mem_blk->online) { 2590 result->response = 2591 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED; 2592 } 2593 } else { 2594 if (sys2memblk) { 2595 error_propagate(errp, local_err); 2596 } else { 2597 error_free(local_err); 2598 result->response = 2599 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2600 } 2601 } 2602 goto out2; 2603 } 2604 2605 if (sys2memblk) { 2606 char removable = '0'; 2607 2608 mem_blk->online = (strncmp(status, "online", 6) == 0); 2609 2610 ga_read_sysfs_file(dirfd, "removable", &removable, 1, &local_err); 2611 if (local_err) { 2612 /* if no 'removable' file, it doesn't support offline mem blk */ 2613 if (errno == ENOENT) { 2614 error_free(local_err); 2615 mem_blk->can_offline = false; 2616 } else { 2617 error_propagate(errp, local_err); 2618 } 2619 } else { 2620 mem_blk->can_offline = (removable != '0'); 2621 } 2622 } else { 2623 if (mem_blk->online != (strncmp(status, "online", 6) == 0)) { 2624 const char *new_state = mem_blk->online ? "online" : "offline"; 2625 2626 ga_write_sysfs_file(dirfd, "state", new_state, strlen(new_state), 2627 &local_err); 2628 if (local_err) { 2629 error_free(local_err); 2630 result->response = 2631 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2632 goto out2; 2633 } 2634 2635 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_SUCCESS; 2636 result->has_error_code = false; 2637 } /* otherwise pretend successful re-(on|off)-lining */ 2638 } 2639 g_free(status); 2640 close(dirfd); 2641 return; 2642 2643 out2: 2644 g_free(status); 2645 close(dirfd); 2646 out1: 2647 if (!sys2memblk) { 2648 result->has_error_code = true; 2649 result->error_code = errno; 2650 } 2651 } 2652 2653 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 2654 { 2655 GuestMemoryBlockList *head, **tail; 2656 Error *local_err = NULL; 2657 struct dirent *de; 2658 DIR *dp; 2659 2660 head = NULL; 2661 tail = &head; 2662 2663 dp = opendir("/sys/devices/system/memory/"); 2664 if (!dp) { 2665 /* it's ok if this happens to be a system that doesn't expose 2666 * memory blocks via sysfs, but otherwise we should report 2667 * an error 2668 */ 2669 if (errno != ENOENT) { 2670 error_setg_errno(errp, errno, "Can't open directory" 2671 "\"/sys/devices/system/memory/\""); 2672 } 2673 return NULL; 2674 } 2675 2676 /* Note: the phys_index of memory block may be discontinuous, 2677 * this is because a memblk is the unit of the Sparse Memory design, which 2678 * allows discontinuous memory ranges (ex. NUMA), so here we should 2679 * traverse the memory block directory. 2680 */ 2681 while ((de = readdir(dp)) != NULL) { 2682 GuestMemoryBlock *mem_blk; 2683 2684 if ((strncmp(de->d_name, "memory", 6) != 0) || 2685 !(de->d_type & DT_DIR)) { 2686 continue; 2687 } 2688 2689 mem_blk = g_malloc0(sizeof *mem_blk); 2690 /* The d_name is "memoryXXX", phys_index is block id, same as XXX */ 2691 mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10); 2692 mem_blk->has_can_offline = true; /* lolspeak ftw */ 2693 transfer_memory_block(mem_blk, true, NULL, &local_err); 2694 if (local_err) { 2695 break; 2696 } 2697 2698 QAPI_LIST_APPEND(tail, mem_blk); 2699 } 2700 2701 closedir(dp); 2702 if (local_err == NULL) { 2703 /* there's no guest with zero memory blocks */ 2704 if (head == NULL) { 2705 error_setg(errp, "guest reported zero memory blocks!"); 2706 } 2707 return head; 2708 } 2709 2710 qapi_free_GuestMemoryBlockList(head); 2711 error_propagate(errp, local_err); 2712 return NULL; 2713 } 2714 2715 GuestMemoryBlockResponseList * 2716 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 2717 { 2718 GuestMemoryBlockResponseList *head, **tail; 2719 Error *local_err = NULL; 2720 2721 head = NULL; 2722 tail = &head; 2723 2724 while (mem_blks != NULL) { 2725 GuestMemoryBlockResponse *result; 2726 GuestMemoryBlock *current_mem_blk = mem_blks->value; 2727 2728 result = g_malloc0(sizeof(*result)); 2729 result->phys_index = current_mem_blk->phys_index; 2730 transfer_memory_block(current_mem_blk, false, result, &local_err); 2731 if (local_err) { /* should never happen */ 2732 goto err; 2733 } 2734 2735 QAPI_LIST_APPEND(tail, result); 2736 mem_blks = mem_blks->next; 2737 } 2738 2739 return head; 2740 err: 2741 qapi_free_GuestMemoryBlockResponseList(head); 2742 error_propagate(errp, local_err); 2743 return NULL; 2744 } 2745 2746 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 2747 { 2748 Error *local_err = NULL; 2749 char *dirpath; 2750 int dirfd; 2751 char *buf; 2752 GuestMemoryBlockInfo *info; 2753 2754 dirpath = g_strdup_printf("/sys/devices/system/memory/"); 2755 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2756 if (dirfd == -1) { 2757 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2758 g_free(dirpath); 2759 return NULL; 2760 } 2761 g_free(dirpath); 2762 2763 buf = g_malloc0(20); 2764 ga_read_sysfs_file(dirfd, "block_size_bytes", buf, 20, &local_err); 2765 close(dirfd); 2766 if (local_err) { 2767 g_free(buf); 2768 error_propagate(errp, local_err); 2769 return NULL; 2770 } 2771 2772 info = g_new0(GuestMemoryBlockInfo, 1); 2773 info->size = strtol(buf, NULL, 16); /* the unit is bytes */ 2774 2775 g_free(buf); 2776 2777 return info; 2778 } 2779 2780 #define MAX_NAME_LEN 128 2781 static GuestDiskStatsInfoList *guest_get_diskstats(Error **errp) 2782 { 2783 #ifdef CONFIG_LINUX 2784 GuestDiskStatsInfoList *head = NULL, **tail = &head; 2785 const char *diskstats = "/proc/diskstats"; 2786 FILE *fp; 2787 size_t n; 2788 char *line = NULL; 2789 2790 fp = fopen(diskstats, "r"); 2791 if (fp == NULL) { 2792 error_setg_errno(errp, errno, "open(\"%s\")", diskstats); 2793 return NULL; 2794 } 2795 2796 while (getline(&line, &n, fp) != -1) { 2797 g_autofree GuestDiskStatsInfo *diskstatinfo = NULL; 2798 g_autofree GuestDiskStats *diskstat = NULL; 2799 char dev_name[MAX_NAME_LEN]; 2800 unsigned int ios_pgr, tot_ticks, rq_ticks, wr_ticks, dc_ticks, fl_ticks; 2801 unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios; 2802 unsigned long wr_merges, rd_sec_or_wr_ios, wr_sec; 2803 unsigned long dc_ios, dc_merges, dc_sec, fl_ios; 2804 unsigned int major, minor; 2805 int i; 2806 2807 i = sscanf(line, "%u %u %s %lu %lu %lu" 2808 "%lu %lu %lu %lu %u %u %u %u" 2809 "%lu %lu %lu %u %lu %u", 2810 &major, &minor, dev_name, 2811 &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios, 2812 &rd_ticks_or_wr_sec, &wr_ios, &wr_merges, &wr_sec, 2813 &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks, 2814 &dc_ios, &dc_merges, &dc_sec, &dc_ticks, 2815 &fl_ios, &fl_ticks); 2816 2817 if (i < 7) { 2818 continue; 2819 } 2820 2821 diskstatinfo = g_new0(GuestDiskStatsInfo, 1); 2822 diskstatinfo->name = g_strdup(dev_name); 2823 diskstatinfo->major = major; 2824 diskstatinfo->minor = minor; 2825 2826 diskstat = g_new0(GuestDiskStats, 1); 2827 if (i == 7) { 2828 diskstat->has_read_ios = true; 2829 diskstat->read_ios = rd_ios; 2830 diskstat->has_read_sectors = true; 2831 diskstat->read_sectors = rd_merges_or_rd_sec; 2832 diskstat->has_write_ios = true; 2833 diskstat->write_ios = rd_sec_or_wr_ios; 2834 diskstat->has_write_sectors = true; 2835 diskstat->write_sectors = rd_ticks_or_wr_sec; 2836 } 2837 if (i >= 14) { 2838 diskstat->has_read_ios = true; 2839 diskstat->read_ios = rd_ios; 2840 diskstat->has_read_sectors = true; 2841 diskstat->read_sectors = rd_sec_or_wr_ios; 2842 diskstat->has_read_merges = true; 2843 diskstat->read_merges = rd_merges_or_rd_sec; 2844 diskstat->has_read_ticks = true; 2845 diskstat->read_ticks = rd_ticks_or_wr_sec; 2846 diskstat->has_write_ios = true; 2847 diskstat->write_ios = wr_ios; 2848 diskstat->has_write_sectors = true; 2849 diskstat->write_sectors = wr_sec; 2850 diskstat->has_write_merges = true; 2851 diskstat->write_merges = wr_merges; 2852 diskstat->has_write_ticks = true; 2853 diskstat->write_ticks = wr_ticks; 2854 diskstat->has_ios_pgr = true; 2855 diskstat->ios_pgr = ios_pgr; 2856 diskstat->has_total_ticks = true; 2857 diskstat->total_ticks = tot_ticks; 2858 diskstat->has_weight_ticks = true; 2859 diskstat->weight_ticks = rq_ticks; 2860 } 2861 if (i >= 18) { 2862 diskstat->has_discard_ios = true; 2863 diskstat->discard_ios = dc_ios; 2864 diskstat->has_discard_merges = true; 2865 diskstat->discard_merges = dc_merges; 2866 diskstat->has_discard_sectors = true; 2867 diskstat->discard_sectors = dc_sec; 2868 diskstat->has_discard_ticks = true; 2869 diskstat->discard_ticks = dc_ticks; 2870 } 2871 if (i >= 20) { 2872 diskstat->has_flush_ios = true; 2873 diskstat->flush_ios = fl_ios; 2874 diskstat->has_flush_ticks = true; 2875 diskstat->flush_ticks = fl_ticks; 2876 } 2877 2878 diskstatinfo->stats = g_steal_pointer(&diskstat); 2879 QAPI_LIST_APPEND(tail, diskstatinfo); 2880 diskstatinfo = NULL; 2881 } 2882 free(line); 2883 fclose(fp); 2884 return head; 2885 #else 2886 g_debug("disk stats reporting available only for Linux"); 2887 return NULL; 2888 #endif 2889 } 2890 2891 GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp) 2892 { 2893 return guest_get_diskstats(errp); 2894 } 2895 2896 #else /* defined(__linux__) */ 2897 2898 void qmp_guest_suspend_disk(Error **errp) 2899 { 2900 error_setg(errp, QERR_UNSUPPORTED); 2901 } 2902 2903 void qmp_guest_suspend_ram(Error **errp) 2904 { 2905 error_setg(errp, QERR_UNSUPPORTED); 2906 } 2907 2908 void qmp_guest_suspend_hybrid(Error **errp) 2909 { 2910 error_setg(errp, QERR_UNSUPPORTED); 2911 } 2912 2913 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 2914 { 2915 error_setg(errp, QERR_UNSUPPORTED); 2916 return NULL; 2917 } 2918 2919 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 2920 { 2921 error_setg(errp, QERR_UNSUPPORTED); 2922 return -1; 2923 } 2924 2925 void qmp_guest_set_user_password(const char *username, 2926 const char *password, 2927 bool crypted, 2928 Error **errp) 2929 { 2930 error_setg(errp, QERR_UNSUPPORTED); 2931 } 2932 2933 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 2934 { 2935 error_setg(errp, QERR_UNSUPPORTED); 2936 return NULL; 2937 } 2938 2939 GuestMemoryBlockResponseList * 2940 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 2941 { 2942 error_setg(errp, QERR_UNSUPPORTED); 2943 return NULL; 2944 } 2945 2946 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 2947 { 2948 error_setg(errp, QERR_UNSUPPORTED); 2949 return NULL; 2950 } 2951 2952 #endif 2953 2954 #ifdef HAVE_GETIFADDRS 2955 static GuestNetworkInterface * 2956 guest_find_interface(GuestNetworkInterfaceList *head, 2957 const char *name) 2958 { 2959 for (; head; head = head->next) { 2960 if (strcmp(head->value->name, name) == 0) { 2961 return head->value; 2962 } 2963 } 2964 2965 return NULL; 2966 } 2967 2968 static int guest_get_network_stats(const char *name, 2969 GuestNetworkInterfaceStat *stats) 2970 { 2971 #ifdef CONFIG_LINUX 2972 int name_len; 2973 char const *devinfo = "/proc/net/dev"; 2974 FILE *fp; 2975 char *line = NULL, *colon; 2976 size_t n = 0; 2977 fp = fopen(devinfo, "r"); 2978 if (!fp) { 2979 g_debug("failed to open network stats %s: %s", devinfo, 2980 g_strerror(errno)); 2981 return -1; 2982 } 2983 name_len = strlen(name); 2984 while (getline(&line, &n, fp) != -1) { 2985 long long dummy; 2986 long long rx_bytes; 2987 long long rx_packets; 2988 long long rx_errs; 2989 long long rx_dropped; 2990 long long tx_bytes; 2991 long long tx_packets; 2992 long long tx_errs; 2993 long long tx_dropped; 2994 char *trim_line; 2995 trim_line = g_strchug(line); 2996 if (trim_line[0] == '\0') { 2997 continue; 2998 } 2999 colon = strchr(trim_line, ':'); 3000 if (!colon) { 3001 continue; 3002 } 3003 if (colon - name_len == trim_line && 3004 strncmp(trim_line, name, name_len) == 0) { 3005 if (sscanf(colon + 1, 3006 "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", 3007 &rx_bytes, &rx_packets, &rx_errs, &rx_dropped, 3008 &dummy, &dummy, &dummy, &dummy, 3009 &tx_bytes, &tx_packets, &tx_errs, &tx_dropped, 3010 &dummy, &dummy, &dummy, &dummy) != 16) { 3011 continue; 3012 } 3013 stats->rx_bytes = rx_bytes; 3014 stats->rx_packets = rx_packets; 3015 stats->rx_errs = rx_errs; 3016 stats->rx_dropped = rx_dropped; 3017 stats->tx_bytes = tx_bytes; 3018 stats->tx_packets = tx_packets; 3019 stats->tx_errs = tx_errs; 3020 stats->tx_dropped = tx_dropped; 3021 fclose(fp); 3022 g_free(line); 3023 return 0; 3024 } 3025 } 3026 fclose(fp); 3027 g_free(line); 3028 g_debug("/proc/net/dev: Interface '%s' not found", name); 3029 #else /* !CONFIG_LINUX */ 3030 g_debug("Network stats reporting available only for Linux"); 3031 #endif /* !CONFIG_LINUX */ 3032 return -1; 3033 } 3034 3035 /* 3036 * Build information about guest interfaces 3037 */ 3038 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 3039 { 3040 GuestNetworkInterfaceList *head = NULL, **tail = &head; 3041 struct ifaddrs *ifap, *ifa; 3042 3043 if (getifaddrs(&ifap) < 0) { 3044 error_setg_errno(errp, errno, "getifaddrs failed"); 3045 goto error; 3046 } 3047 3048 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 3049 GuestNetworkInterface *info; 3050 GuestIpAddressList **address_tail; 3051 GuestIpAddress *address_item = NULL; 3052 GuestNetworkInterfaceStat *interface_stat = NULL; 3053 char addr4[INET_ADDRSTRLEN]; 3054 char addr6[INET6_ADDRSTRLEN]; 3055 int sock; 3056 struct ifreq ifr; 3057 unsigned char *mac_addr; 3058 void *p; 3059 3060 g_debug("Processing %s interface", ifa->ifa_name); 3061 3062 info = guest_find_interface(head, ifa->ifa_name); 3063 3064 if (!info) { 3065 info = g_malloc0(sizeof(*info)); 3066 info->name = g_strdup(ifa->ifa_name); 3067 3068 QAPI_LIST_APPEND(tail, info); 3069 } 3070 3071 if (!info->has_hardware_address) { 3072 /* we haven't obtained HW address yet */ 3073 sock = socket(PF_INET, SOCK_STREAM, 0); 3074 if (sock == -1) { 3075 error_setg_errno(errp, errno, "failed to create socket"); 3076 goto error; 3077 } 3078 3079 memset(&ifr, 0, sizeof(ifr)); 3080 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->name); 3081 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { 3082 /* 3083 * We can't get the hw addr of this interface, but that's not a 3084 * fatal error. Don't set info->hardware_address, but keep 3085 * going. 3086 */ 3087 if (errno == EADDRNOTAVAIL) { 3088 /* The interface doesn't have a hw addr (e.g. loopback). */ 3089 g_debug("failed to get MAC address of %s: %s", 3090 ifa->ifa_name, strerror(errno)); 3091 } else{ 3092 g_warning("failed to get MAC address of %s: %s", 3093 ifa->ifa_name, strerror(errno)); 3094 } 3095 3096 } else { 3097 #ifdef CONFIG_SOLARIS 3098 mac_addr = (unsigned char *) &ifr.ifr_addr.sa_data; 3099 #else 3100 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 3101 #endif 3102 info->hardware_address = 3103 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", 3104 (int) mac_addr[0], (int) mac_addr[1], 3105 (int) mac_addr[2], (int) mac_addr[3], 3106 (int) mac_addr[4], (int) mac_addr[5]); 3107 3108 info->has_hardware_address = true; 3109 } 3110 close(sock); 3111 } 3112 3113 if (ifa->ifa_addr && 3114 ifa->ifa_addr->sa_family == AF_INET) { 3115 /* interface with IPv4 address */ 3116 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; 3117 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) { 3118 error_setg_errno(errp, errno, "inet_ntop failed"); 3119 goto error; 3120 } 3121 3122 address_item = g_malloc0(sizeof(*address_item)); 3123 address_item->ip_address = g_strdup(addr4); 3124 address_item->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4; 3125 3126 if (ifa->ifa_netmask) { 3127 /* Count the number of set bits in netmask. 3128 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 3129 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; 3130 address_item->prefix = ctpop32(((uint32_t *) p)[0]); 3131 } 3132 } else if (ifa->ifa_addr && 3133 ifa->ifa_addr->sa_family == AF_INET6) { 3134 /* interface with IPv6 address */ 3135 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; 3136 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) { 3137 error_setg_errno(errp, errno, "inet_ntop failed"); 3138 goto error; 3139 } 3140 3141 address_item = g_malloc0(sizeof(*address_item)); 3142 address_item->ip_address = g_strdup(addr6); 3143 address_item->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6; 3144 3145 if (ifa->ifa_netmask) { 3146 /* Count the number of set bits in netmask. 3147 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 3148 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; 3149 address_item->prefix = 3150 ctpop32(((uint32_t *) p)[0]) + 3151 ctpop32(((uint32_t *) p)[1]) + 3152 ctpop32(((uint32_t *) p)[2]) + 3153 ctpop32(((uint32_t *) p)[3]); 3154 } 3155 } 3156 3157 if (!address_item) { 3158 continue; 3159 } 3160 3161 address_tail = &info->ip_addresses; 3162 while (*address_tail) { 3163 address_tail = &(*address_tail)->next; 3164 } 3165 QAPI_LIST_APPEND(address_tail, address_item); 3166 3167 info->has_ip_addresses = true; 3168 3169 if (!info->has_statistics) { 3170 interface_stat = g_malloc0(sizeof(*interface_stat)); 3171 if (guest_get_network_stats(info->name, interface_stat) == -1) { 3172 info->has_statistics = false; 3173 g_free(interface_stat); 3174 } else { 3175 info->statistics = interface_stat; 3176 info->has_statistics = true; 3177 } 3178 } 3179 } 3180 3181 freeifaddrs(ifap); 3182 return head; 3183 3184 error: 3185 freeifaddrs(ifap); 3186 qapi_free_GuestNetworkInterfaceList(head); 3187 return NULL; 3188 } 3189 3190 #else 3191 3192 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 3193 { 3194 error_setg(errp, QERR_UNSUPPORTED); 3195 return NULL; 3196 } 3197 3198 #endif /* HAVE_GETIFADDRS */ 3199 3200 #if !defined(CONFIG_FSFREEZE) 3201 3202 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 3203 { 3204 error_setg(errp, QERR_UNSUPPORTED); 3205 return NULL; 3206 } 3207 3208 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 3209 { 3210 error_setg(errp, QERR_UNSUPPORTED); 3211 3212 return 0; 3213 } 3214 3215 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 3216 { 3217 error_setg(errp, QERR_UNSUPPORTED); 3218 3219 return 0; 3220 } 3221 3222 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 3223 strList *mountpoints, 3224 Error **errp) 3225 { 3226 error_setg(errp, QERR_UNSUPPORTED); 3227 3228 return 0; 3229 } 3230 3231 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 3232 { 3233 error_setg(errp, QERR_UNSUPPORTED); 3234 3235 return 0; 3236 } 3237 3238 GuestDiskInfoList *qmp_guest_get_disks(Error **errp) 3239 { 3240 error_setg(errp, QERR_UNSUPPORTED); 3241 return NULL; 3242 } 3243 3244 GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp) 3245 { 3246 error_setg(errp, QERR_UNSUPPORTED); 3247 return NULL; 3248 } 3249 3250 3251 #endif /* CONFIG_FSFREEZE */ 3252 3253 #if !defined(CONFIG_FSTRIM) 3254 GuestFilesystemTrimResponse * 3255 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 3256 { 3257 error_setg(errp, QERR_UNSUPPORTED); 3258 return NULL; 3259 } 3260 #endif 3261 3262 /* add unsupported commands to the blacklist */ 3263 GList *ga_command_blacklist_init(GList *blacklist) 3264 { 3265 #if !defined(__linux__) 3266 { 3267 const char *list[] = { 3268 "guest-suspend-disk", "guest-suspend-ram", 3269 "guest-suspend-hybrid", "guest-get-vcpus", "guest-set-vcpus", 3270 "guest-get-memory-blocks", "guest-set-memory-blocks", 3271 "guest-get-memory-block-size", "guest-get-memory-block-info", 3272 NULL}; 3273 char **p = (char **)list; 3274 3275 while (*p) { 3276 blacklist = g_list_append(blacklist, g_strdup(*p++)); 3277 } 3278 } 3279 #endif 3280 3281 #if !defined(HAVE_GETIFADDRS) 3282 blacklist = g_list_append(blacklist, 3283 g_strdup("guest-network-get-interfaces")); 3284 #endif 3285 3286 #if !defined(CONFIG_FSFREEZE) 3287 { 3288 const char *list[] = { 3289 "guest-get-fsinfo", "guest-fsfreeze-status", 3290 "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list", 3291 "guest-fsfreeze-thaw", "guest-get-fsinfo", 3292 "guest-get-disks", NULL}; 3293 char **p = (char **)list; 3294 3295 while (*p) { 3296 blacklist = g_list_append(blacklist, g_strdup(*p++)); 3297 } 3298 } 3299 #endif 3300 3301 #if !defined(CONFIG_FSTRIM) 3302 blacklist = g_list_append(blacklist, g_strdup("guest-fstrim")); 3303 #endif 3304 3305 blacklist = g_list_append(blacklist, g_strdup("guest-get-devices")); 3306 3307 return blacklist; 3308 } 3309 3310 /* register init/cleanup routines for stateful command groups */ 3311 void ga_command_state_init(GAState *s, GACommandState *cs) 3312 { 3313 #if defined(CONFIG_FSFREEZE) 3314 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); 3315 #endif 3316 } 3317 3318 #ifdef HAVE_UTMPX 3319 3320 #define QGA_MICRO_SECOND_TO_SECOND 1000000 3321 3322 static double ga_get_login_time(struct utmpx *user_info) 3323 { 3324 double seconds = (double)user_info->ut_tv.tv_sec; 3325 double useconds = (double)user_info->ut_tv.tv_usec; 3326 useconds /= QGA_MICRO_SECOND_TO_SECOND; 3327 return seconds + useconds; 3328 } 3329 3330 GuestUserList *qmp_guest_get_users(Error **errp) 3331 { 3332 GHashTable *cache = NULL; 3333 GuestUserList *head = NULL, **tail = &head; 3334 struct utmpx *user_info = NULL; 3335 gpointer value = NULL; 3336 GuestUser *user = NULL; 3337 double login_time = 0; 3338 3339 cache = g_hash_table_new(g_str_hash, g_str_equal); 3340 setutxent(); 3341 3342 for (;;) { 3343 user_info = getutxent(); 3344 if (user_info == NULL) { 3345 break; 3346 } else if (user_info->ut_type != USER_PROCESS) { 3347 continue; 3348 } else if (g_hash_table_contains(cache, user_info->ut_user)) { 3349 value = g_hash_table_lookup(cache, user_info->ut_user); 3350 user = (GuestUser *)value; 3351 login_time = ga_get_login_time(user_info); 3352 /* We're ensuring the earliest login time to be sent */ 3353 if (login_time < user->login_time) { 3354 user->login_time = login_time; 3355 } 3356 continue; 3357 } 3358 3359 user = g_new0(GuestUser, 1); 3360 user->user = g_strdup(user_info->ut_user); 3361 user->login_time = ga_get_login_time(user_info); 3362 3363 g_hash_table_insert(cache, user->user, user); 3364 3365 QAPI_LIST_APPEND(tail, user); 3366 } 3367 endutxent(); 3368 g_hash_table_destroy(cache); 3369 return head; 3370 } 3371 3372 #else 3373 3374 GuestUserList *qmp_guest_get_users(Error **errp) 3375 { 3376 error_setg(errp, QERR_UNSUPPORTED); 3377 return NULL; 3378 } 3379 3380 #endif 3381 3382 /* Replace escaped special characters with theire real values. The replacement 3383 * is done in place -- returned value is in the original string. 3384 */ 3385 static void ga_osrelease_replace_special(gchar *value) 3386 { 3387 gchar *p, *p2, quote; 3388 3389 /* Trim the string at first space or semicolon if it is not enclosed in 3390 * single or double quotes. */ 3391 if ((value[0] != '"') || (value[0] == '\'')) { 3392 p = strchr(value, ' '); 3393 if (p != NULL) { 3394 *p = 0; 3395 } 3396 p = strchr(value, ';'); 3397 if (p != NULL) { 3398 *p = 0; 3399 } 3400 return; 3401 } 3402 3403 quote = value[0]; 3404 p2 = value; 3405 p = value + 1; 3406 while (*p != 0) { 3407 if (*p == '\\') { 3408 p++; 3409 switch (*p) { 3410 case '$': 3411 case '\'': 3412 case '"': 3413 case '\\': 3414 case '`': 3415 break; 3416 default: 3417 /* Keep literal backslash followed by whatever is there */ 3418 p--; 3419 break; 3420 } 3421 } else if (*p == quote) { 3422 *p2 = 0; 3423 break; 3424 } 3425 *(p2++) = *(p++); 3426 } 3427 } 3428 3429 static GKeyFile *ga_parse_osrelease(const char *fname) 3430 { 3431 gchar *content = NULL; 3432 gchar *content2 = NULL; 3433 GError *err = NULL; 3434 GKeyFile *keys = g_key_file_new(); 3435 const char *group = "[os-release]\n"; 3436 3437 if (!g_file_get_contents(fname, &content, NULL, &err)) { 3438 slog("failed to read '%s', error: %s", fname, err->message); 3439 goto fail; 3440 } 3441 3442 if (!g_utf8_validate(content, -1, NULL)) { 3443 slog("file is not utf-8 encoded: %s", fname); 3444 goto fail; 3445 } 3446 content2 = g_strdup_printf("%s%s", group, content); 3447 3448 if (!g_key_file_load_from_data(keys, content2, -1, G_KEY_FILE_NONE, 3449 &err)) { 3450 slog("failed to parse file '%s', error: %s", fname, err->message); 3451 goto fail; 3452 } 3453 3454 g_free(content); 3455 g_free(content2); 3456 return keys; 3457 3458 fail: 3459 g_error_free(err); 3460 g_free(content); 3461 g_free(content2); 3462 g_key_file_free(keys); 3463 return NULL; 3464 } 3465 3466 GuestOSInfo *qmp_guest_get_osinfo(Error **errp) 3467 { 3468 GuestOSInfo *info = NULL; 3469 struct utsname kinfo; 3470 GKeyFile *osrelease = NULL; 3471 const char *qga_os_release = g_getenv("QGA_OS_RELEASE"); 3472 3473 info = g_new0(GuestOSInfo, 1); 3474 3475 if (uname(&kinfo) != 0) { 3476 error_setg_errno(errp, errno, "uname failed"); 3477 } else { 3478 info->has_kernel_version = true; 3479 info->kernel_version = g_strdup(kinfo.version); 3480 info->has_kernel_release = true; 3481 info->kernel_release = g_strdup(kinfo.release); 3482 info->has_machine = true; 3483 info->machine = g_strdup(kinfo.machine); 3484 } 3485 3486 if (qga_os_release != NULL) { 3487 osrelease = ga_parse_osrelease(qga_os_release); 3488 } else { 3489 osrelease = ga_parse_osrelease("/etc/os-release"); 3490 if (osrelease == NULL) { 3491 osrelease = ga_parse_osrelease("/usr/lib/os-release"); 3492 } 3493 } 3494 3495 if (osrelease != NULL) { 3496 char *value; 3497 3498 #define GET_FIELD(field, osfield) do { \ 3499 value = g_key_file_get_value(osrelease, "os-release", osfield, NULL); \ 3500 if (value != NULL) { \ 3501 ga_osrelease_replace_special(value); \ 3502 info->has_ ## field = true; \ 3503 info->field = value; \ 3504 } \ 3505 } while (0) 3506 GET_FIELD(id, "ID"); 3507 GET_FIELD(name, "NAME"); 3508 GET_FIELD(pretty_name, "PRETTY_NAME"); 3509 GET_FIELD(version, "VERSION"); 3510 GET_FIELD(version_id, "VERSION_ID"); 3511 GET_FIELD(variant, "VARIANT"); 3512 GET_FIELD(variant_id, "VARIANT_ID"); 3513 #undef GET_FIELD 3514 3515 g_key_file_free(osrelease); 3516 } 3517 3518 return info; 3519 } 3520 3521 GuestDeviceInfoList *qmp_guest_get_devices(Error **errp) 3522 { 3523 error_setg(errp, QERR_UNSUPPORTED); 3524 3525 return NULL; 3526 } 3527 3528 #ifndef HOST_NAME_MAX 3529 # ifdef _POSIX_HOST_NAME_MAX 3530 # define HOST_NAME_MAX _POSIX_HOST_NAME_MAX 3531 # else 3532 # define HOST_NAME_MAX 255 3533 # endif 3534 #endif 3535 3536 char *qga_get_host_name(Error **errp) 3537 { 3538 long len = -1; 3539 g_autofree char *hostname = NULL; 3540 3541 #ifdef _SC_HOST_NAME_MAX 3542 len = sysconf(_SC_HOST_NAME_MAX); 3543 #endif /* _SC_HOST_NAME_MAX */ 3544 3545 if (len < 0) { 3546 len = HOST_NAME_MAX; 3547 } 3548 3549 /* Unfortunately, gethostname() below does not guarantee a 3550 * NULL terminated string. Therefore, allocate one byte more 3551 * to be sure. */ 3552 hostname = g_new0(char, len + 1); 3553 3554 if (gethostname(hostname, len) < 0) { 3555 error_setg_errno(errp, errno, 3556 "cannot get hostname"); 3557 return NULL; 3558 } 3559 3560 return g_steal_pointer(&hostname); 3561 } 3562