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