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