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