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