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