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