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 "qemu-common.h" 20 #include "guest-agent-core.h" 21 #include "qga-qapi-commands.h" 22 #include "qapi/error.h" 23 #include "qapi/qmp/qerror.h" 24 #include "qemu/queue.h" 25 #include "qemu/host-utils.h" 26 #include "qemu/sockets.h" 27 #include "qemu/base64.h" 28 #include "qemu/cutils.h" 29 30 #ifdef HAVE_UTMPX 31 #include <utmpx.h> 32 #endif 33 34 #ifndef CONFIG_HAS_ENVIRON 35 #ifdef __APPLE__ 36 #include <crt_externs.h> 37 #define environ (*_NSGetEnviron()) 38 #else 39 extern char **environ; 40 #endif 41 #endif 42 43 #if defined(__linux__) 44 #include <mntent.h> 45 #include <linux/fs.h> 46 #include <ifaddrs.h> 47 #include <arpa/inet.h> 48 #include <sys/socket.h> 49 #include <net/if.h> 50 #include <sys/statvfs.h> 51 52 #ifdef CONFIG_LIBUDEV 53 #include <libudev.h> 54 #endif 55 56 #ifdef FIFREEZE 57 #define CONFIG_FSFREEZE 58 #endif 59 #ifdef FITRIM 60 #define CONFIG_FSTRIM 61 #endif 62 #endif 63 64 static void ga_wait_child(pid_t pid, int *status, Error **errp) 65 { 66 pid_t rpid; 67 68 *status = 0; 69 70 do { 71 rpid = waitpid(pid, status, 0); 72 } while (rpid == -1 && errno == EINTR); 73 74 if (rpid == -1) { 75 error_setg_errno(errp, errno, "failed to wait for child (pid: %d)", 76 pid); 77 return; 78 } 79 80 g_assert(rpid == pid); 81 } 82 83 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **errp) 84 { 85 const char *shutdown_flag; 86 Error *local_err = NULL; 87 pid_t pid; 88 int status; 89 90 slog("guest-shutdown called, mode: %s", mode); 91 if (!has_mode || strcmp(mode, "powerdown") == 0) { 92 shutdown_flag = "-P"; 93 } else if (strcmp(mode, "halt") == 0) { 94 shutdown_flag = "-H"; 95 } else if (strcmp(mode, "reboot") == 0) { 96 shutdown_flag = "-r"; 97 } else { 98 error_setg(errp, 99 "mode is invalid (valid values are: halt|powerdown|reboot"); 100 return; 101 } 102 103 pid = fork(); 104 if (pid == 0) { 105 /* child, start the shutdown */ 106 setsid(); 107 reopen_fd_to_null(0); 108 reopen_fd_to_null(1); 109 reopen_fd_to_null(2); 110 111 execle("/sbin/shutdown", "shutdown", "-h", shutdown_flag, "+0", 112 "hypervisor initiated shutdown", (char*)NULL, environ); 113 _exit(EXIT_FAILURE); 114 } else if (pid < 0) { 115 error_setg_errno(errp, errno, "failed to create child process"); 116 return; 117 } 118 119 ga_wait_child(pid, &status, &local_err); 120 if (local_err) { 121 error_propagate(errp, local_err); 122 return; 123 } 124 125 if (!WIFEXITED(status)) { 126 error_setg(errp, "child process has terminated abnormally"); 127 return; 128 } 129 130 if (WEXITSTATUS(status)) { 131 error_setg(errp, "child process has failed to shutdown"); 132 return; 133 } 134 135 /* succeeded */ 136 } 137 138 int64_t qmp_guest_get_time(Error **errp) 139 { 140 int ret; 141 qemu_timeval tq; 142 143 ret = qemu_gettimeofday(&tq); 144 if (ret < 0) { 145 error_setg_errno(errp, errno, "Failed to get time"); 146 return -1; 147 } 148 149 return tq.tv_sec * 1000000000LL + tq.tv_usec * 1000; 150 } 151 152 void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp) 153 { 154 int ret; 155 int status; 156 pid_t pid; 157 Error *local_err = NULL; 158 struct timeval tv; 159 160 /* If user has passed a time, validate and set it. */ 161 if (has_time) { 162 GDate date = { 0, }; 163 164 /* year-2038 will overflow in case time_t is 32bit */ 165 if (time_ns / 1000000000 != (time_t)(time_ns / 1000000000)) { 166 error_setg(errp, "Time %" PRId64 " is too large", time_ns); 167 return; 168 } 169 170 tv.tv_sec = time_ns / 1000000000; 171 tv.tv_usec = (time_ns % 1000000000) / 1000; 172 g_date_set_time_t(&date, tv.tv_sec); 173 if (date.year < 1970 || date.year >= 2070) { 174 error_setg_errno(errp, errno, "Invalid time"); 175 return; 176 } 177 178 ret = settimeofday(&tv, NULL); 179 if (ret < 0) { 180 error_setg_errno(errp, errno, "Failed to set time to guest"); 181 return; 182 } 183 } 184 185 /* Now, if user has passed a time to set and the system time is set, we 186 * just need to synchronize the hardware clock. However, if no time was 187 * passed, user is requesting the opposite: set the system time from the 188 * hardware clock (RTC). */ 189 pid = fork(); 190 if (pid == 0) { 191 setsid(); 192 reopen_fd_to_null(0); 193 reopen_fd_to_null(1); 194 reopen_fd_to_null(2); 195 196 /* Use '/sbin/hwclock -w' to set RTC from the system time, 197 * or '/sbin/hwclock -s' to set the system time from RTC. */ 198 execle("/sbin/hwclock", "hwclock", has_time ? "-w" : "-s", 199 NULL, environ); 200 _exit(EXIT_FAILURE); 201 } else if (pid < 0) { 202 error_setg_errno(errp, errno, "failed to create child process"); 203 return; 204 } 205 206 ga_wait_child(pid, &status, &local_err); 207 if (local_err) { 208 error_propagate(errp, local_err); 209 return; 210 } 211 212 if (!WIFEXITED(status)) { 213 error_setg(errp, "child process has terminated abnormally"); 214 return; 215 } 216 217 if (WEXITSTATUS(status)) { 218 error_setg(errp, "hwclock failed to set hardware clock to system time"); 219 return; 220 } 221 } 222 223 typedef enum { 224 RW_STATE_NEW, 225 RW_STATE_READING, 226 RW_STATE_WRITING, 227 } RwState; 228 229 typedef struct GuestFileHandle { 230 uint64_t id; 231 FILE *fh; 232 RwState state; 233 QTAILQ_ENTRY(GuestFileHandle) next; 234 } GuestFileHandle; 235 236 static struct { 237 QTAILQ_HEAD(, GuestFileHandle) filehandles; 238 } guest_file_state = { 239 .filehandles = QTAILQ_HEAD_INITIALIZER(guest_file_state.filehandles), 240 }; 241 242 static int64_t guest_file_handle_add(FILE *fh, Error **errp) 243 { 244 GuestFileHandle *gfh; 245 int64_t handle; 246 247 handle = ga_get_fd_handle(ga_state, errp); 248 if (handle < 0) { 249 return -1; 250 } 251 252 gfh = g_new0(GuestFileHandle, 1); 253 gfh->id = handle; 254 gfh->fh = fh; 255 QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next); 256 257 return handle; 258 } 259 260 static GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp) 261 { 262 GuestFileHandle *gfh; 263 264 QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next) 265 { 266 if (gfh->id == id) { 267 return gfh; 268 } 269 } 270 271 error_setg(errp, "handle '%" PRId64 "' has not been found", id); 272 return NULL; 273 } 274 275 typedef const char * const ccpc; 276 277 #ifndef O_BINARY 278 #define O_BINARY 0 279 #endif 280 281 /* http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html */ 282 static const struct { 283 ccpc *forms; 284 int oflag_base; 285 } guest_file_open_modes[] = { 286 { (ccpc[]){ "r", NULL }, O_RDONLY }, 287 { (ccpc[]){ "rb", NULL }, O_RDONLY | O_BINARY }, 288 { (ccpc[]){ "w", NULL }, O_WRONLY | O_CREAT | O_TRUNC }, 289 { (ccpc[]){ "wb", NULL }, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY }, 290 { (ccpc[]){ "a", NULL }, O_WRONLY | O_CREAT | O_APPEND }, 291 { (ccpc[]){ "ab", NULL }, O_WRONLY | O_CREAT | O_APPEND | O_BINARY }, 292 { (ccpc[]){ "r+", NULL }, O_RDWR }, 293 { (ccpc[]){ "rb+", "r+b", NULL }, O_RDWR | O_BINARY }, 294 { (ccpc[]){ "w+", NULL }, O_RDWR | O_CREAT | O_TRUNC }, 295 { (ccpc[]){ "wb+", "w+b", NULL }, O_RDWR | O_CREAT | O_TRUNC | O_BINARY }, 296 { (ccpc[]){ "a+", NULL }, O_RDWR | O_CREAT | O_APPEND }, 297 { (ccpc[]){ "ab+", "a+b", NULL }, O_RDWR | O_CREAT | O_APPEND | O_BINARY } 298 }; 299 300 static int 301 find_open_flag(const char *mode_str, Error **errp) 302 { 303 unsigned mode; 304 305 for (mode = 0; mode < ARRAY_SIZE(guest_file_open_modes); ++mode) { 306 ccpc *form; 307 308 form = guest_file_open_modes[mode].forms; 309 while (*form != NULL && strcmp(*form, mode_str) != 0) { 310 ++form; 311 } 312 if (*form != NULL) { 313 break; 314 } 315 } 316 317 if (mode == ARRAY_SIZE(guest_file_open_modes)) { 318 error_setg(errp, "invalid file open mode '%s'", mode_str); 319 return -1; 320 } 321 return guest_file_open_modes[mode].oflag_base | O_NOCTTY | O_NONBLOCK; 322 } 323 324 #define DEFAULT_NEW_FILE_MODE (S_IRUSR | S_IWUSR | \ 325 S_IRGRP | S_IWGRP | \ 326 S_IROTH | S_IWOTH) 327 328 static FILE * 329 safe_open_or_create(const char *path, const char *mode, Error **errp) 330 { 331 Error *local_err = NULL; 332 int oflag; 333 334 oflag = find_open_flag(mode, &local_err); 335 if (local_err == NULL) { 336 int fd; 337 338 /* If the caller wants / allows creation of a new file, we implement it 339 * with a two step process: open() + (open() / fchmod()). 340 * 341 * First we insist on creating the file exclusively as a new file. If 342 * that succeeds, we're free to set any file-mode bits on it. (The 343 * motivation is that we want to set those file-mode bits independently 344 * of the current umask.) 345 * 346 * If the exclusive creation fails because the file already exists 347 * (EEXIST is not possible for any other reason), we just attempt to 348 * open the file, but in this case we won't be allowed to change the 349 * file-mode bits on the preexistent file. 350 * 351 * The pathname should never disappear between the two open()s in 352 * practice. If it happens, then someone very likely tried to race us. 353 * In this case just go ahead and report the ENOENT from the second 354 * open() to the caller. 355 * 356 * If the caller wants to open a preexistent file, then the first 357 * open() is decisive and its third argument is ignored, and the second 358 * open() and the fchmod() are never called. 359 */ 360 fd = open(path, oflag | ((oflag & O_CREAT) ? O_EXCL : 0), 0); 361 if (fd == -1 && errno == EEXIST) { 362 oflag &= ~(unsigned)O_CREAT; 363 fd = open(path, oflag); 364 } 365 366 if (fd == -1) { 367 error_setg_errno(&local_err, errno, "failed to open file '%s' " 368 "(mode: '%s')", path, mode); 369 } else { 370 qemu_set_cloexec(fd); 371 372 if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) { 373 error_setg_errno(&local_err, errno, "failed to set permission " 374 "0%03o on new file '%s' (mode: '%s')", 375 (unsigned)DEFAULT_NEW_FILE_MODE, path, mode); 376 } else { 377 FILE *f; 378 379 f = fdopen(fd, mode); 380 if (f == NULL) { 381 error_setg_errno(&local_err, errno, "failed to associate " 382 "stdio stream with file descriptor %d, " 383 "file '%s' (mode: '%s')", fd, path, mode); 384 } else { 385 return f; 386 } 387 } 388 389 close(fd); 390 if (oflag & O_CREAT) { 391 unlink(path); 392 } 393 } 394 } 395 396 error_propagate(errp, local_err); 397 return NULL; 398 } 399 400 int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, 401 Error **errp) 402 { 403 FILE *fh; 404 Error *local_err = NULL; 405 int64_t handle; 406 407 if (!has_mode) { 408 mode = "r"; 409 } 410 slog("guest-file-open called, filepath: %s, mode: %s", path, mode); 411 fh = safe_open_or_create(path, mode, &local_err); 412 if (local_err != NULL) { 413 error_propagate(errp, local_err); 414 return -1; 415 } 416 417 /* set fd non-blocking to avoid common use cases (like reading from a 418 * named pipe) from hanging the agent 419 */ 420 qemu_set_nonblock(fileno(fh)); 421 422 handle = guest_file_handle_add(fh, errp); 423 if (handle < 0) { 424 fclose(fh); 425 return -1; 426 } 427 428 slog("guest-file-open, handle: %" PRId64, handle); 429 return handle; 430 } 431 432 void qmp_guest_file_close(int64_t handle, Error **errp) 433 { 434 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 435 int ret; 436 437 slog("guest-file-close called, handle: %" PRId64, handle); 438 if (!gfh) { 439 return; 440 } 441 442 ret = fclose(gfh->fh); 443 if (ret == EOF) { 444 error_setg_errno(errp, errno, "failed to close handle"); 445 return; 446 } 447 448 QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next); 449 g_free(gfh); 450 } 451 452 struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count, 453 int64_t count, Error **errp) 454 { 455 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 456 GuestFileRead *read_data = NULL; 457 guchar *buf; 458 FILE *fh; 459 size_t read_count; 460 461 if (!gfh) { 462 return NULL; 463 } 464 465 if (!has_count) { 466 count = QGA_READ_COUNT_DEFAULT; 467 } else if (count < 0 || count >= UINT32_MAX) { 468 error_setg(errp, "value '%" PRId64 "' is invalid for argument count", 469 count); 470 return NULL; 471 } 472 473 fh = gfh->fh; 474 475 /* explicitly flush when switching from writing to reading */ 476 if (gfh->state == RW_STATE_WRITING) { 477 int ret = fflush(fh); 478 if (ret == EOF) { 479 error_setg_errno(errp, errno, "failed to flush file"); 480 return NULL; 481 } 482 gfh->state = RW_STATE_NEW; 483 } 484 485 buf = g_malloc0(count+1); 486 read_count = fread(buf, 1, count, fh); 487 if (ferror(fh)) { 488 error_setg_errno(errp, errno, "failed to read file"); 489 slog("guest-file-read failed, handle: %" PRId64, handle); 490 } else { 491 buf[read_count] = 0; 492 read_data = g_new0(GuestFileRead, 1); 493 read_data->count = read_count; 494 read_data->eof = feof(fh); 495 if (read_count) { 496 read_data->buf_b64 = g_base64_encode(buf, read_count); 497 } 498 gfh->state = RW_STATE_READING; 499 } 500 g_free(buf); 501 clearerr(fh); 502 503 return read_data; 504 } 505 506 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64, 507 bool has_count, int64_t count, 508 Error **errp) 509 { 510 GuestFileWrite *write_data = NULL; 511 guchar *buf; 512 gsize buf_len; 513 int write_count; 514 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 515 FILE *fh; 516 517 if (!gfh) { 518 return NULL; 519 } 520 521 fh = gfh->fh; 522 523 if (gfh->state == RW_STATE_READING) { 524 int ret = fseek(fh, 0, SEEK_CUR); 525 if (ret == -1) { 526 error_setg_errno(errp, errno, "failed to seek file"); 527 return NULL; 528 } 529 gfh->state = RW_STATE_NEW; 530 } 531 532 buf = qbase64_decode(buf_b64, -1, &buf_len, errp); 533 if (!buf) { 534 return NULL; 535 } 536 537 if (!has_count) { 538 count = buf_len; 539 } else if (count < 0 || count > buf_len) { 540 error_setg(errp, "value '%" PRId64 "' is invalid for argument count", 541 count); 542 g_free(buf); 543 return NULL; 544 } 545 546 write_count = fwrite(buf, 1, count, fh); 547 if (ferror(fh)) { 548 error_setg_errno(errp, errno, "failed to write to file"); 549 slog("guest-file-write failed, handle: %" PRId64, handle); 550 } else { 551 write_data = g_new0(GuestFileWrite, 1); 552 write_data->count = write_count; 553 write_data->eof = feof(fh); 554 gfh->state = RW_STATE_WRITING; 555 } 556 g_free(buf); 557 clearerr(fh); 558 559 return write_data; 560 } 561 562 struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset, 563 GuestFileWhence *whence_code, 564 Error **errp) 565 { 566 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 567 GuestFileSeek *seek_data = NULL; 568 FILE *fh; 569 int ret; 570 int whence; 571 Error *err = NULL; 572 573 if (!gfh) { 574 return NULL; 575 } 576 577 /* We stupidly exposed 'whence':'int' in our qapi */ 578 whence = ga_parse_whence(whence_code, &err); 579 if (err) { 580 error_propagate(errp, err); 581 return NULL; 582 } 583 584 fh = gfh->fh; 585 ret = fseek(fh, offset, whence); 586 if (ret == -1) { 587 error_setg_errno(errp, errno, "failed to seek file"); 588 if (errno == ESPIPE) { 589 /* file is non-seekable, stdio shouldn't be buffering anyways */ 590 gfh->state = RW_STATE_NEW; 591 } 592 } else { 593 seek_data = g_new0(GuestFileSeek, 1); 594 seek_data->position = ftell(fh); 595 seek_data->eof = feof(fh); 596 gfh->state = RW_STATE_NEW; 597 } 598 clearerr(fh); 599 600 return seek_data; 601 } 602 603 void qmp_guest_file_flush(int64_t handle, Error **errp) 604 { 605 GuestFileHandle *gfh = guest_file_handle_find(handle, errp); 606 FILE *fh; 607 int ret; 608 609 if (!gfh) { 610 return; 611 } 612 613 fh = gfh->fh; 614 ret = fflush(fh); 615 if (ret == EOF) { 616 error_setg_errno(errp, errno, "failed to flush file"); 617 } else { 618 gfh->state = RW_STATE_NEW; 619 } 620 } 621 622 /* linux-specific implementations. avoid this if at all possible. */ 623 #if defined(__linux__) 624 625 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM) 626 typedef struct FsMount { 627 char *dirname; 628 char *devtype; 629 unsigned int devmajor, devminor; 630 QTAILQ_ENTRY(FsMount) next; 631 } FsMount; 632 633 typedef QTAILQ_HEAD(FsMountList, FsMount) FsMountList; 634 635 static void free_fs_mount_list(FsMountList *mounts) 636 { 637 FsMount *mount, *temp; 638 639 if (!mounts) { 640 return; 641 } 642 643 QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) { 644 QTAILQ_REMOVE(mounts, mount, next); 645 g_free(mount->dirname); 646 g_free(mount->devtype); 647 g_free(mount); 648 } 649 } 650 651 static int dev_major_minor(const char *devpath, 652 unsigned int *devmajor, unsigned int *devminor) 653 { 654 struct stat st; 655 656 *devmajor = 0; 657 *devminor = 0; 658 659 if (stat(devpath, &st) < 0) { 660 slog("failed to stat device file '%s': %s", devpath, strerror(errno)); 661 return -1; 662 } 663 if (S_ISDIR(st.st_mode)) { 664 /* It is bind mount */ 665 return -2; 666 } 667 if (S_ISBLK(st.st_mode)) { 668 *devmajor = major(st.st_rdev); 669 *devminor = minor(st.st_rdev); 670 return 0; 671 } 672 return -1; 673 } 674 675 /* 676 * Walk the mount table and build a list of local file systems 677 */ 678 static void build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp) 679 { 680 struct mntent *ment; 681 FsMount *mount; 682 char const *mtab = "/proc/self/mounts"; 683 FILE *fp; 684 unsigned int devmajor, devminor; 685 686 fp = setmntent(mtab, "r"); 687 if (!fp) { 688 error_setg(errp, "failed to open mtab file: '%s'", mtab); 689 return; 690 } 691 692 while ((ment = getmntent(fp))) { 693 /* 694 * An entry which device name doesn't start with a '/' is 695 * either a dummy file system or a network file system. 696 * Add special handling for smbfs and cifs as is done by 697 * coreutils as well. 698 */ 699 if ((ment->mnt_fsname[0] != '/') || 700 (strcmp(ment->mnt_type, "smbfs") == 0) || 701 (strcmp(ment->mnt_type, "cifs") == 0)) { 702 continue; 703 } 704 if (dev_major_minor(ment->mnt_fsname, &devmajor, &devminor) == -2) { 705 /* Skip bind mounts */ 706 continue; 707 } 708 709 mount = g_new0(FsMount, 1); 710 mount->dirname = g_strdup(ment->mnt_dir); 711 mount->devtype = g_strdup(ment->mnt_type); 712 mount->devmajor = devmajor; 713 mount->devminor = devminor; 714 715 QTAILQ_INSERT_TAIL(mounts, mount, next); 716 } 717 718 endmntent(fp); 719 } 720 721 static void decode_mntname(char *name, int len) 722 { 723 int i, j = 0; 724 for (i = 0; i <= len; i++) { 725 if (name[i] != '\\') { 726 name[j++] = name[i]; 727 } else if (name[i + 1] == '\\') { 728 name[j++] = '\\'; 729 i++; 730 } else if (name[i + 1] >= '0' && name[i + 1] <= '3' && 731 name[i + 2] >= '0' && name[i + 2] <= '7' && 732 name[i + 3] >= '0' && name[i + 3] <= '7') { 733 name[j++] = (name[i + 1] - '0') * 64 + 734 (name[i + 2] - '0') * 8 + 735 (name[i + 3] - '0'); 736 i += 3; 737 } else { 738 name[j++] = name[i]; 739 } 740 } 741 } 742 743 static void build_fs_mount_list(FsMountList *mounts, Error **errp) 744 { 745 FsMount *mount; 746 char const *mountinfo = "/proc/self/mountinfo"; 747 FILE *fp; 748 char *line = NULL, *dash; 749 size_t n; 750 char check; 751 unsigned int devmajor, devminor; 752 int ret, dir_s, dir_e, type_s, type_e, dev_s, dev_e; 753 754 fp = fopen(mountinfo, "r"); 755 if (!fp) { 756 build_fs_mount_list_from_mtab(mounts, errp); 757 return; 758 } 759 760 while (getline(&line, &n, fp) != -1) { 761 ret = sscanf(line, "%*u %*u %u:%u %*s %n%*s%n%c", 762 &devmajor, &devminor, &dir_s, &dir_e, &check); 763 if (ret < 3) { 764 continue; 765 } 766 dash = strstr(line + dir_e, " - "); 767 if (!dash) { 768 continue; 769 } 770 ret = sscanf(dash, " - %n%*s%n %n%*s%n%c", 771 &type_s, &type_e, &dev_s, &dev_e, &check); 772 if (ret < 1) { 773 continue; 774 } 775 line[dir_e] = 0; 776 dash[type_e] = 0; 777 dash[dev_e] = 0; 778 decode_mntname(line + dir_s, dir_e - dir_s); 779 decode_mntname(dash + dev_s, dev_e - dev_s); 780 if (devmajor == 0) { 781 /* btrfs reports major number = 0 */ 782 if (strcmp("btrfs", dash + type_s) != 0 || 783 dev_major_minor(dash + dev_s, &devmajor, &devminor) < 0) { 784 continue; 785 } 786 } 787 788 mount = g_new0(FsMount, 1); 789 mount->dirname = g_strdup(line + dir_s); 790 mount->devtype = g_strdup(dash + type_s); 791 mount->devmajor = devmajor; 792 mount->devminor = devminor; 793 794 QTAILQ_INSERT_TAIL(mounts, mount, next); 795 } 796 free(line); 797 798 fclose(fp); 799 } 800 #endif 801 802 #if defined(CONFIG_FSFREEZE) 803 804 static char *get_pci_driver(char const *syspath, int pathlen, Error **errp) 805 { 806 char *path; 807 char *dpath; 808 char *driver = NULL; 809 char buf[PATH_MAX]; 810 ssize_t len; 811 812 path = g_strndup(syspath, pathlen); 813 dpath = g_strdup_printf("%s/driver", path); 814 len = readlink(dpath, buf, sizeof(buf) - 1); 815 if (len != -1) { 816 buf[len] = 0; 817 driver = g_path_get_basename(buf); 818 } 819 g_free(dpath); 820 g_free(path); 821 return driver; 822 } 823 824 static int compare_uint(const void *_a, const void *_b) 825 { 826 unsigned int a = *(unsigned int *)_a; 827 unsigned int b = *(unsigned int *)_b; 828 829 return a < b ? -1 : a > b ? 1 : 0; 830 } 831 832 /* Walk the specified sysfs and build a sorted list of host or ata numbers */ 833 static int build_hosts(char const *syspath, char const *host, bool ata, 834 unsigned int *hosts, int hosts_max, Error **errp) 835 { 836 char *path; 837 DIR *dir; 838 struct dirent *entry; 839 int i = 0; 840 841 path = g_strndup(syspath, host - syspath); 842 dir = opendir(path); 843 if (!dir) { 844 error_setg_errno(errp, errno, "opendir(\"%s\")", path); 845 g_free(path); 846 return -1; 847 } 848 849 while (i < hosts_max) { 850 entry = readdir(dir); 851 if (!entry) { 852 break; 853 } 854 if (ata && sscanf(entry->d_name, "ata%d", hosts + i) == 1) { 855 ++i; 856 } else if (!ata && sscanf(entry->d_name, "host%d", hosts + i) == 1) { 857 ++i; 858 } 859 } 860 861 qsort(hosts, i, sizeof(hosts[0]), compare_uint); 862 863 g_free(path); 864 closedir(dir); 865 return i; 866 } 867 868 /* Store disk device info specified by @sysfs into @fs */ 869 static void build_guest_fsinfo_for_real_device(char const *syspath, 870 GuestFilesystemInfo *fs, 871 Error **errp) 872 { 873 unsigned int pci[4], host, hosts[8], tgt[3]; 874 int i, nhosts = 0, pcilen; 875 GuestDiskAddress *disk; 876 GuestPCIAddress *pciaddr; 877 GuestDiskAddressList *list = NULL; 878 bool has_ata = false, has_host = false, has_tgt = false; 879 char *p, *q, *driver = NULL; 880 #ifdef CONFIG_LIBUDEV 881 struct udev *udev = NULL; 882 struct udev_device *udevice = NULL; 883 #endif 884 885 p = strstr(syspath, "/devices/pci"); 886 if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n", 887 pci, pci + 1, pci + 2, pci + 3, &pcilen) < 4) { 888 g_debug("only pci device is supported: sysfs path '%s'", syspath); 889 return; 890 } 891 892 p += 12 + pcilen; 893 while (true) { 894 driver = get_pci_driver(syspath, p - syspath, errp); 895 if (driver && (g_str_equal(driver, "ata_piix") || 896 g_str_equal(driver, "sym53c8xx") || 897 g_str_equal(driver, "virtio-pci") || 898 g_str_equal(driver, "ahci"))) { 899 break; 900 } 901 902 g_free(driver); 903 if (sscanf(p, "/%x:%x:%x.%x%n", 904 pci, pci + 1, pci + 2, pci + 3, &pcilen) == 4) { 905 p += pcilen; 906 continue; 907 } 908 909 g_debug("unsupported driver or sysfs path '%s'", syspath); 910 return; 911 } 912 913 p = strstr(syspath, "/target"); 914 if (p && sscanf(p + 7, "%*u:%*u:%*u/%*u:%u:%u:%u", 915 tgt, tgt + 1, tgt + 2) == 3) { 916 has_tgt = true; 917 } 918 919 p = strstr(syspath, "/ata"); 920 if (p) { 921 q = p + 4; 922 has_ata = true; 923 } else { 924 p = strstr(syspath, "/host"); 925 q = p + 5; 926 } 927 if (p && sscanf(q, "%u", &host) == 1) { 928 has_host = true; 929 nhosts = build_hosts(syspath, p, has_ata, hosts, 930 ARRAY_SIZE(hosts), errp); 931 if (nhosts < 0) { 932 goto cleanup; 933 } 934 } 935 936 pciaddr = g_malloc0(sizeof(*pciaddr)); 937 pciaddr->domain = pci[0]; 938 pciaddr->bus = pci[1]; 939 pciaddr->slot = pci[2]; 940 pciaddr->function = pci[3]; 941 942 disk = g_malloc0(sizeof(*disk)); 943 disk->pci_controller = pciaddr; 944 945 list = g_malloc0(sizeof(*list)); 946 list->value = disk; 947 948 #ifdef CONFIG_LIBUDEV 949 udev = udev_new(); 950 udevice = udev_device_new_from_syspath(udev, syspath); 951 if (udev == NULL || udevice == NULL) { 952 g_debug("failed to query udev"); 953 } else { 954 const char *devnode, *serial; 955 devnode = udev_device_get_devnode(udevice); 956 if (devnode != NULL) { 957 disk->dev = g_strdup(devnode); 958 disk->has_dev = true; 959 } 960 serial = udev_device_get_property_value(udevice, "ID_SERIAL"); 961 if (serial != NULL && *serial != 0) { 962 disk->serial = g_strdup(serial); 963 disk->has_serial = true; 964 } 965 } 966 #endif 967 968 if (strcmp(driver, "ata_piix") == 0) { 969 /* a host per ide bus, target*:0:<unit>:0 */ 970 if (!has_host || !has_tgt) { 971 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 972 goto cleanup; 973 } 974 for (i = 0; i < nhosts; i++) { 975 if (host == hosts[i]) { 976 disk->bus_type = GUEST_DISK_BUS_TYPE_IDE; 977 disk->bus = i; 978 disk->unit = tgt[1]; 979 break; 980 } 981 } 982 if (i >= nhosts) { 983 g_debug("no host for '%s' (driver '%s')", syspath, driver); 984 goto cleanup; 985 } 986 } else if (strcmp(driver, "sym53c8xx") == 0) { 987 /* scsi(LSI Logic): target*:0:<unit>:0 */ 988 if (!has_tgt) { 989 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 990 goto cleanup; 991 } 992 disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI; 993 disk->unit = tgt[1]; 994 } else if (strcmp(driver, "virtio-pci") == 0) { 995 if (has_tgt) { 996 /* virtio-scsi: target*:0:0:<unit> */ 997 disk->bus_type = GUEST_DISK_BUS_TYPE_SCSI; 998 disk->unit = tgt[2]; 999 } else { 1000 /* virtio-blk: 1 disk per 1 device */ 1001 disk->bus_type = GUEST_DISK_BUS_TYPE_VIRTIO; 1002 } 1003 } else if (strcmp(driver, "ahci") == 0) { 1004 /* ahci: 1 host per 1 unit */ 1005 if (!has_host || !has_tgt) { 1006 g_debug("invalid sysfs path '%s' (driver '%s')", syspath, driver); 1007 goto cleanup; 1008 } 1009 for (i = 0; i < nhosts; i++) { 1010 if (host == hosts[i]) { 1011 disk->unit = i; 1012 disk->bus_type = GUEST_DISK_BUS_TYPE_SATA; 1013 break; 1014 } 1015 } 1016 if (i >= nhosts) { 1017 g_debug("no host for '%s' (driver '%s')", syspath, driver); 1018 goto cleanup; 1019 } 1020 } else { 1021 g_debug("unknown driver '%s' (sysfs path '%s')", driver, syspath); 1022 goto cleanup; 1023 } 1024 1025 list->next = fs->disk; 1026 fs->disk = list; 1027 goto out; 1028 1029 cleanup: 1030 if (list) { 1031 qapi_free_GuestDiskAddressList(list); 1032 } 1033 out: 1034 g_free(driver); 1035 #ifdef CONFIG_LIBUDEV 1036 udev_unref(udev); 1037 udev_device_unref(udevice); 1038 #endif 1039 return; 1040 } 1041 1042 static void build_guest_fsinfo_for_device(char const *devpath, 1043 GuestFilesystemInfo *fs, 1044 Error **errp); 1045 1046 /* Store a list of slave devices of virtual volume specified by @syspath into 1047 * @fs */ 1048 static void build_guest_fsinfo_for_virtual_device(char const *syspath, 1049 GuestFilesystemInfo *fs, 1050 Error **errp) 1051 { 1052 DIR *dir; 1053 char *dirpath; 1054 struct dirent *entry; 1055 1056 dirpath = g_strdup_printf("%s/slaves", syspath); 1057 dir = opendir(dirpath); 1058 if (!dir) { 1059 if (errno != ENOENT) { 1060 error_setg_errno(errp, errno, "opendir(\"%s\")", dirpath); 1061 } 1062 g_free(dirpath); 1063 return; 1064 } 1065 1066 for (;;) { 1067 errno = 0; 1068 entry = readdir(dir); 1069 if (entry == NULL) { 1070 if (errno) { 1071 error_setg_errno(errp, errno, "readdir(\"%s\")", dirpath); 1072 } 1073 break; 1074 } 1075 1076 if (entry->d_type == DT_LNK) { 1077 char *path; 1078 1079 g_debug(" slave device '%s'", entry->d_name); 1080 path = g_strdup_printf("%s/slaves/%s", syspath, entry->d_name); 1081 build_guest_fsinfo_for_device(path, fs, errp); 1082 g_free(path); 1083 1084 if (*errp) { 1085 break; 1086 } 1087 } 1088 } 1089 1090 g_free(dirpath); 1091 closedir(dir); 1092 } 1093 1094 /* Dispatch to functions for virtual/real device */ 1095 static void build_guest_fsinfo_for_device(char const *devpath, 1096 GuestFilesystemInfo *fs, 1097 Error **errp) 1098 { 1099 char *syspath = realpath(devpath, NULL); 1100 1101 if (!syspath) { 1102 error_setg_errno(errp, errno, "realpath(\"%s\")", devpath); 1103 return; 1104 } 1105 1106 if (!fs->name) { 1107 fs->name = g_path_get_basename(syspath); 1108 } 1109 1110 g_debug(" parse sysfs path '%s'", syspath); 1111 1112 if (strstr(syspath, "/devices/virtual/block/")) { 1113 build_guest_fsinfo_for_virtual_device(syspath, fs, errp); 1114 } else { 1115 build_guest_fsinfo_for_real_device(syspath, fs, errp); 1116 } 1117 1118 free(syspath); 1119 } 1120 1121 /* Return a list of the disk device(s)' info which @mount lies on */ 1122 static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount, 1123 Error **errp) 1124 { 1125 GuestFilesystemInfo *fs = g_malloc0(sizeof(*fs)); 1126 struct statvfs buf; 1127 unsigned long used, nonroot_total, fr_size; 1128 char *devpath = g_strdup_printf("/sys/dev/block/%u:%u", 1129 mount->devmajor, mount->devminor); 1130 1131 fs->mountpoint = g_strdup(mount->dirname); 1132 fs->type = g_strdup(mount->devtype); 1133 build_guest_fsinfo_for_device(devpath, fs, errp); 1134 1135 if (statvfs(fs->mountpoint, &buf) == 0) { 1136 fr_size = buf.f_frsize; 1137 used = buf.f_blocks - buf.f_bfree; 1138 nonroot_total = used + buf.f_bavail; 1139 fs->used_bytes = used * fr_size; 1140 fs->total_bytes = nonroot_total * fr_size; 1141 1142 fs->has_total_bytes = true; 1143 fs->has_used_bytes = true; 1144 } 1145 1146 g_free(devpath); 1147 1148 return fs; 1149 } 1150 1151 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 1152 { 1153 FsMountList mounts; 1154 struct FsMount *mount; 1155 GuestFilesystemInfoList *new, *ret = NULL; 1156 Error *local_err = NULL; 1157 1158 QTAILQ_INIT(&mounts); 1159 build_fs_mount_list(&mounts, &local_err); 1160 if (local_err) { 1161 error_propagate(errp, local_err); 1162 return NULL; 1163 } 1164 1165 QTAILQ_FOREACH(mount, &mounts, next) { 1166 g_debug("Building guest fsinfo for '%s'", mount->dirname); 1167 1168 new = g_malloc0(sizeof(*ret)); 1169 new->value = build_guest_fsinfo(mount, &local_err); 1170 new->next = ret; 1171 ret = new; 1172 if (local_err) { 1173 error_propagate(errp, local_err); 1174 qapi_free_GuestFilesystemInfoList(ret); 1175 ret = NULL; 1176 break; 1177 } 1178 } 1179 1180 free_fs_mount_list(&mounts); 1181 return ret; 1182 } 1183 1184 1185 typedef enum { 1186 FSFREEZE_HOOK_THAW = 0, 1187 FSFREEZE_HOOK_FREEZE, 1188 } FsfreezeHookArg; 1189 1190 static const char *fsfreeze_hook_arg_string[] = { 1191 "thaw", 1192 "freeze", 1193 }; 1194 1195 static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **errp) 1196 { 1197 int status; 1198 pid_t pid; 1199 const char *hook; 1200 const char *arg_str = fsfreeze_hook_arg_string[arg]; 1201 Error *local_err = NULL; 1202 1203 hook = ga_fsfreeze_hook(ga_state); 1204 if (!hook) { 1205 return; 1206 } 1207 if (access(hook, X_OK) != 0) { 1208 error_setg_errno(errp, errno, "can't access fsfreeze hook '%s'", hook); 1209 return; 1210 } 1211 1212 slog("executing fsfreeze hook with arg '%s'", arg_str); 1213 pid = fork(); 1214 if (pid == 0) { 1215 setsid(); 1216 reopen_fd_to_null(0); 1217 reopen_fd_to_null(1); 1218 reopen_fd_to_null(2); 1219 1220 execle(hook, hook, arg_str, NULL, environ); 1221 _exit(EXIT_FAILURE); 1222 } else if (pid < 0) { 1223 error_setg_errno(errp, errno, "failed to create child process"); 1224 return; 1225 } 1226 1227 ga_wait_child(pid, &status, &local_err); 1228 if (local_err) { 1229 error_propagate(errp, local_err); 1230 return; 1231 } 1232 1233 if (!WIFEXITED(status)) { 1234 error_setg(errp, "fsfreeze hook has terminated abnormally"); 1235 return; 1236 } 1237 1238 status = WEXITSTATUS(status); 1239 if (status) { 1240 error_setg(errp, "fsfreeze hook has failed with status %d", status); 1241 return; 1242 } 1243 } 1244 1245 /* 1246 * Return status of freeze/thaw 1247 */ 1248 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 1249 { 1250 if (ga_is_frozen(ga_state)) { 1251 return GUEST_FSFREEZE_STATUS_FROZEN; 1252 } 1253 1254 return GUEST_FSFREEZE_STATUS_THAWED; 1255 } 1256 1257 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 1258 { 1259 return qmp_guest_fsfreeze_freeze_list(false, NULL, errp); 1260 } 1261 1262 /* 1263 * Walk list of mounted file systems in the guest, and freeze the ones which 1264 * are real local file systems. 1265 */ 1266 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 1267 strList *mountpoints, 1268 Error **errp) 1269 { 1270 int ret = 0, i = 0; 1271 strList *list; 1272 FsMountList mounts; 1273 struct FsMount *mount; 1274 Error *local_err = NULL; 1275 int fd; 1276 1277 slog("guest-fsfreeze called"); 1278 1279 execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err); 1280 if (local_err) { 1281 error_propagate(errp, local_err); 1282 return -1; 1283 } 1284 1285 QTAILQ_INIT(&mounts); 1286 build_fs_mount_list(&mounts, &local_err); 1287 if (local_err) { 1288 error_propagate(errp, local_err); 1289 return -1; 1290 } 1291 1292 /* cannot risk guest agent blocking itself on a write in this state */ 1293 ga_set_frozen(ga_state); 1294 1295 QTAILQ_FOREACH_REVERSE(mount, &mounts, next) { 1296 /* To issue fsfreeze in the reverse order of mounts, check if the 1297 * mount is listed in the list here */ 1298 if (has_mountpoints) { 1299 for (list = mountpoints; list; list = list->next) { 1300 if (strcmp(list->value, mount->dirname) == 0) { 1301 break; 1302 } 1303 } 1304 if (!list) { 1305 continue; 1306 } 1307 } 1308 1309 fd = qemu_open(mount->dirname, O_RDONLY); 1310 if (fd == -1) { 1311 error_setg_errno(errp, errno, "failed to open %s", mount->dirname); 1312 goto error; 1313 } 1314 1315 /* we try to cull filesystems we know won't work in advance, but other 1316 * filesystems may not implement fsfreeze for less obvious reasons. 1317 * these will report EOPNOTSUPP. we simply ignore these when tallying 1318 * the number of frozen filesystems. 1319 * if a filesystem is mounted more than once (aka bind mount) a 1320 * consecutive attempt to freeze an already frozen filesystem will 1321 * return EBUSY. 1322 * 1323 * any other error means a failure to freeze a filesystem we 1324 * expect to be freezable, so return an error in those cases 1325 * and return system to thawed state. 1326 */ 1327 ret = ioctl(fd, FIFREEZE); 1328 if (ret == -1) { 1329 if (errno != EOPNOTSUPP && errno != EBUSY) { 1330 error_setg_errno(errp, errno, "failed to freeze %s", 1331 mount->dirname); 1332 close(fd); 1333 goto error; 1334 } 1335 } else { 1336 i++; 1337 } 1338 close(fd); 1339 } 1340 1341 free_fs_mount_list(&mounts); 1342 /* We may not issue any FIFREEZE here. 1343 * Just unset ga_state here and ready for the next call. 1344 */ 1345 if (i == 0) { 1346 ga_unset_frozen(ga_state); 1347 } 1348 return i; 1349 1350 error: 1351 free_fs_mount_list(&mounts); 1352 qmp_guest_fsfreeze_thaw(NULL); 1353 return 0; 1354 } 1355 1356 /* 1357 * Walk list of frozen file systems in the guest, and thaw them. 1358 */ 1359 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 1360 { 1361 int ret; 1362 FsMountList mounts; 1363 FsMount *mount; 1364 int fd, i = 0, logged; 1365 Error *local_err = NULL; 1366 1367 QTAILQ_INIT(&mounts); 1368 build_fs_mount_list(&mounts, &local_err); 1369 if (local_err) { 1370 error_propagate(errp, local_err); 1371 return 0; 1372 } 1373 1374 QTAILQ_FOREACH(mount, &mounts, next) { 1375 logged = false; 1376 fd = qemu_open(mount->dirname, O_RDONLY); 1377 if (fd == -1) { 1378 continue; 1379 } 1380 /* we have no way of knowing whether a filesystem was actually unfrozen 1381 * as a result of a successful call to FITHAW, only that if an error 1382 * was returned the filesystem was *not* unfrozen by that particular 1383 * call. 1384 * 1385 * since multiple preceding FIFREEZEs require multiple calls to FITHAW 1386 * to unfreeze, continuing issuing FITHAW until an error is returned, 1387 * in which case either the filesystem is in an unfreezable state, or, 1388 * more likely, it was thawed previously (and remains so afterward). 1389 * 1390 * also, since the most recent successful call is the one that did 1391 * the actual unfreeze, we can use this to provide an accurate count 1392 * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which 1393 * may * be useful for determining whether a filesystem was unfrozen 1394 * during the freeze/thaw phase by a process other than qemu-ga. 1395 */ 1396 do { 1397 ret = ioctl(fd, FITHAW); 1398 if (ret == 0 && !logged) { 1399 i++; 1400 logged = true; 1401 } 1402 } while (ret == 0); 1403 close(fd); 1404 } 1405 1406 ga_unset_frozen(ga_state); 1407 free_fs_mount_list(&mounts); 1408 1409 execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, errp); 1410 1411 return i; 1412 } 1413 1414 static void guest_fsfreeze_cleanup(void) 1415 { 1416 Error *err = NULL; 1417 1418 if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) { 1419 qmp_guest_fsfreeze_thaw(&err); 1420 if (err) { 1421 slog("failed to clean up frozen filesystems: %s", 1422 error_get_pretty(err)); 1423 error_free(err); 1424 } 1425 } 1426 } 1427 #endif /* CONFIG_FSFREEZE */ 1428 1429 #if defined(CONFIG_FSTRIM) 1430 /* 1431 * Walk list of mounted file systems in the guest, and trim them. 1432 */ 1433 GuestFilesystemTrimResponse * 1434 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 1435 { 1436 GuestFilesystemTrimResponse *response; 1437 GuestFilesystemTrimResultList *list; 1438 GuestFilesystemTrimResult *result; 1439 int ret = 0; 1440 FsMountList mounts; 1441 struct FsMount *mount; 1442 int fd; 1443 Error *local_err = NULL; 1444 struct fstrim_range r; 1445 1446 slog("guest-fstrim called"); 1447 1448 QTAILQ_INIT(&mounts); 1449 build_fs_mount_list(&mounts, &local_err); 1450 if (local_err) { 1451 error_propagate(errp, local_err); 1452 return NULL; 1453 } 1454 1455 response = g_malloc0(sizeof(*response)); 1456 1457 QTAILQ_FOREACH(mount, &mounts, next) { 1458 result = g_malloc0(sizeof(*result)); 1459 result->path = g_strdup(mount->dirname); 1460 1461 list = g_malloc0(sizeof(*list)); 1462 list->value = result; 1463 list->next = response->paths; 1464 response->paths = list; 1465 1466 fd = qemu_open(mount->dirname, O_RDONLY); 1467 if (fd == -1) { 1468 result->error = g_strdup_printf("failed to open: %s", 1469 strerror(errno)); 1470 result->has_error = true; 1471 continue; 1472 } 1473 1474 /* We try to cull filesystems we know won't work in advance, but other 1475 * filesystems may not implement fstrim for less obvious reasons. 1476 * These will report EOPNOTSUPP; while in some other cases ENOTTY 1477 * will be reported (e.g. CD-ROMs). 1478 * Any other error means an unexpected error. 1479 */ 1480 r.start = 0; 1481 r.len = -1; 1482 r.minlen = has_minimum ? minimum : 0; 1483 ret = ioctl(fd, FITRIM, &r); 1484 if (ret == -1) { 1485 result->has_error = true; 1486 if (errno == ENOTTY || errno == EOPNOTSUPP) { 1487 result->error = g_strdup("trim not supported"); 1488 } else { 1489 result->error = g_strdup_printf("failed to trim: %s", 1490 strerror(errno)); 1491 } 1492 close(fd); 1493 continue; 1494 } 1495 1496 result->has_minimum = true; 1497 result->minimum = r.minlen; 1498 result->has_trimmed = true; 1499 result->trimmed = r.len; 1500 close(fd); 1501 } 1502 1503 free_fs_mount_list(&mounts); 1504 return response; 1505 } 1506 #endif /* CONFIG_FSTRIM */ 1507 1508 1509 #define LINUX_SYS_STATE_FILE "/sys/power/state" 1510 #define SUSPEND_SUPPORTED 0 1511 #define SUSPEND_NOT_SUPPORTED 1 1512 1513 typedef enum { 1514 SUSPEND_MODE_DISK = 0, 1515 SUSPEND_MODE_RAM = 1, 1516 SUSPEND_MODE_HYBRID = 2, 1517 } SuspendMode; 1518 1519 /* 1520 * Executes a command in a child process using g_spawn_sync, 1521 * returning an int >= 0 representing the exit status of the 1522 * process. 1523 * 1524 * If the program wasn't found in path, returns -1. 1525 * 1526 * If a problem happened when creating the child process, 1527 * returns -1 and errp is set. 1528 */ 1529 static int run_process_child(const char *command[], Error **errp) 1530 { 1531 int exit_status, spawn_flag; 1532 GError *g_err = NULL; 1533 bool success; 1534 1535 spawn_flag = G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | 1536 G_SPAWN_STDERR_TO_DEV_NULL; 1537 1538 success = g_spawn_sync(NULL, (char **)command, environ, spawn_flag, 1539 NULL, NULL, NULL, NULL, 1540 &exit_status, &g_err); 1541 1542 if (success) { 1543 return WEXITSTATUS(exit_status); 1544 } 1545 1546 if (g_err && (g_err->code != G_SPAWN_ERROR_NOENT)) { 1547 error_setg(errp, "failed to create child process, error '%s'", 1548 g_err->message); 1549 } 1550 1551 g_error_free(g_err); 1552 return -1; 1553 } 1554 1555 static bool systemd_supports_mode(SuspendMode mode, Error **errp) 1556 { 1557 Error *local_err = NULL; 1558 const char *systemctl_args[3] = {"systemd-hibernate", "systemd-suspend", 1559 "systemd-hybrid-sleep"}; 1560 const char *cmd[4] = {"systemctl", "status", systemctl_args[mode], NULL}; 1561 int status; 1562 1563 status = run_process_child(cmd, &local_err); 1564 1565 /* 1566 * systemctl status uses LSB return codes so we can expect 1567 * status > 0 and be ok. To assert if the guest has support 1568 * for the selected suspend mode, status should be < 4. 4 is 1569 * the code for unknown service status, the return value when 1570 * the service does not exist. A common value is status = 3 1571 * (program is not running). 1572 */ 1573 if (status > 0 && status < 4) { 1574 return true; 1575 } 1576 1577 error_propagate(errp, local_err); 1578 return false; 1579 } 1580 1581 static void systemd_suspend(SuspendMode mode, Error **errp) 1582 { 1583 Error *local_err = NULL; 1584 const char *systemctl_args[3] = {"hibernate", "suspend", "hybrid-sleep"}; 1585 const char *cmd[3] = {"systemctl", systemctl_args[mode], NULL}; 1586 int status; 1587 1588 status = run_process_child(cmd, &local_err); 1589 1590 if (status == 0) { 1591 return; 1592 } 1593 1594 if ((status == -1) && !local_err) { 1595 error_setg(errp, "the helper program 'systemctl %s' was not found", 1596 systemctl_args[mode]); 1597 return; 1598 } 1599 1600 if (local_err) { 1601 error_propagate(errp, local_err); 1602 } else { 1603 error_setg(errp, "the helper program 'systemctl %s' returned an " 1604 "unexpected exit status code (%d)", 1605 systemctl_args[mode], status); 1606 } 1607 } 1608 1609 static bool pmutils_supports_mode(SuspendMode mode, Error **errp) 1610 { 1611 Error *local_err = NULL; 1612 const char *pmutils_args[3] = {"--hibernate", "--suspend", 1613 "--suspend-hybrid"}; 1614 const char *cmd[3] = {"pm-is-supported", pmutils_args[mode], NULL}; 1615 int status; 1616 1617 status = run_process_child(cmd, &local_err); 1618 1619 if (status == SUSPEND_SUPPORTED) { 1620 return true; 1621 } 1622 1623 if ((status == -1) && !local_err) { 1624 return false; 1625 } 1626 1627 if (local_err) { 1628 error_propagate(errp, local_err); 1629 } else { 1630 error_setg(errp, 1631 "the helper program '%s' returned an unexpected exit" 1632 " status code (%d)", "pm-is-supported", status); 1633 } 1634 1635 return false; 1636 } 1637 1638 static void pmutils_suspend(SuspendMode mode, Error **errp) 1639 { 1640 Error *local_err = NULL; 1641 const char *pmutils_binaries[3] = {"pm-hibernate", "pm-suspend", 1642 "pm-suspend-hybrid"}; 1643 const char *cmd[2] = {pmutils_binaries[mode], NULL}; 1644 int status; 1645 1646 status = run_process_child(cmd, &local_err); 1647 1648 if (status == 0) { 1649 return; 1650 } 1651 1652 if ((status == -1) && !local_err) { 1653 error_setg(errp, "the helper program '%s' was not found", 1654 pmutils_binaries[mode]); 1655 return; 1656 } 1657 1658 if (local_err) { 1659 error_propagate(errp, local_err); 1660 } else { 1661 error_setg(errp, 1662 "the helper program '%s' returned an unexpected exit" 1663 " status code (%d)", pmutils_binaries[mode], status); 1664 } 1665 } 1666 1667 static bool linux_sys_state_supports_mode(SuspendMode mode, Error **errp) 1668 { 1669 const char *sysfile_strs[3] = {"disk", "mem", NULL}; 1670 const char *sysfile_str = sysfile_strs[mode]; 1671 char buf[32]; /* hopefully big enough */ 1672 int fd; 1673 ssize_t ret; 1674 1675 if (!sysfile_str) { 1676 error_setg(errp, "unknown guest suspend mode"); 1677 return false; 1678 } 1679 1680 fd = open(LINUX_SYS_STATE_FILE, O_RDONLY); 1681 if (fd < 0) { 1682 return false; 1683 } 1684 1685 ret = read(fd, buf, sizeof(buf) - 1); 1686 close(fd); 1687 if (ret <= 0) { 1688 return false; 1689 } 1690 buf[ret] = '\0'; 1691 1692 if (strstr(buf, sysfile_str)) { 1693 return true; 1694 } 1695 return false; 1696 } 1697 1698 static void linux_sys_state_suspend(SuspendMode mode, Error **errp) 1699 { 1700 Error *local_err = NULL; 1701 const char *sysfile_strs[3] = {"disk", "mem", NULL}; 1702 const char *sysfile_str = sysfile_strs[mode]; 1703 pid_t pid; 1704 int status; 1705 1706 if (!sysfile_str) { 1707 error_setg(errp, "unknown guest suspend mode"); 1708 return; 1709 } 1710 1711 pid = fork(); 1712 if (!pid) { 1713 /* child */ 1714 int fd; 1715 1716 setsid(); 1717 reopen_fd_to_null(0); 1718 reopen_fd_to_null(1); 1719 reopen_fd_to_null(2); 1720 1721 fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); 1722 if (fd < 0) { 1723 _exit(EXIT_FAILURE); 1724 } 1725 1726 if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) { 1727 _exit(EXIT_FAILURE); 1728 } 1729 1730 _exit(EXIT_SUCCESS); 1731 } else if (pid < 0) { 1732 error_setg_errno(errp, errno, "failed to create child process"); 1733 return; 1734 } 1735 1736 ga_wait_child(pid, &status, &local_err); 1737 if (local_err) { 1738 error_propagate(errp, local_err); 1739 return; 1740 } 1741 1742 if (WEXITSTATUS(status)) { 1743 error_setg(errp, "child process has failed to suspend"); 1744 } 1745 1746 } 1747 1748 static void guest_suspend(SuspendMode mode, Error **errp) 1749 { 1750 Error *local_err = NULL; 1751 bool mode_supported = false; 1752 1753 if (systemd_supports_mode(mode, &local_err)) { 1754 mode_supported = true; 1755 systemd_suspend(mode, &local_err); 1756 } 1757 1758 if (!local_err) { 1759 return; 1760 } 1761 1762 error_free(local_err); 1763 1764 if (pmutils_supports_mode(mode, &local_err)) { 1765 mode_supported = true; 1766 pmutils_suspend(mode, &local_err); 1767 } 1768 1769 if (!local_err) { 1770 return; 1771 } 1772 1773 error_free(local_err); 1774 1775 if (linux_sys_state_supports_mode(mode, &local_err)) { 1776 mode_supported = true; 1777 linux_sys_state_suspend(mode, &local_err); 1778 } 1779 1780 if (!mode_supported) { 1781 error_setg(errp, 1782 "the requested suspend mode is not supported by the guest"); 1783 } else { 1784 error_propagate(errp, local_err); 1785 } 1786 } 1787 1788 void qmp_guest_suspend_disk(Error **errp) 1789 { 1790 guest_suspend(SUSPEND_MODE_DISK, errp); 1791 } 1792 1793 void qmp_guest_suspend_ram(Error **errp) 1794 { 1795 guest_suspend(SUSPEND_MODE_RAM, errp); 1796 } 1797 1798 void qmp_guest_suspend_hybrid(Error **errp) 1799 { 1800 guest_suspend(SUSPEND_MODE_HYBRID, errp); 1801 } 1802 1803 static GuestNetworkInterfaceList * 1804 guest_find_interface(GuestNetworkInterfaceList *head, 1805 const char *name) 1806 { 1807 for (; head; head = head->next) { 1808 if (strcmp(head->value->name, name) == 0) { 1809 break; 1810 } 1811 } 1812 1813 return head; 1814 } 1815 1816 static int guest_get_network_stats(const char *name, 1817 GuestNetworkInterfaceStat *stats) 1818 { 1819 int name_len; 1820 char const *devinfo = "/proc/net/dev"; 1821 FILE *fp; 1822 char *line = NULL, *colon; 1823 size_t n = 0; 1824 fp = fopen(devinfo, "r"); 1825 if (!fp) { 1826 return -1; 1827 } 1828 name_len = strlen(name); 1829 while (getline(&line, &n, fp) != -1) { 1830 long long dummy; 1831 long long rx_bytes; 1832 long long rx_packets; 1833 long long rx_errs; 1834 long long rx_dropped; 1835 long long tx_bytes; 1836 long long tx_packets; 1837 long long tx_errs; 1838 long long tx_dropped; 1839 char *trim_line; 1840 trim_line = g_strchug(line); 1841 if (trim_line[0] == '\0') { 1842 continue; 1843 } 1844 colon = strchr(trim_line, ':'); 1845 if (!colon) { 1846 continue; 1847 } 1848 if (colon - name_len == trim_line && 1849 strncmp(trim_line, name, name_len) == 0) { 1850 if (sscanf(colon + 1, 1851 "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", 1852 &rx_bytes, &rx_packets, &rx_errs, &rx_dropped, 1853 &dummy, &dummy, &dummy, &dummy, 1854 &tx_bytes, &tx_packets, &tx_errs, &tx_dropped, 1855 &dummy, &dummy, &dummy, &dummy) != 16) { 1856 continue; 1857 } 1858 stats->rx_bytes = rx_bytes; 1859 stats->rx_packets = rx_packets; 1860 stats->rx_errs = rx_errs; 1861 stats->rx_dropped = rx_dropped; 1862 stats->tx_bytes = tx_bytes; 1863 stats->tx_packets = tx_packets; 1864 stats->tx_errs = tx_errs; 1865 stats->tx_dropped = tx_dropped; 1866 fclose(fp); 1867 g_free(line); 1868 return 0; 1869 } 1870 } 1871 fclose(fp); 1872 g_free(line); 1873 g_debug("/proc/net/dev: Interface '%s' not found", name); 1874 return -1; 1875 } 1876 1877 /* 1878 * Build information about guest interfaces 1879 */ 1880 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 1881 { 1882 GuestNetworkInterfaceList *head = NULL, *cur_item = NULL; 1883 struct ifaddrs *ifap, *ifa; 1884 1885 if (getifaddrs(&ifap) < 0) { 1886 error_setg_errno(errp, errno, "getifaddrs failed"); 1887 goto error; 1888 } 1889 1890 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1891 GuestNetworkInterfaceList *info; 1892 GuestIpAddressList **address_list = NULL, *address_item = NULL; 1893 GuestNetworkInterfaceStat *interface_stat = NULL; 1894 char addr4[INET_ADDRSTRLEN]; 1895 char addr6[INET6_ADDRSTRLEN]; 1896 int sock; 1897 struct ifreq ifr; 1898 unsigned char *mac_addr; 1899 void *p; 1900 1901 g_debug("Processing %s interface", ifa->ifa_name); 1902 1903 info = guest_find_interface(head, ifa->ifa_name); 1904 1905 if (!info) { 1906 info = g_malloc0(sizeof(*info)); 1907 info->value = g_malloc0(sizeof(*info->value)); 1908 info->value->name = g_strdup(ifa->ifa_name); 1909 1910 if (!cur_item) { 1911 head = cur_item = info; 1912 } else { 1913 cur_item->next = info; 1914 cur_item = info; 1915 } 1916 } 1917 1918 if (!info->value->has_hardware_address && 1919 ifa->ifa_flags & SIOCGIFHWADDR) { 1920 /* we haven't obtained HW address yet */ 1921 sock = socket(PF_INET, SOCK_STREAM, 0); 1922 if (sock == -1) { 1923 error_setg_errno(errp, errno, "failed to create socket"); 1924 goto error; 1925 } 1926 1927 memset(&ifr, 0, sizeof(ifr)); 1928 pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name); 1929 if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { 1930 error_setg_errno(errp, errno, 1931 "failed to get MAC address of %s", 1932 ifa->ifa_name); 1933 close(sock); 1934 goto error; 1935 } 1936 1937 close(sock); 1938 mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data; 1939 1940 info->value->hardware_address = 1941 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x", 1942 (int) mac_addr[0], (int) mac_addr[1], 1943 (int) mac_addr[2], (int) mac_addr[3], 1944 (int) mac_addr[4], (int) mac_addr[5]); 1945 1946 info->value->has_hardware_address = true; 1947 } 1948 1949 if (ifa->ifa_addr && 1950 ifa->ifa_addr->sa_family == AF_INET) { 1951 /* interface with IPv4 address */ 1952 p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr; 1953 if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) { 1954 error_setg_errno(errp, errno, "inet_ntop failed"); 1955 goto error; 1956 } 1957 1958 address_item = g_malloc0(sizeof(*address_item)); 1959 address_item->value = g_malloc0(sizeof(*address_item->value)); 1960 address_item->value->ip_address = g_strdup(addr4); 1961 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4; 1962 1963 if (ifa->ifa_netmask) { 1964 /* Count the number of set bits in netmask. 1965 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 1966 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr; 1967 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]); 1968 } 1969 } else if (ifa->ifa_addr && 1970 ifa->ifa_addr->sa_family == AF_INET6) { 1971 /* interface with IPv6 address */ 1972 p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; 1973 if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) { 1974 error_setg_errno(errp, errno, "inet_ntop failed"); 1975 goto error; 1976 } 1977 1978 address_item = g_malloc0(sizeof(*address_item)); 1979 address_item->value = g_malloc0(sizeof(*address_item->value)); 1980 address_item->value->ip_address = g_strdup(addr6); 1981 address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6; 1982 1983 if (ifa->ifa_netmask) { 1984 /* Count the number of set bits in netmask. 1985 * This is safe as '1' and '0' cannot be shuffled in netmask. */ 1986 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; 1987 address_item->value->prefix = 1988 ctpop32(((uint32_t *) p)[0]) + 1989 ctpop32(((uint32_t *) p)[1]) + 1990 ctpop32(((uint32_t *) p)[2]) + 1991 ctpop32(((uint32_t *) p)[3]); 1992 } 1993 } 1994 1995 if (!address_item) { 1996 continue; 1997 } 1998 1999 address_list = &info->value->ip_addresses; 2000 2001 while (*address_list && (*address_list)->next) { 2002 address_list = &(*address_list)->next; 2003 } 2004 2005 if (!*address_list) { 2006 *address_list = address_item; 2007 } else { 2008 (*address_list)->next = address_item; 2009 } 2010 2011 info->value->has_ip_addresses = true; 2012 2013 if (!info->value->has_statistics) { 2014 interface_stat = g_malloc0(sizeof(*interface_stat)); 2015 if (guest_get_network_stats(info->value->name, 2016 interface_stat) == -1) { 2017 info->value->has_statistics = false; 2018 g_free(interface_stat); 2019 } else { 2020 info->value->statistics = interface_stat; 2021 info->value->has_statistics = true; 2022 } 2023 } 2024 } 2025 2026 freeifaddrs(ifap); 2027 return head; 2028 2029 error: 2030 freeifaddrs(ifap); 2031 qapi_free_GuestNetworkInterfaceList(head); 2032 return NULL; 2033 } 2034 2035 #define SYSCONF_EXACT(name, errp) sysconf_exact((name), #name, (errp)) 2036 2037 static long sysconf_exact(int name, const char *name_str, Error **errp) 2038 { 2039 long ret; 2040 2041 errno = 0; 2042 ret = sysconf(name); 2043 if (ret == -1) { 2044 if (errno == 0) { 2045 error_setg(errp, "sysconf(%s): value indefinite", name_str); 2046 } else { 2047 error_setg_errno(errp, errno, "sysconf(%s)", name_str); 2048 } 2049 } 2050 return ret; 2051 } 2052 2053 /* Transfer online/offline status between @vcpu and the guest system. 2054 * 2055 * On input either @errp or *@errp must be NULL. 2056 * 2057 * In system-to-@vcpu direction, the following @vcpu fields are accessed: 2058 * - R: vcpu->logical_id 2059 * - W: vcpu->online 2060 * - W: vcpu->can_offline 2061 * 2062 * In @vcpu-to-system direction, the following @vcpu fields are accessed: 2063 * - R: vcpu->logical_id 2064 * - R: vcpu->online 2065 * 2066 * Written members remain unmodified on error. 2067 */ 2068 static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu, 2069 char *dirpath, Error **errp) 2070 { 2071 int fd; 2072 int res; 2073 int dirfd; 2074 static const char fn[] = "online"; 2075 2076 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2077 if (dirfd == -1) { 2078 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2079 return; 2080 } 2081 2082 fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); 2083 if (fd == -1) { 2084 if (errno != ENOENT) { 2085 error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn); 2086 } else if (sys2vcpu) { 2087 vcpu->online = true; 2088 vcpu->can_offline = false; 2089 } else if (!vcpu->online) { 2090 error_setg(errp, "logical processor #%" PRId64 " can't be " 2091 "offlined", vcpu->logical_id); 2092 } /* otherwise pretend successful re-onlining */ 2093 } else { 2094 unsigned char status; 2095 2096 res = pread(fd, &status, 1, 0); 2097 if (res == -1) { 2098 error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn); 2099 } else if (res == 0) { 2100 error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, 2101 fn); 2102 } else if (sys2vcpu) { 2103 vcpu->online = (status != '0'); 2104 vcpu->can_offline = true; 2105 } else if (vcpu->online != (status != '0')) { 2106 status = '0' + vcpu->online; 2107 if (pwrite(fd, &status, 1, 0) == -1) { 2108 error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath, 2109 fn); 2110 } 2111 } /* otherwise pretend successful re-(on|off)-lining */ 2112 2113 res = close(fd); 2114 g_assert(res == 0); 2115 } 2116 2117 res = close(dirfd); 2118 g_assert(res == 0); 2119 } 2120 2121 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 2122 { 2123 int64_t current; 2124 GuestLogicalProcessorList *head, **link; 2125 long sc_max; 2126 Error *local_err = NULL; 2127 2128 current = 0; 2129 head = NULL; 2130 link = &head; 2131 sc_max = SYSCONF_EXACT(_SC_NPROCESSORS_CONF, &local_err); 2132 2133 while (local_err == NULL && current < sc_max) { 2134 GuestLogicalProcessor *vcpu; 2135 GuestLogicalProcessorList *entry; 2136 int64_t id = current++; 2137 char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", 2138 id); 2139 2140 if (g_file_test(path, G_FILE_TEST_EXISTS)) { 2141 vcpu = g_malloc0(sizeof *vcpu); 2142 vcpu->logical_id = id; 2143 vcpu->has_can_offline = true; /* lolspeak ftw */ 2144 transfer_vcpu(vcpu, true, path, &local_err); 2145 entry = g_malloc0(sizeof *entry); 2146 entry->value = vcpu; 2147 *link = entry; 2148 link = &entry->next; 2149 } 2150 g_free(path); 2151 } 2152 2153 if (local_err == NULL) { 2154 /* there's no guest with zero VCPUs */ 2155 g_assert(head != NULL); 2156 return head; 2157 } 2158 2159 qapi_free_GuestLogicalProcessorList(head); 2160 error_propagate(errp, local_err); 2161 return NULL; 2162 } 2163 2164 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 2165 { 2166 int64_t processed; 2167 Error *local_err = NULL; 2168 2169 processed = 0; 2170 while (vcpus != NULL) { 2171 char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", 2172 vcpus->value->logical_id); 2173 2174 transfer_vcpu(vcpus->value, false, path, &local_err); 2175 g_free(path); 2176 if (local_err != NULL) { 2177 break; 2178 } 2179 ++processed; 2180 vcpus = vcpus->next; 2181 } 2182 2183 if (local_err != NULL) { 2184 if (processed == 0) { 2185 error_propagate(errp, local_err); 2186 } else { 2187 error_free(local_err); 2188 } 2189 } 2190 2191 return processed; 2192 } 2193 2194 void qmp_guest_set_user_password(const char *username, 2195 const char *password, 2196 bool crypted, 2197 Error **errp) 2198 { 2199 Error *local_err = NULL; 2200 char *passwd_path = NULL; 2201 pid_t pid; 2202 int status; 2203 int datafd[2] = { -1, -1 }; 2204 char *rawpasswddata = NULL; 2205 size_t rawpasswdlen; 2206 char *chpasswddata = NULL; 2207 size_t chpasswdlen; 2208 2209 rawpasswddata = (char *)qbase64_decode(password, -1, &rawpasswdlen, errp); 2210 if (!rawpasswddata) { 2211 return; 2212 } 2213 rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1); 2214 rawpasswddata[rawpasswdlen] = '\0'; 2215 2216 if (strchr(rawpasswddata, '\n')) { 2217 error_setg(errp, "forbidden characters in raw password"); 2218 goto out; 2219 } 2220 2221 if (strchr(username, '\n') || 2222 strchr(username, ':')) { 2223 error_setg(errp, "forbidden characters in username"); 2224 goto out; 2225 } 2226 2227 chpasswddata = g_strdup_printf("%s:%s\n", username, rawpasswddata); 2228 chpasswdlen = strlen(chpasswddata); 2229 2230 passwd_path = g_find_program_in_path("chpasswd"); 2231 2232 if (!passwd_path) { 2233 error_setg(errp, "cannot find 'passwd' program in PATH"); 2234 goto out; 2235 } 2236 2237 if (pipe(datafd) < 0) { 2238 error_setg(errp, "cannot create pipe FDs"); 2239 goto out; 2240 } 2241 2242 pid = fork(); 2243 if (pid == 0) { 2244 close(datafd[1]); 2245 /* child */ 2246 setsid(); 2247 dup2(datafd[0], 0); 2248 reopen_fd_to_null(1); 2249 reopen_fd_to_null(2); 2250 2251 if (crypted) { 2252 execle(passwd_path, "chpasswd", "-e", NULL, environ); 2253 } else { 2254 execle(passwd_path, "chpasswd", NULL, environ); 2255 } 2256 _exit(EXIT_FAILURE); 2257 } else if (pid < 0) { 2258 error_setg_errno(errp, errno, "failed to create child process"); 2259 goto out; 2260 } 2261 close(datafd[0]); 2262 datafd[0] = -1; 2263 2264 if (qemu_write_full(datafd[1], chpasswddata, chpasswdlen) != chpasswdlen) { 2265 error_setg_errno(errp, errno, "cannot write new account password"); 2266 goto out; 2267 } 2268 close(datafd[1]); 2269 datafd[1] = -1; 2270 2271 ga_wait_child(pid, &status, &local_err); 2272 if (local_err) { 2273 error_propagate(errp, local_err); 2274 goto out; 2275 } 2276 2277 if (!WIFEXITED(status)) { 2278 error_setg(errp, "child process has terminated abnormally"); 2279 goto out; 2280 } 2281 2282 if (WEXITSTATUS(status)) { 2283 error_setg(errp, "child process has failed to set user password"); 2284 goto out; 2285 } 2286 2287 out: 2288 g_free(chpasswddata); 2289 g_free(rawpasswddata); 2290 g_free(passwd_path); 2291 if (datafd[0] != -1) { 2292 close(datafd[0]); 2293 } 2294 if (datafd[1] != -1) { 2295 close(datafd[1]); 2296 } 2297 } 2298 2299 static void ga_read_sysfs_file(int dirfd, const char *pathname, char *buf, 2300 int size, Error **errp) 2301 { 2302 int fd; 2303 int res; 2304 2305 errno = 0; 2306 fd = openat(dirfd, pathname, O_RDONLY); 2307 if (fd == -1) { 2308 error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname); 2309 return; 2310 } 2311 2312 res = pread(fd, buf, size, 0); 2313 if (res == -1) { 2314 error_setg_errno(errp, errno, "pread sysfs file \"%s\"", pathname); 2315 } else if (res == 0) { 2316 error_setg(errp, "pread sysfs file \"%s\": unexpected EOF", pathname); 2317 } 2318 close(fd); 2319 } 2320 2321 static void ga_write_sysfs_file(int dirfd, const char *pathname, 2322 const char *buf, int size, Error **errp) 2323 { 2324 int fd; 2325 2326 errno = 0; 2327 fd = openat(dirfd, pathname, O_WRONLY); 2328 if (fd == -1) { 2329 error_setg_errno(errp, errno, "open sysfs file \"%s\"", pathname); 2330 return; 2331 } 2332 2333 if (pwrite(fd, buf, size, 0) == -1) { 2334 error_setg_errno(errp, errno, "pwrite sysfs file \"%s\"", pathname); 2335 } 2336 2337 close(fd); 2338 } 2339 2340 /* Transfer online/offline status between @mem_blk and the guest system. 2341 * 2342 * On input either @errp or *@errp must be NULL. 2343 * 2344 * In system-to-@mem_blk direction, the following @mem_blk fields are accessed: 2345 * - R: mem_blk->phys_index 2346 * - W: mem_blk->online 2347 * - W: mem_blk->can_offline 2348 * 2349 * In @mem_blk-to-system direction, the following @mem_blk fields are accessed: 2350 * - R: mem_blk->phys_index 2351 * - R: mem_blk->online 2352 *- R: mem_blk->can_offline 2353 * Written members remain unmodified on error. 2354 */ 2355 static void transfer_memory_block(GuestMemoryBlock *mem_blk, bool sys2memblk, 2356 GuestMemoryBlockResponse *result, 2357 Error **errp) 2358 { 2359 char *dirpath; 2360 int dirfd; 2361 char *status; 2362 Error *local_err = NULL; 2363 2364 if (!sys2memblk) { 2365 DIR *dp; 2366 2367 if (!result) { 2368 error_setg(errp, "Internal error, 'result' should not be NULL"); 2369 return; 2370 } 2371 errno = 0; 2372 dp = opendir("/sys/devices/system/memory/"); 2373 /* if there is no 'memory' directory in sysfs, 2374 * we think this VM does not support online/offline memory block, 2375 * any other solution? 2376 */ 2377 if (!dp) { 2378 if (errno == ENOENT) { 2379 result->response = 2380 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED; 2381 } 2382 goto out1; 2383 } 2384 closedir(dp); 2385 } 2386 2387 dirpath = g_strdup_printf("/sys/devices/system/memory/memory%" PRId64 "/", 2388 mem_blk->phys_index); 2389 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2390 if (dirfd == -1) { 2391 if (sys2memblk) { 2392 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2393 } else { 2394 if (errno == ENOENT) { 2395 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_NOT_FOUND; 2396 } else { 2397 result->response = 2398 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2399 } 2400 } 2401 g_free(dirpath); 2402 goto out1; 2403 } 2404 g_free(dirpath); 2405 2406 status = g_malloc0(10); 2407 ga_read_sysfs_file(dirfd, "state", status, 10, &local_err); 2408 if (local_err) { 2409 /* treat with sysfs file that not exist in old kernel */ 2410 if (errno == ENOENT) { 2411 error_free(local_err); 2412 if (sys2memblk) { 2413 mem_blk->online = true; 2414 mem_blk->can_offline = false; 2415 } else if (!mem_blk->online) { 2416 result->response = 2417 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_NOT_SUPPORTED; 2418 } 2419 } else { 2420 if (sys2memblk) { 2421 error_propagate(errp, local_err); 2422 } else { 2423 result->response = 2424 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2425 } 2426 } 2427 goto out2; 2428 } 2429 2430 if (sys2memblk) { 2431 char removable = '0'; 2432 2433 mem_blk->online = (strncmp(status, "online", 6) == 0); 2434 2435 ga_read_sysfs_file(dirfd, "removable", &removable, 1, &local_err); 2436 if (local_err) { 2437 /* if no 'removable' file, it doesn't support offline mem blk */ 2438 if (errno == ENOENT) { 2439 error_free(local_err); 2440 mem_blk->can_offline = false; 2441 } else { 2442 error_propagate(errp, local_err); 2443 } 2444 } else { 2445 mem_blk->can_offline = (removable != '0'); 2446 } 2447 } else { 2448 if (mem_blk->online != (strncmp(status, "online", 6) == 0)) { 2449 const char *new_state = mem_blk->online ? "online" : "offline"; 2450 2451 ga_write_sysfs_file(dirfd, "state", new_state, strlen(new_state), 2452 &local_err); 2453 if (local_err) { 2454 error_free(local_err); 2455 result->response = 2456 GUEST_MEMORY_BLOCK_RESPONSE_TYPE_OPERATION_FAILED; 2457 goto out2; 2458 } 2459 2460 result->response = GUEST_MEMORY_BLOCK_RESPONSE_TYPE_SUCCESS; 2461 result->has_error_code = false; 2462 } /* otherwise pretend successful re-(on|off)-lining */ 2463 } 2464 g_free(status); 2465 close(dirfd); 2466 return; 2467 2468 out2: 2469 g_free(status); 2470 close(dirfd); 2471 out1: 2472 if (!sys2memblk) { 2473 result->has_error_code = true; 2474 result->error_code = errno; 2475 } 2476 } 2477 2478 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 2479 { 2480 GuestMemoryBlockList *head, **link; 2481 Error *local_err = NULL; 2482 struct dirent *de; 2483 DIR *dp; 2484 2485 head = NULL; 2486 link = &head; 2487 2488 dp = opendir("/sys/devices/system/memory/"); 2489 if (!dp) { 2490 /* it's ok if this happens to be a system that doesn't expose 2491 * memory blocks via sysfs, but otherwise we should report 2492 * an error 2493 */ 2494 if (errno != ENOENT) { 2495 error_setg_errno(errp, errno, "Can't open directory" 2496 "\"/sys/devices/system/memory/\""); 2497 } 2498 return NULL; 2499 } 2500 2501 /* Note: the phys_index of memory block may be discontinuous, 2502 * this is because a memblk is the unit of the Sparse Memory design, which 2503 * allows discontinuous memory ranges (ex. NUMA), so here we should 2504 * traverse the memory block directory. 2505 */ 2506 while ((de = readdir(dp)) != NULL) { 2507 GuestMemoryBlock *mem_blk; 2508 GuestMemoryBlockList *entry; 2509 2510 if ((strncmp(de->d_name, "memory", 6) != 0) || 2511 !(de->d_type & DT_DIR)) { 2512 continue; 2513 } 2514 2515 mem_blk = g_malloc0(sizeof *mem_blk); 2516 /* The d_name is "memoryXXX", phys_index is block id, same as XXX */ 2517 mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10); 2518 mem_blk->has_can_offline = true; /* lolspeak ftw */ 2519 transfer_memory_block(mem_blk, true, NULL, &local_err); 2520 2521 entry = g_malloc0(sizeof *entry); 2522 entry->value = mem_blk; 2523 2524 *link = entry; 2525 link = &entry->next; 2526 } 2527 2528 closedir(dp); 2529 if (local_err == NULL) { 2530 /* there's no guest with zero memory blocks */ 2531 if (head == NULL) { 2532 error_setg(errp, "guest reported zero memory blocks!"); 2533 } 2534 return head; 2535 } 2536 2537 qapi_free_GuestMemoryBlockList(head); 2538 error_propagate(errp, local_err); 2539 return NULL; 2540 } 2541 2542 GuestMemoryBlockResponseList * 2543 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 2544 { 2545 GuestMemoryBlockResponseList *head, **link; 2546 Error *local_err = NULL; 2547 2548 head = NULL; 2549 link = &head; 2550 2551 while (mem_blks != NULL) { 2552 GuestMemoryBlockResponse *result; 2553 GuestMemoryBlockResponseList *entry; 2554 GuestMemoryBlock *current_mem_blk = mem_blks->value; 2555 2556 result = g_malloc0(sizeof(*result)); 2557 result->phys_index = current_mem_blk->phys_index; 2558 transfer_memory_block(current_mem_blk, false, result, &local_err); 2559 if (local_err) { /* should never happen */ 2560 goto err; 2561 } 2562 entry = g_malloc0(sizeof *entry); 2563 entry->value = result; 2564 2565 *link = entry; 2566 link = &entry->next; 2567 mem_blks = mem_blks->next; 2568 } 2569 2570 return head; 2571 err: 2572 qapi_free_GuestMemoryBlockResponseList(head); 2573 error_propagate(errp, local_err); 2574 return NULL; 2575 } 2576 2577 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 2578 { 2579 Error *local_err = NULL; 2580 char *dirpath; 2581 int dirfd; 2582 char *buf; 2583 GuestMemoryBlockInfo *info; 2584 2585 dirpath = g_strdup_printf("/sys/devices/system/memory/"); 2586 dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); 2587 if (dirfd == -1) { 2588 error_setg_errno(errp, errno, "open(\"%s\")", dirpath); 2589 g_free(dirpath); 2590 return NULL; 2591 } 2592 g_free(dirpath); 2593 2594 buf = g_malloc0(20); 2595 ga_read_sysfs_file(dirfd, "block_size_bytes", buf, 20, &local_err); 2596 close(dirfd); 2597 if (local_err) { 2598 g_free(buf); 2599 error_propagate(errp, local_err); 2600 return NULL; 2601 } 2602 2603 info = g_new0(GuestMemoryBlockInfo, 1); 2604 info->size = strtol(buf, NULL, 16); /* the unit is bytes */ 2605 2606 g_free(buf); 2607 2608 return info; 2609 } 2610 2611 #else /* defined(__linux__) */ 2612 2613 void qmp_guest_suspend_disk(Error **errp) 2614 { 2615 error_setg(errp, QERR_UNSUPPORTED); 2616 } 2617 2618 void qmp_guest_suspend_ram(Error **errp) 2619 { 2620 error_setg(errp, QERR_UNSUPPORTED); 2621 } 2622 2623 void qmp_guest_suspend_hybrid(Error **errp) 2624 { 2625 error_setg(errp, QERR_UNSUPPORTED); 2626 } 2627 2628 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp) 2629 { 2630 error_setg(errp, QERR_UNSUPPORTED); 2631 return NULL; 2632 } 2633 2634 GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) 2635 { 2636 error_setg(errp, QERR_UNSUPPORTED); 2637 return NULL; 2638 } 2639 2640 int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp) 2641 { 2642 error_setg(errp, QERR_UNSUPPORTED); 2643 return -1; 2644 } 2645 2646 void qmp_guest_set_user_password(const char *username, 2647 const char *password, 2648 bool crypted, 2649 Error **errp) 2650 { 2651 error_setg(errp, QERR_UNSUPPORTED); 2652 } 2653 2654 GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp) 2655 { 2656 error_setg(errp, QERR_UNSUPPORTED); 2657 return NULL; 2658 } 2659 2660 GuestMemoryBlockResponseList * 2661 qmp_guest_set_memory_blocks(GuestMemoryBlockList *mem_blks, Error **errp) 2662 { 2663 error_setg(errp, QERR_UNSUPPORTED); 2664 return NULL; 2665 } 2666 2667 GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) 2668 { 2669 error_setg(errp, QERR_UNSUPPORTED); 2670 return NULL; 2671 } 2672 2673 #endif 2674 2675 #if !defined(CONFIG_FSFREEZE) 2676 2677 GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) 2678 { 2679 error_setg(errp, QERR_UNSUPPORTED); 2680 return NULL; 2681 } 2682 2683 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **errp) 2684 { 2685 error_setg(errp, QERR_UNSUPPORTED); 2686 2687 return 0; 2688 } 2689 2690 int64_t qmp_guest_fsfreeze_freeze(Error **errp) 2691 { 2692 error_setg(errp, QERR_UNSUPPORTED); 2693 2694 return 0; 2695 } 2696 2697 int64_t qmp_guest_fsfreeze_freeze_list(bool has_mountpoints, 2698 strList *mountpoints, 2699 Error **errp) 2700 { 2701 error_setg(errp, QERR_UNSUPPORTED); 2702 2703 return 0; 2704 } 2705 2706 int64_t qmp_guest_fsfreeze_thaw(Error **errp) 2707 { 2708 error_setg(errp, QERR_UNSUPPORTED); 2709 2710 return 0; 2711 } 2712 #endif /* CONFIG_FSFREEZE */ 2713 2714 #if !defined(CONFIG_FSTRIM) 2715 GuestFilesystemTrimResponse * 2716 qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) 2717 { 2718 error_setg(errp, QERR_UNSUPPORTED); 2719 return NULL; 2720 } 2721 #endif 2722 2723 /* add unsupported commands to the blacklist */ 2724 GList *ga_command_blacklist_init(GList *blacklist) 2725 { 2726 #if !defined(__linux__) 2727 { 2728 const char *list[] = { 2729 "guest-suspend-disk", "guest-suspend-ram", 2730 "guest-suspend-hybrid", "guest-network-get-interfaces", 2731 "guest-get-vcpus", "guest-set-vcpus", 2732 "guest-get-memory-blocks", "guest-set-memory-blocks", 2733 "guest-get-memory-block-size", NULL}; 2734 char **p = (char **)list; 2735 2736 while (*p) { 2737 blacklist = g_list_append(blacklist, g_strdup(*p++)); 2738 } 2739 } 2740 #endif 2741 2742 #if !defined(CONFIG_FSFREEZE) 2743 { 2744 const char *list[] = { 2745 "guest-get-fsinfo", "guest-fsfreeze-status", 2746 "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list", 2747 "guest-fsfreeze-thaw", "guest-get-fsinfo", NULL}; 2748 char **p = (char **)list; 2749 2750 while (*p) { 2751 blacklist = g_list_append(blacklist, g_strdup(*p++)); 2752 } 2753 } 2754 #endif 2755 2756 #if !defined(CONFIG_FSTRIM) 2757 blacklist = g_list_append(blacklist, g_strdup("guest-fstrim")); 2758 #endif 2759 2760 return blacklist; 2761 } 2762 2763 /* register init/cleanup routines for stateful command groups */ 2764 void ga_command_state_init(GAState *s, GACommandState *cs) 2765 { 2766 #if defined(CONFIG_FSFREEZE) 2767 ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup); 2768 #endif 2769 } 2770 2771 #ifdef HAVE_UTMPX 2772 2773 #define QGA_MICRO_SECOND_TO_SECOND 1000000 2774 2775 static double ga_get_login_time(struct utmpx *user_info) 2776 { 2777 double seconds = (double)user_info->ut_tv.tv_sec; 2778 double useconds = (double)user_info->ut_tv.tv_usec; 2779 useconds /= QGA_MICRO_SECOND_TO_SECOND; 2780 return seconds + useconds; 2781 } 2782 2783 GuestUserList *qmp_guest_get_users(Error **err) 2784 { 2785 GHashTable *cache = NULL; 2786 GuestUserList *head = NULL, *cur_item = NULL; 2787 struct utmpx *user_info = NULL; 2788 gpointer value = NULL; 2789 GuestUser *user = NULL; 2790 GuestUserList *item = NULL; 2791 double login_time = 0; 2792 2793 cache = g_hash_table_new(g_str_hash, g_str_equal); 2794 setutxent(); 2795 2796 for (;;) { 2797 user_info = getutxent(); 2798 if (user_info == NULL) { 2799 break; 2800 } else if (user_info->ut_type != USER_PROCESS) { 2801 continue; 2802 } else if (g_hash_table_contains(cache, user_info->ut_user)) { 2803 value = g_hash_table_lookup(cache, user_info->ut_user); 2804 user = (GuestUser *)value; 2805 login_time = ga_get_login_time(user_info); 2806 /* We're ensuring the earliest login time to be sent */ 2807 if (login_time < user->login_time) { 2808 user->login_time = login_time; 2809 } 2810 continue; 2811 } 2812 2813 item = g_new0(GuestUserList, 1); 2814 item->value = g_new0(GuestUser, 1); 2815 item->value->user = g_strdup(user_info->ut_user); 2816 item->value->login_time = ga_get_login_time(user_info); 2817 2818 g_hash_table_insert(cache, item->value->user, item->value); 2819 2820 if (!cur_item) { 2821 head = cur_item = item; 2822 } else { 2823 cur_item->next = item; 2824 cur_item = item; 2825 } 2826 } 2827 endutxent(); 2828 g_hash_table_destroy(cache); 2829 return head; 2830 } 2831 2832 #else 2833 2834 GuestUserList *qmp_guest_get_users(Error **errp) 2835 { 2836 error_setg(errp, QERR_UNSUPPORTED); 2837 return NULL; 2838 } 2839 2840 #endif 2841 2842 /* Replace escaped special characters with theire real values. The replacement 2843 * is done in place -- returned value is in the original string. 2844 */ 2845 static void ga_osrelease_replace_special(gchar *value) 2846 { 2847 gchar *p, *p2, quote; 2848 2849 /* Trim the string at first space or semicolon if it is not enclosed in 2850 * single or double quotes. */ 2851 if ((value[0] != '"') || (value[0] == '\'')) { 2852 p = strchr(value, ' '); 2853 if (p != NULL) { 2854 *p = 0; 2855 } 2856 p = strchr(value, ';'); 2857 if (p != NULL) { 2858 *p = 0; 2859 } 2860 return; 2861 } 2862 2863 quote = value[0]; 2864 p2 = value; 2865 p = value + 1; 2866 while (*p != 0) { 2867 if (*p == '\\') { 2868 p++; 2869 switch (*p) { 2870 case '$': 2871 case '\'': 2872 case '"': 2873 case '\\': 2874 case '`': 2875 break; 2876 default: 2877 /* Keep literal backslash followed by whatever is there */ 2878 p--; 2879 break; 2880 } 2881 } else if (*p == quote) { 2882 *p2 = 0; 2883 break; 2884 } 2885 *(p2++) = *(p++); 2886 } 2887 } 2888 2889 static GKeyFile *ga_parse_osrelease(const char *fname) 2890 { 2891 gchar *content = NULL; 2892 gchar *content2 = NULL; 2893 GError *err = NULL; 2894 GKeyFile *keys = g_key_file_new(); 2895 const char *group = "[os-release]\n"; 2896 2897 if (!g_file_get_contents(fname, &content, NULL, &err)) { 2898 slog("failed to read '%s', error: %s", fname, err->message); 2899 goto fail; 2900 } 2901 2902 if (!g_utf8_validate(content, -1, NULL)) { 2903 slog("file is not utf-8 encoded: %s", fname); 2904 goto fail; 2905 } 2906 content2 = g_strdup_printf("%s%s", group, content); 2907 2908 if (!g_key_file_load_from_data(keys, content2, -1, G_KEY_FILE_NONE, 2909 &err)) { 2910 slog("failed to parse file '%s', error: %s", fname, err->message); 2911 goto fail; 2912 } 2913 2914 g_free(content); 2915 g_free(content2); 2916 return keys; 2917 2918 fail: 2919 g_error_free(err); 2920 g_free(content); 2921 g_free(content2); 2922 g_key_file_free(keys); 2923 return NULL; 2924 } 2925 2926 GuestOSInfo *qmp_guest_get_osinfo(Error **errp) 2927 { 2928 GuestOSInfo *info = NULL; 2929 struct utsname kinfo; 2930 GKeyFile *osrelease = NULL; 2931 const char *qga_os_release = g_getenv("QGA_OS_RELEASE"); 2932 2933 info = g_new0(GuestOSInfo, 1); 2934 2935 if (uname(&kinfo) != 0) { 2936 error_setg_errno(errp, errno, "uname failed"); 2937 } else { 2938 info->has_kernel_version = true; 2939 info->kernel_version = g_strdup(kinfo.version); 2940 info->has_kernel_release = true; 2941 info->kernel_release = g_strdup(kinfo.release); 2942 info->has_machine = true; 2943 info->machine = g_strdup(kinfo.machine); 2944 } 2945 2946 if (qga_os_release != NULL) { 2947 osrelease = ga_parse_osrelease(qga_os_release); 2948 } else { 2949 osrelease = ga_parse_osrelease("/etc/os-release"); 2950 if (osrelease == NULL) { 2951 osrelease = ga_parse_osrelease("/usr/lib/os-release"); 2952 } 2953 } 2954 2955 if (osrelease != NULL) { 2956 char *value; 2957 2958 #define GET_FIELD(field, osfield) do { \ 2959 value = g_key_file_get_value(osrelease, "os-release", osfield, NULL); \ 2960 if (value != NULL) { \ 2961 ga_osrelease_replace_special(value); \ 2962 info->has_ ## field = true; \ 2963 info->field = value; \ 2964 } \ 2965 } while (0) 2966 GET_FIELD(id, "ID"); 2967 GET_FIELD(name, "NAME"); 2968 GET_FIELD(pretty_name, "PRETTY_NAME"); 2969 GET_FIELD(version, "VERSION"); 2970 GET_FIELD(version_id, "VERSION_ID"); 2971 GET_FIELD(variant, "VARIANT"); 2972 GET_FIELD(variant_id, "VARIANT_ID"); 2973 #undef GET_FIELD 2974 2975 g_key_file_free(osrelease); 2976 } 2977 2978 return info; 2979 } 2980