cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

commands-posix.c (93163B)


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