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