xref: /openbmc/qemu/qga/commands-posix.c (revision 8917c3bd)
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 <glib.h>
15 #include <sys/types.h>
16 #include <sys/ioctl.h>
17 #include <sys/wait.h>
18 #include "qga/guest-agent-core.h"
19 #include "qga-qmp-commands.h"
20 #include "qapi/qmp/qerror.h"
21 #include "qemu/queue.h"
22 #include "qemu/host-utils.h"
23 
24 #ifndef CONFIG_HAS_ENVIRON
25 #ifdef __APPLE__
26 #include <crt_externs.h>
27 #define environ (*_NSGetEnviron())
28 #else
29 extern char **environ;
30 #endif
31 #endif
32 
33 #if defined(__linux__)
34 #include <mntent.h>
35 #include <linux/fs.h>
36 #include <ifaddrs.h>
37 #include <arpa/inet.h>
38 #include <sys/socket.h>
39 #include <net/if.h>
40 
41 #ifdef FIFREEZE
42 #define CONFIG_FSFREEZE
43 #endif
44 #ifdef FITRIM
45 #define CONFIG_FSTRIM
46 #endif
47 #endif
48 
49 static void ga_wait_child(pid_t pid, int *status, Error **err)
50 {
51     pid_t rpid;
52 
53     *status = 0;
54 
55     do {
56         rpid = waitpid(pid, status, 0);
57     } while (rpid == -1 && errno == EINTR);
58 
59     if (rpid == -1) {
60         error_setg_errno(err, errno, "failed to wait for child (pid: %d)", pid);
61         return;
62     }
63 
64     g_assert(rpid == pid);
65 }
66 
67 void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
68 {
69     const char *shutdown_flag;
70     Error *local_err = NULL;
71     pid_t pid;
72     int status;
73 
74     slog("guest-shutdown called, mode: %s", mode);
75     if (!has_mode || strcmp(mode, "powerdown") == 0) {
76         shutdown_flag = "-P";
77     } else if (strcmp(mode, "halt") == 0) {
78         shutdown_flag = "-H";
79     } else if (strcmp(mode, "reboot") == 0) {
80         shutdown_flag = "-r";
81     } else {
82         error_setg(err,
83                    "mode is invalid (valid values are: halt|powerdown|reboot");
84         return;
85     }
86 
87     pid = fork();
88     if (pid == 0) {
89         /* child, start the shutdown */
90         setsid();
91         reopen_fd_to_null(0);
92         reopen_fd_to_null(1);
93         reopen_fd_to_null(2);
94 
95         execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
96                "hypervisor initiated shutdown", (char*)NULL, environ);
97         _exit(EXIT_FAILURE);
98     } else if (pid < 0) {
99         error_setg_errno(err, errno, "failed to create child process");
100         return;
101     }
102 
103     ga_wait_child(pid, &status, &local_err);
104     if (error_is_set(&local_err)) {
105         error_propagate(err, local_err);
106         return;
107     }
108 
109     if (!WIFEXITED(status)) {
110         error_setg(err, "child process has terminated abnormally");
111         return;
112     }
113 
114     if (WEXITSTATUS(status)) {
115         error_setg(err, "child process has failed to shutdown");
116         return;
117     }
118 
119     /* succeded */
120 }
121 
122 typedef struct GuestFileHandle {
123     uint64_t id;
124     FILE *fh;
125     QTAILQ_ENTRY(GuestFileHandle) next;
126 } GuestFileHandle;
127 
128 static struct {
129     QTAILQ_HEAD(, GuestFileHandle) filehandles;
130 } guest_file_state;
131 
132 static void guest_file_handle_add(FILE *fh)
133 {
134     GuestFileHandle *gfh;
135 
136     gfh = g_malloc0(sizeof(GuestFileHandle));
137     gfh->id = fileno(fh);
138     gfh->fh = fh;
139     QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next);
140 }
141 
142 static GuestFileHandle *guest_file_handle_find(int64_t id, Error **err)
143 {
144     GuestFileHandle *gfh;
145 
146     QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next)
147     {
148         if (gfh->id == id) {
149             return gfh;
150         }
151     }
152 
153     error_setg(err, "handle '%" PRId64 "' has not been found", id);
154     return NULL;
155 }
156 
157 int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err)
158 {
159     FILE *fh;
160     int fd;
161     int64_t ret = -1;
162 
163     if (!has_mode) {
164         mode = "r";
165     }
166     slog("guest-file-open called, filepath: %s, mode: %s", path, mode);
167     fh = fopen(path, mode);
168     if (!fh) {
169         error_setg_errno(err, errno, "failed to open file '%s' (mode: '%s')",
170                          path, mode);
171         return -1;
172     }
173 
174     /* set fd non-blocking to avoid common use cases (like reading from a
175      * named pipe) from hanging the agent
176      */
177     fd = fileno(fh);
178     ret = fcntl(fd, F_GETFL);
179     ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK);
180     if (ret == -1) {
181         error_setg_errno(err, errno, "failed to make file '%s' non-blocking",
182                          path);
183         fclose(fh);
184         return -1;
185     }
186 
187     guest_file_handle_add(fh);
188     slog("guest-file-open, handle: %d", fd);
189     return fd;
190 }
191 
192 void qmp_guest_file_close(int64_t handle, Error **err)
193 {
194     GuestFileHandle *gfh = guest_file_handle_find(handle, err);
195     int ret;
196 
197     slog("guest-file-close called, handle: %ld", handle);
198     if (!gfh) {
199         return;
200     }
201 
202     ret = fclose(gfh->fh);
203     if (ret == EOF) {
204         error_setg_errno(err, errno, "failed to close handle");
205         return;
206     }
207 
208     QTAILQ_REMOVE(&guest_file_state.filehandles, gfh, next);
209     g_free(gfh);
210 }
211 
212 struct GuestFileRead *qmp_guest_file_read(int64_t handle, bool has_count,
213                                           int64_t count, Error **err)
214 {
215     GuestFileHandle *gfh = guest_file_handle_find(handle, err);
216     GuestFileRead *read_data = NULL;
217     guchar *buf;
218     FILE *fh;
219     size_t read_count;
220 
221     if (!gfh) {
222         return NULL;
223     }
224 
225     if (!has_count) {
226         count = QGA_READ_COUNT_DEFAULT;
227     } else if (count < 0) {
228         error_setg(err, "value '%" PRId64 "' is invalid for argument count",
229                    count);
230         return NULL;
231     }
232 
233     fh = gfh->fh;
234     buf = g_malloc0(count+1);
235     read_count = fread(buf, 1, count, fh);
236     if (ferror(fh)) {
237         error_setg_errno(err, errno, "failed to read file");
238         slog("guest-file-read failed, handle: %ld", handle);
239     } else {
240         buf[read_count] = 0;
241         read_data = g_malloc0(sizeof(GuestFileRead));
242         read_data->count = read_count;
243         read_data->eof = feof(fh);
244         if (read_count) {
245             read_data->buf_b64 = g_base64_encode(buf, read_count);
246         }
247     }
248     g_free(buf);
249     clearerr(fh);
250 
251     return read_data;
252 }
253 
254 GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
255                                      bool has_count, int64_t count, Error **err)
256 {
257     GuestFileWrite *write_data = NULL;
258     guchar *buf;
259     gsize buf_len;
260     int write_count;
261     GuestFileHandle *gfh = guest_file_handle_find(handle, err);
262     FILE *fh;
263 
264     if (!gfh) {
265         return NULL;
266     }
267 
268     fh = gfh->fh;
269     buf = g_base64_decode(buf_b64, &buf_len);
270 
271     if (!has_count) {
272         count = buf_len;
273     } else if (count < 0 || count > buf_len) {
274         error_setg(err, "value '%" PRId64 "' is invalid for argument count",
275                    count);
276         g_free(buf);
277         return NULL;
278     }
279 
280     write_count = fwrite(buf, 1, count, fh);
281     if (ferror(fh)) {
282         error_setg_errno(err, errno, "failed to write to file");
283         slog("guest-file-write failed, handle: %ld", handle);
284     } else {
285         write_data = g_malloc0(sizeof(GuestFileWrite));
286         write_data->count = write_count;
287         write_data->eof = feof(fh);
288     }
289     g_free(buf);
290     clearerr(fh);
291 
292     return write_data;
293 }
294 
295 struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
296                                           int64_t whence, Error **err)
297 {
298     GuestFileHandle *gfh = guest_file_handle_find(handle, err);
299     GuestFileSeek *seek_data = NULL;
300     FILE *fh;
301     int ret;
302 
303     if (!gfh) {
304         return NULL;
305     }
306 
307     fh = gfh->fh;
308     ret = fseek(fh, offset, whence);
309     if (ret == -1) {
310         error_setg_errno(err, errno, "failed to seek file");
311     } else {
312         seek_data = g_malloc0(sizeof(GuestFileRead));
313         seek_data->position = ftell(fh);
314         seek_data->eof = feof(fh);
315     }
316     clearerr(fh);
317 
318     return seek_data;
319 }
320 
321 void qmp_guest_file_flush(int64_t handle, Error **err)
322 {
323     GuestFileHandle *gfh = guest_file_handle_find(handle, err);
324     FILE *fh;
325     int ret;
326 
327     if (!gfh) {
328         return;
329     }
330 
331     fh = gfh->fh;
332     ret = fflush(fh);
333     if (ret == EOF) {
334         error_setg_errno(err, errno, "failed to flush file");
335     }
336 }
337 
338 static void guest_file_init(void)
339 {
340     QTAILQ_INIT(&guest_file_state.filehandles);
341 }
342 
343 /* linux-specific implementations. avoid this if at all possible. */
344 #if defined(__linux__)
345 
346 #if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
347 typedef struct FsMount {
348     char *dirname;
349     char *devtype;
350     QTAILQ_ENTRY(FsMount) next;
351 } FsMount;
352 
353 typedef QTAILQ_HEAD(, FsMount) FsMountList;
354 
355 static void free_fs_mount_list(FsMountList *mounts)
356 {
357      FsMount *mount, *temp;
358 
359      if (!mounts) {
360          return;
361      }
362 
363      QTAILQ_FOREACH_SAFE(mount, mounts, next, temp) {
364          QTAILQ_REMOVE(mounts, mount, next);
365          g_free(mount->dirname);
366          g_free(mount->devtype);
367          g_free(mount);
368      }
369 }
370 
371 /*
372  * Walk the mount table and build a list of local file systems
373  */
374 static void build_fs_mount_list(FsMountList *mounts, Error **err)
375 {
376     struct mntent *ment;
377     FsMount *mount;
378     char const *mtab = "/proc/self/mounts";
379     FILE *fp;
380 
381     fp = setmntent(mtab, "r");
382     if (!fp) {
383         error_setg(err, "failed to open mtab file: '%s'", mtab);
384         return;
385     }
386 
387     while ((ment = getmntent(fp))) {
388         /*
389          * An entry which device name doesn't start with a '/' is
390          * either a dummy file system or a network file system.
391          * Add special handling for smbfs and cifs as is done by
392          * coreutils as well.
393          */
394         if ((ment->mnt_fsname[0] != '/') ||
395             (strcmp(ment->mnt_type, "smbfs") == 0) ||
396             (strcmp(ment->mnt_type, "cifs") == 0)) {
397             continue;
398         }
399 
400         mount = g_malloc0(sizeof(FsMount));
401         mount->dirname = g_strdup(ment->mnt_dir);
402         mount->devtype = g_strdup(ment->mnt_type);
403 
404         QTAILQ_INSERT_TAIL(mounts, mount, next);
405     }
406 
407     endmntent(fp);
408 }
409 #endif
410 
411 #if defined(CONFIG_FSFREEZE)
412 
413 typedef enum {
414     FSFREEZE_HOOK_THAW = 0,
415     FSFREEZE_HOOK_FREEZE,
416 } FsfreezeHookArg;
417 
418 const char *fsfreeze_hook_arg_string[] = {
419     "thaw",
420     "freeze",
421 };
422 
423 static void execute_fsfreeze_hook(FsfreezeHookArg arg, Error **err)
424 {
425     int status;
426     pid_t pid;
427     const char *hook;
428     const char *arg_str = fsfreeze_hook_arg_string[arg];
429     Error *local_err = NULL;
430 
431     hook = ga_fsfreeze_hook(ga_state);
432     if (!hook) {
433         return;
434     }
435     if (access(hook, X_OK) != 0) {
436         error_setg_errno(err, errno, "can't access fsfreeze hook '%s'", hook);
437         return;
438     }
439 
440     slog("executing fsfreeze hook with arg '%s'", arg_str);
441     pid = fork();
442     if (pid == 0) {
443         setsid();
444         reopen_fd_to_null(0);
445         reopen_fd_to_null(1);
446         reopen_fd_to_null(2);
447 
448         execle(hook, hook, arg_str, NULL, environ);
449         _exit(EXIT_FAILURE);
450     } else if (pid < 0) {
451         error_setg_errno(err, errno, "failed to create child process");
452         return;
453     }
454 
455     ga_wait_child(pid, &status, &local_err);
456     if (error_is_set(&local_err)) {
457         error_propagate(err, local_err);
458         return;
459     }
460 
461     if (!WIFEXITED(status)) {
462         error_setg(err, "fsfreeze hook has terminated abnormally");
463         return;
464     }
465 
466     status = WEXITSTATUS(status);
467     if (status) {
468         error_setg(err, "fsfreeze hook has failed with status %d", status);
469         return;
470     }
471 }
472 
473 /*
474  * Return status of freeze/thaw
475  */
476 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
477 {
478     if (ga_is_frozen(ga_state)) {
479         return GUEST_FSFREEZE_STATUS_FROZEN;
480     }
481 
482     return GUEST_FSFREEZE_STATUS_THAWED;
483 }
484 
485 /*
486  * Walk list of mounted file systems in the guest, and freeze the ones which
487  * are real local file systems.
488  */
489 int64_t qmp_guest_fsfreeze_freeze(Error **err)
490 {
491     int ret = 0, i = 0;
492     FsMountList mounts;
493     struct FsMount *mount;
494     Error *local_err = NULL;
495     int fd;
496 
497     slog("guest-fsfreeze called");
498 
499     execute_fsfreeze_hook(FSFREEZE_HOOK_FREEZE, &local_err);
500     if (error_is_set(&local_err)) {
501         error_propagate(err, local_err);
502         return -1;
503     }
504 
505     QTAILQ_INIT(&mounts);
506     build_fs_mount_list(&mounts, &local_err);
507     if (error_is_set(&local_err)) {
508         error_propagate(err, local_err);
509         return -1;
510     }
511 
512     /* cannot risk guest agent blocking itself on a write in this state */
513     ga_set_frozen(ga_state);
514 
515     QTAILQ_FOREACH(mount, &mounts, next) {
516         fd = qemu_open(mount->dirname, O_RDONLY);
517         if (fd == -1) {
518             error_setg_errno(err, errno, "failed to open %s", mount->dirname);
519             goto error;
520         }
521 
522         /* we try to cull filesytems we know won't work in advance, but other
523          * filesytems may not implement fsfreeze for less obvious reasons.
524          * these will report EOPNOTSUPP. we simply ignore these when tallying
525          * the number of frozen filesystems.
526          *
527          * any other error means a failure to freeze a filesystem we
528          * expect to be freezable, so return an error in those cases
529          * and return system to thawed state.
530          */
531         ret = ioctl(fd, FIFREEZE);
532         if (ret == -1) {
533             if (errno != EOPNOTSUPP) {
534                 error_setg_errno(err, errno, "failed to freeze %s",
535                                  mount->dirname);
536                 close(fd);
537                 goto error;
538             }
539         } else {
540             i++;
541         }
542         close(fd);
543     }
544 
545     free_fs_mount_list(&mounts);
546     return i;
547 
548 error:
549     free_fs_mount_list(&mounts);
550     qmp_guest_fsfreeze_thaw(NULL);
551     return 0;
552 }
553 
554 /*
555  * Walk list of frozen file systems in the guest, and thaw them.
556  */
557 int64_t qmp_guest_fsfreeze_thaw(Error **err)
558 {
559     int ret;
560     FsMountList mounts;
561     FsMount *mount;
562     int fd, i = 0, logged;
563     Error *local_err = NULL;
564 
565     QTAILQ_INIT(&mounts);
566     build_fs_mount_list(&mounts, &local_err);
567     if (error_is_set(&local_err)) {
568         error_propagate(err, local_err);
569         return 0;
570     }
571 
572     QTAILQ_FOREACH(mount, &mounts, next) {
573         logged = false;
574         fd = qemu_open(mount->dirname, O_RDONLY);
575         if (fd == -1) {
576             continue;
577         }
578         /* we have no way of knowing whether a filesystem was actually unfrozen
579          * as a result of a successful call to FITHAW, only that if an error
580          * was returned the filesystem was *not* unfrozen by that particular
581          * call.
582          *
583          * since multiple preceding FIFREEZEs require multiple calls to FITHAW
584          * to unfreeze, continuing issuing FITHAW until an error is returned,
585          * in which case either the filesystem is in an unfreezable state, or,
586          * more likely, it was thawed previously (and remains so afterward).
587          *
588          * also, since the most recent successful call is the one that did
589          * the actual unfreeze, we can use this to provide an accurate count
590          * of the number of filesystems unfrozen by guest-fsfreeze-thaw, which
591          * may * be useful for determining whether a filesystem was unfrozen
592          * during the freeze/thaw phase by a process other than qemu-ga.
593          */
594         do {
595             ret = ioctl(fd, FITHAW);
596             if (ret == 0 && !logged) {
597                 i++;
598                 logged = true;
599             }
600         } while (ret == 0);
601         close(fd);
602     }
603 
604     ga_unset_frozen(ga_state);
605     free_fs_mount_list(&mounts);
606 
607     execute_fsfreeze_hook(FSFREEZE_HOOK_THAW, err);
608 
609     return i;
610 }
611 
612 static void guest_fsfreeze_cleanup(void)
613 {
614     Error *err = NULL;
615 
616     if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
617         qmp_guest_fsfreeze_thaw(&err);
618         if (err) {
619             slog("failed to clean up frozen filesystems: %s",
620                  error_get_pretty(err));
621             error_free(err);
622         }
623     }
624 }
625 #endif /* CONFIG_FSFREEZE */
626 
627 #if defined(CONFIG_FSTRIM)
628 /*
629  * Walk list of mounted file systems in the guest, and trim them.
630  */
631 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
632 {
633     int ret = 0;
634     FsMountList mounts;
635     struct FsMount *mount;
636     int fd;
637     Error *local_err = NULL;
638     struct fstrim_range r = {
639         .start = 0,
640         .len = -1,
641         .minlen = has_minimum ? minimum : 0,
642     };
643 
644     slog("guest-fstrim called");
645 
646     QTAILQ_INIT(&mounts);
647     build_fs_mount_list(&mounts, &local_err);
648     if (error_is_set(&local_err)) {
649         error_propagate(err, local_err);
650         return;
651     }
652 
653     QTAILQ_FOREACH(mount, &mounts, next) {
654         fd = qemu_open(mount->dirname, O_RDONLY);
655         if (fd == -1) {
656             error_setg_errno(err, errno, "failed to open %s", mount->dirname);
657             goto error;
658         }
659 
660         /* We try to cull filesytems we know won't work in advance, but other
661          * filesytems may not implement fstrim for less obvious reasons.  These
662          * will report EOPNOTSUPP; we simply ignore these errors.  Any other
663          * error means an unexpected error, so return it in those cases.  In
664          * some other cases ENOTTY will be reported (e.g. CD-ROMs).
665          */
666         ret = ioctl(fd, FITRIM, &r);
667         if (ret == -1) {
668             if (errno != ENOTTY && errno != EOPNOTSUPP) {
669                 error_setg_errno(err, errno, "failed to trim %s",
670                                  mount->dirname);
671                 close(fd);
672                 goto error;
673             }
674         }
675         close(fd);
676     }
677 
678 error:
679     free_fs_mount_list(&mounts);
680 }
681 #endif /* CONFIG_FSTRIM */
682 
683 
684 #define LINUX_SYS_STATE_FILE "/sys/power/state"
685 #define SUSPEND_SUPPORTED 0
686 #define SUSPEND_NOT_SUPPORTED 1
687 
688 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
689                                const char *sysfile_str, Error **err)
690 {
691     Error *local_err = NULL;
692     char *pmutils_path;
693     pid_t pid;
694     int status;
695 
696     pmutils_path = g_find_program_in_path(pmutils_bin);
697 
698     pid = fork();
699     if (!pid) {
700         char buf[32]; /* hopefully big enough */
701         ssize_t ret;
702         int fd;
703 
704         setsid();
705         reopen_fd_to_null(0);
706         reopen_fd_to_null(1);
707         reopen_fd_to_null(2);
708 
709         if (pmutils_path) {
710             execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
711         }
712 
713         /*
714          * If we get here either pm-utils is not installed or execle() has
715          * failed. Let's try the manual method if the caller wants it.
716          */
717 
718         if (!sysfile_str) {
719             _exit(SUSPEND_NOT_SUPPORTED);
720         }
721 
722         fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
723         if (fd < 0) {
724             _exit(SUSPEND_NOT_SUPPORTED);
725         }
726 
727         ret = read(fd, buf, sizeof(buf)-1);
728         if (ret <= 0) {
729             _exit(SUSPEND_NOT_SUPPORTED);
730         }
731         buf[ret] = '\0';
732 
733         if (strstr(buf, sysfile_str)) {
734             _exit(SUSPEND_SUPPORTED);
735         }
736 
737         _exit(SUSPEND_NOT_SUPPORTED);
738     } else if (pid < 0) {
739         error_setg_errno(err, errno, "failed to create child process");
740         goto out;
741     }
742 
743     ga_wait_child(pid, &status, &local_err);
744     if (error_is_set(&local_err)) {
745         error_propagate(err, local_err);
746         goto out;
747     }
748 
749     if (!WIFEXITED(status)) {
750         error_setg(err, "child process has terminated abnormally");
751         goto out;
752     }
753 
754     switch (WEXITSTATUS(status)) {
755     case SUSPEND_SUPPORTED:
756         goto out;
757     case SUSPEND_NOT_SUPPORTED:
758         error_setg(err,
759                    "the requested suspend mode is not supported by the guest");
760         goto out;
761     default:
762         error_setg(err,
763                    "the helper program '%s' returned an unexpected exit status"
764                    " code (%d)", pmutils_path, WEXITSTATUS(status));
765         goto out;
766     }
767 
768 out:
769     g_free(pmutils_path);
770 }
771 
772 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
773                           Error **err)
774 {
775     Error *local_err = NULL;
776     char *pmutils_path;
777     pid_t pid;
778     int status;
779 
780     pmutils_path = g_find_program_in_path(pmutils_bin);
781 
782     pid = fork();
783     if (pid == 0) {
784         /* child */
785         int fd;
786 
787         setsid();
788         reopen_fd_to_null(0);
789         reopen_fd_to_null(1);
790         reopen_fd_to_null(2);
791 
792         if (pmutils_path) {
793             execle(pmutils_path, pmutils_bin, NULL, environ);
794         }
795 
796         /*
797          * If we get here either pm-utils is not installed or execle() has
798          * failed. Let's try the manual method if the caller wants it.
799          */
800 
801         if (!sysfile_str) {
802             _exit(EXIT_FAILURE);
803         }
804 
805         fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
806         if (fd < 0) {
807             _exit(EXIT_FAILURE);
808         }
809 
810         if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
811             _exit(EXIT_FAILURE);
812         }
813 
814         _exit(EXIT_SUCCESS);
815     } else if (pid < 0) {
816         error_setg_errno(err, errno, "failed to create child process");
817         goto out;
818     }
819 
820     ga_wait_child(pid, &status, &local_err);
821     if (error_is_set(&local_err)) {
822         error_propagate(err, local_err);
823         goto out;
824     }
825 
826     if (!WIFEXITED(status)) {
827         error_setg(err, "child process has terminated abnormally");
828         goto out;
829     }
830 
831     if (WEXITSTATUS(status)) {
832         error_setg(err, "child process has failed to suspend");
833         goto out;
834     }
835 
836 out:
837     g_free(pmutils_path);
838 }
839 
840 void qmp_guest_suspend_disk(Error **err)
841 {
842     bios_supports_mode("pm-is-supported", "--hibernate", "disk", err);
843     if (error_is_set(err)) {
844         return;
845     }
846 
847     guest_suspend("pm-hibernate", "disk", err);
848 }
849 
850 void qmp_guest_suspend_ram(Error **err)
851 {
852     bios_supports_mode("pm-is-supported", "--suspend", "mem", err);
853     if (error_is_set(err)) {
854         return;
855     }
856 
857     guest_suspend("pm-suspend", "mem", err);
858 }
859 
860 void qmp_guest_suspend_hybrid(Error **err)
861 {
862     bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err);
863     if (error_is_set(err)) {
864         return;
865     }
866 
867     guest_suspend("pm-suspend-hybrid", NULL, err);
868 }
869 
870 static GuestNetworkInterfaceList *
871 guest_find_interface(GuestNetworkInterfaceList *head,
872                      const char *name)
873 {
874     for (; head; head = head->next) {
875         if (strcmp(head->value->name, name) == 0) {
876             break;
877         }
878     }
879 
880     return head;
881 }
882 
883 /*
884  * Build information about guest interfaces
885  */
886 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
887 {
888     GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
889     struct ifaddrs *ifap, *ifa;
890 
891     if (getifaddrs(&ifap) < 0) {
892         error_setg_errno(errp, errno, "getifaddrs failed");
893         goto error;
894     }
895 
896     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
897         GuestNetworkInterfaceList *info;
898         GuestIpAddressList **address_list = NULL, *address_item = NULL;
899         char addr4[INET_ADDRSTRLEN];
900         char addr6[INET6_ADDRSTRLEN];
901         int sock;
902         struct ifreq ifr;
903         unsigned char *mac_addr;
904         void *p;
905 
906         g_debug("Processing %s interface", ifa->ifa_name);
907 
908         info = guest_find_interface(head, ifa->ifa_name);
909 
910         if (!info) {
911             info = g_malloc0(sizeof(*info));
912             info->value = g_malloc0(sizeof(*info->value));
913             info->value->name = g_strdup(ifa->ifa_name);
914 
915             if (!cur_item) {
916                 head = cur_item = info;
917             } else {
918                 cur_item->next = info;
919                 cur_item = info;
920             }
921         }
922 
923         if (!info->value->has_hardware_address &&
924             ifa->ifa_flags & SIOCGIFHWADDR) {
925             /* we haven't obtained HW address yet */
926             sock = socket(PF_INET, SOCK_STREAM, 0);
927             if (sock == -1) {
928                 error_setg_errno(errp, errno, "failed to create socket");
929                 goto error;
930             }
931 
932             memset(&ifr, 0, sizeof(ifr));
933             pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name);
934             if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
935                 error_setg_errno(errp, errno,
936                                  "failed to get MAC address of %s",
937                                  ifa->ifa_name);
938                 close(sock);
939                 goto error;
940             }
941 
942             close(sock);
943             mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
944 
945             info->value->hardware_address =
946                 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
947                                 (int) mac_addr[0], (int) mac_addr[1],
948                                 (int) mac_addr[2], (int) mac_addr[3],
949                                 (int) mac_addr[4], (int) mac_addr[5]);
950 
951             info->value->has_hardware_address = true;
952         }
953 
954         if (ifa->ifa_addr &&
955             ifa->ifa_addr->sa_family == AF_INET) {
956             /* interface with IPv4 address */
957             p = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
958             if (!inet_ntop(AF_INET, p, addr4, sizeof(addr4))) {
959                 error_setg_errno(errp, errno, "inet_ntop failed");
960                 goto error;
961             }
962 
963             address_item = g_malloc0(sizeof(*address_item));
964             address_item->value = g_malloc0(sizeof(*address_item->value));
965             address_item->value->ip_address = g_strdup(addr4);
966             address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
967 
968             if (ifa->ifa_netmask) {
969                 /* Count the number of set bits in netmask.
970                  * This is safe as '1' and '0' cannot be shuffled in netmask. */
971                 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
972                 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
973             }
974         } else if (ifa->ifa_addr &&
975                    ifa->ifa_addr->sa_family == AF_INET6) {
976             /* interface with IPv6 address */
977             p = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
978             if (!inet_ntop(AF_INET6, p, addr6, sizeof(addr6))) {
979                 error_setg_errno(errp, errno, "inet_ntop failed");
980                 goto error;
981             }
982 
983             address_item = g_malloc0(sizeof(*address_item));
984             address_item->value = g_malloc0(sizeof(*address_item->value));
985             address_item->value->ip_address = g_strdup(addr6);
986             address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
987 
988             if (ifa->ifa_netmask) {
989                 /* Count the number of set bits in netmask.
990                  * This is safe as '1' and '0' cannot be shuffled in netmask. */
991                 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
992                 address_item->value->prefix =
993                     ctpop32(((uint32_t *) p)[0]) +
994                     ctpop32(((uint32_t *) p)[1]) +
995                     ctpop32(((uint32_t *) p)[2]) +
996                     ctpop32(((uint32_t *) p)[3]);
997             }
998         }
999 
1000         if (!address_item) {
1001             continue;
1002         }
1003 
1004         address_list = &info->value->ip_addresses;
1005 
1006         while (*address_list && (*address_list)->next) {
1007             address_list = &(*address_list)->next;
1008         }
1009 
1010         if (!*address_list) {
1011             *address_list = address_item;
1012         } else {
1013             (*address_list)->next = address_item;
1014         }
1015 
1016         info->value->has_ip_addresses = true;
1017 
1018 
1019     }
1020 
1021     freeifaddrs(ifap);
1022     return head;
1023 
1024 error:
1025     freeifaddrs(ifap);
1026     qapi_free_GuestNetworkInterfaceList(head);
1027     return NULL;
1028 }
1029 
1030 #else /* defined(__linux__) */
1031 
1032 void qmp_guest_suspend_disk(Error **err)
1033 {
1034     error_set(err, QERR_UNSUPPORTED);
1035 }
1036 
1037 void qmp_guest_suspend_ram(Error **err)
1038 {
1039     error_set(err, QERR_UNSUPPORTED);
1040 }
1041 
1042 void qmp_guest_suspend_hybrid(Error **err)
1043 {
1044     error_set(err, QERR_UNSUPPORTED);
1045 }
1046 
1047 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
1048 {
1049     error_set(errp, QERR_UNSUPPORTED);
1050     return NULL;
1051 }
1052 
1053 #endif
1054 
1055 #if !defined(CONFIG_FSFREEZE)
1056 
1057 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
1058 {
1059     error_set(err, QERR_UNSUPPORTED);
1060 
1061     return 0;
1062 }
1063 
1064 int64_t qmp_guest_fsfreeze_freeze(Error **err)
1065 {
1066     error_set(err, QERR_UNSUPPORTED);
1067 
1068     return 0;
1069 }
1070 
1071 int64_t qmp_guest_fsfreeze_thaw(Error **err)
1072 {
1073     error_set(err, QERR_UNSUPPORTED);
1074 
1075     return 0;
1076 }
1077 #endif /* CONFIG_FSFREEZE */
1078 
1079 #if !defined(CONFIG_FSTRIM)
1080 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
1081 {
1082     error_set(err, QERR_UNSUPPORTED);
1083 }
1084 #endif
1085 
1086 /* register init/cleanup routines for stateful command groups */
1087 void ga_command_state_init(GAState *s, GACommandState *cs)
1088 {
1089 #if defined(CONFIG_FSFREEZE)
1090     ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
1091 #endif
1092     ga_command_state_add(cs, guest_file_init, NULL);
1093 }
1094