xref: /openbmc/qemu/qga/commands-posix.c (revision 3588185b)
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     int64_t ret;
615     Error *err = NULL;
616 
617     if (ga_is_frozen(ga_state) == GUEST_FSFREEZE_STATUS_FROZEN) {
618         ret = qmp_guest_fsfreeze_thaw(&err);
619         if (ret < 0 || err) {
620             slog("failed to clean up frozen filesystems");
621         }
622     }
623 }
624 #endif /* CONFIG_FSFREEZE */
625 
626 #if defined(CONFIG_FSTRIM)
627 /*
628  * Walk list of mounted file systems in the guest, and trim them.
629  */
630 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
631 {
632     int ret = 0;
633     FsMountList mounts;
634     struct FsMount *mount;
635     int fd;
636     Error *local_err = NULL;
637     struct fstrim_range r = {
638         .start = 0,
639         .len = -1,
640         .minlen = has_minimum ? minimum : 0,
641     };
642 
643     slog("guest-fstrim called");
644 
645     QTAILQ_INIT(&mounts);
646     build_fs_mount_list(&mounts, &local_err);
647     if (error_is_set(&local_err)) {
648         error_propagate(err, local_err);
649         return;
650     }
651 
652     QTAILQ_FOREACH(mount, &mounts, next) {
653         fd = qemu_open(mount->dirname, O_RDONLY);
654         if (fd == -1) {
655             error_setg_errno(err, errno, "failed to open %s", mount->dirname);
656             goto error;
657         }
658 
659         /* We try to cull filesytems we know won't work in advance, but other
660          * filesytems may not implement fstrim for less obvious reasons.  These
661          * will report EOPNOTSUPP; we simply ignore these errors.  Any other
662          * error means an unexpected error, so return it in those cases.  In
663          * some other cases ENOTTY will be reported (e.g. CD-ROMs).
664          */
665         ret = ioctl(fd, FITRIM, &r);
666         if (ret == -1) {
667             if (errno != ENOTTY && errno != EOPNOTSUPP) {
668                 error_setg_errno(err, errno, "failed to trim %s",
669                                  mount->dirname);
670                 close(fd);
671                 goto error;
672             }
673         }
674         close(fd);
675     }
676 
677 error:
678     free_fs_mount_list(&mounts);
679 }
680 #endif /* CONFIG_FSTRIM */
681 
682 
683 #define LINUX_SYS_STATE_FILE "/sys/power/state"
684 #define SUSPEND_SUPPORTED 0
685 #define SUSPEND_NOT_SUPPORTED 1
686 
687 static void bios_supports_mode(const char *pmutils_bin, const char *pmutils_arg,
688                                const char *sysfile_str, Error **err)
689 {
690     Error *local_err = NULL;
691     char *pmutils_path;
692     pid_t pid;
693     int status;
694 
695     pmutils_path = g_find_program_in_path(pmutils_bin);
696 
697     pid = fork();
698     if (!pid) {
699         char buf[32]; /* hopefully big enough */
700         ssize_t ret;
701         int fd;
702 
703         setsid();
704         reopen_fd_to_null(0);
705         reopen_fd_to_null(1);
706         reopen_fd_to_null(2);
707 
708         if (pmutils_path) {
709             execle(pmutils_path, pmutils_bin, pmutils_arg, NULL, environ);
710         }
711 
712         /*
713          * If we get here either pm-utils is not installed or execle() has
714          * failed. Let's try the manual method if the caller wants it.
715          */
716 
717         if (!sysfile_str) {
718             _exit(SUSPEND_NOT_SUPPORTED);
719         }
720 
721         fd = open(LINUX_SYS_STATE_FILE, O_RDONLY);
722         if (fd < 0) {
723             _exit(SUSPEND_NOT_SUPPORTED);
724         }
725 
726         ret = read(fd, buf, sizeof(buf)-1);
727         if (ret <= 0) {
728             _exit(SUSPEND_NOT_SUPPORTED);
729         }
730         buf[ret] = '\0';
731 
732         if (strstr(buf, sysfile_str)) {
733             _exit(SUSPEND_SUPPORTED);
734         }
735 
736         _exit(SUSPEND_NOT_SUPPORTED);
737     } else if (pid < 0) {
738         error_setg_errno(err, errno, "failed to create child process");
739         goto out;
740     }
741 
742     ga_wait_child(pid, &status, &local_err);
743     if (error_is_set(&local_err)) {
744         error_propagate(err, local_err);
745         goto out;
746     }
747 
748     if (!WIFEXITED(status)) {
749         error_setg(err, "child process has terminated abnormally");
750         goto out;
751     }
752 
753     switch (WEXITSTATUS(status)) {
754     case SUSPEND_SUPPORTED:
755         goto out;
756     case SUSPEND_NOT_SUPPORTED:
757         error_setg(err,
758                    "the requested suspend mode is not supported by the guest");
759         goto out;
760     default:
761         error_setg(err,
762                    "the helper program '%s' returned an unexpected exit status"
763                    " code (%d)", pmutils_path, WEXITSTATUS(status));
764         goto out;
765     }
766 
767 out:
768     g_free(pmutils_path);
769 }
770 
771 static void guest_suspend(const char *pmutils_bin, const char *sysfile_str,
772                           Error **err)
773 {
774     Error *local_err = NULL;
775     char *pmutils_path;
776     pid_t pid;
777     int status;
778 
779     pmutils_path = g_find_program_in_path(pmutils_bin);
780 
781     pid = fork();
782     if (pid == 0) {
783         /* child */
784         int fd;
785 
786         setsid();
787         reopen_fd_to_null(0);
788         reopen_fd_to_null(1);
789         reopen_fd_to_null(2);
790 
791         if (pmutils_path) {
792             execle(pmutils_path, pmutils_bin, NULL, environ);
793         }
794 
795         /*
796          * If we get here either pm-utils is not installed or execle() has
797          * failed. Let's try the manual method if the caller wants it.
798          */
799 
800         if (!sysfile_str) {
801             _exit(EXIT_FAILURE);
802         }
803 
804         fd = open(LINUX_SYS_STATE_FILE, O_WRONLY);
805         if (fd < 0) {
806             _exit(EXIT_FAILURE);
807         }
808 
809         if (write(fd, sysfile_str, strlen(sysfile_str)) < 0) {
810             _exit(EXIT_FAILURE);
811         }
812 
813         _exit(EXIT_SUCCESS);
814     } else if (pid < 0) {
815         error_setg_errno(err, errno, "failed to create child process");
816         goto out;
817     }
818 
819     ga_wait_child(pid, &status, &local_err);
820     if (error_is_set(&local_err)) {
821         error_propagate(err, local_err);
822         goto out;
823     }
824 
825     if (!WIFEXITED(status)) {
826         error_setg(err, "child process has terminated abnormally");
827         goto out;
828     }
829 
830     if (WEXITSTATUS(status)) {
831         error_setg(err, "child process has failed to suspend");
832         goto out;
833     }
834 
835 out:
836     g_free(pmutils_path);
837 }
838 
839 void qmp_guest_suspend_disk(Error **err)
840 {
841     bios_supports_mode("pm-is-supported", "--hibernate", "disk", err);
842     if (error_is_set(err)) {
843         return;
844     }
845 
846     guest_suspend("pm-hibernate", "disk", err);
847 }
848 
849 void qmp_guest_suspend_ram(Error **err)
850 {
851     bios_supports_mode("pm-is-supported", "--suspend", "mem", err);
852     if (error_is_set(err)) {
853         return;
854     }
855 
856     guest_suspend("pm-suspend", "mem", err);
857 }
858 
859 void qmp_guest_suspend_hybrid(Error **err)
860 {
861     bios_supports_mode("pm-is-supported", "--suspend-hybrid", NULL, err);
862     if (error_is_set(err)) {
863         return;
864     }
865 
866     guest_suspend("pm-suspend-hybrid", NULL, err);
867 }
868 
869 static GuestNetworkInterfaceList *
870 guest_find_interface(GuestNetworkInterfaceList *head,
871                      const char *name)
872 {
873     for (; head; head = head->next) {
874         if (strcmp(head->value->name, name) == 0) {
875             break;
876         }
877     }
878 
879     return head;
880 }
881 
882 /*
883  * Build information about guest interfaces
884  */
885 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
886 {
887     GuestNetworkInterfaceList *head = NULL, *cur_item = NULL;
888     struct ifaddrs *ifap, *ifa;
889 
890     if (getifaddrs(&ifap) < 0) {
891         error_setg_errno(errp, errno, "getifaddrs failed");
892         goto error;
893     }
894 
895     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
896         GuestNetworkInterfaceList *info;
897         GuestIpAddressList **address_list = NULL, *address_item = NULL;
898         char addr4[INET_ADDRSTRLEN];
899         char addr6[INET6_ADDRSTRLEN];
900         int sock;
901         struct ifreq ifr;
902         unsigned char *mac_addr;
903         void *p;
904 
905         g_debug("Processing %s interface", ifa->ifa_name);
906 
907         info = guest_find_interface(head, ifa->ifa_name);
908 
909         if (!info) {
910             info = g_malloc0(sizeof(*info));
911             info->value = g_malloc0(sizeof(*info->value));
912             info->value->name = g_strdup(ifa->ifa_name);
913 
914             if (!cur_item) {
915                 head = cur_item = info;
916             } else {
917                 cur_item->next = info;
918                 cur_item = info;
919             }
920         }
921 
922         if (!info->value->has_hardware_address &&
923             ifa->ifa_flags & SIOCGIFHWADDR) {
924             /* we haven't obtained HW address yet */
925             sock = socket(PF_INET, SOCK_STREAM, 0);
926             if (sock == -1) {
927                 error_setg_errno(errp, errno, "failed to create socket");
928                 goto error;
929             }
930 
931             memset(&ifr, 0, sizeof(ifr));
932             pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->value->name);
933             if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
934                 error_setg_errno(errp, errno,
935                                  "failed to get MAC address of %s",
936                                  ifa->ifa_name);
937                 goto error;
938             }
939 
940             mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
941 
942             info->value->hardware_address =
943                 g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
944                                 (int) mac_addr[0], (int) mac_addr[1],
945                                 (int) mac_addr[2], (int) mac_addr[3],
946                                 (int) mac_addr[4], (int) mac_addr[5]);
947 
948             info->value->has_hardware_address = true;
949             close(sock);
950         }
951 
952         if (ifa->ifa_addr &&
953             ifa->ifa_addr->sa_family == AF_INET) {
954             /* interface with IPv4 address */
955             address_item = g_malloc0(sizeof(*address_item));
956             address_item->value = g_malloc0(sizeof(*address_item->value));
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->value->ip_address = g_strdup(addr4);
964             address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV4;
965 
966             if (ifa->ifa_netmask) {
967                 /* Count the number of set bits in netmask.
968                  * This is safe as '1' and '0' cannot be shuffled in netmask. */
969                 p = &((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
970                 address_item->value->prefix = ctpop32(((uint32_t *) p)[0]);
971             }
972         } else if (ifa->ifa_addr &&
973                    ifa->ifa_addr->sa_family == AF_INET6) {
974             /* interface with IPv6 address */
975             address_item = g_malloc0(sizeof(*address_item));
976             address_item->value = g_malloc0(sizeof(*address_item->value));
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->value->ip_address = g_strdup(addr6);
984             address_item->value->ip_address_type = GUEST_IP_ADDRESS_TYPE_IPV6;
985 
986             if (ifa->ifa_netmask) {
987                 /* Count the number of set bits in netmask.
988                  * This is safe as '1' and '0' cannot be shuffled in netmask. */
989                 p = &((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
990                 address_item->value->prefix =
991                     ctpop32(((uint32_t *) p)[0]) +
992                     ctpop32(((uint32_t *) p)[1]) +
993                     ctpop32(((uint32_t *) p)[2]) +
994                     ctpop32(((uint32_t *) p)[3]);
995             }
996         }
997 
998         if (!address_item) {
999             continue;
1000         }
1001 
1002         address_list = &info->value->ip_addresses;
1003 
1004         while (*address_list && (*address_list)->next) {
1005             address_list = &(*address_list)->next;
1006         }
1007 
1008         if (!*address_list) {
1009             *address_list = address_item;
1010         } else {
1011             (*address_list)->next = address_item;
1012         }
1013 
1014         info->value->has_ip_addresses = true;
1015 
1016 
1017     }
1018 
1019     freeifaddrs(ifap);
1020     return head;
1021 
1022 error:
1023     freeifaddrs(ifap);
1024     qapi_free_GuestNetworkInterfaceList(head);
1025     return NULL;
1026 }
1027 
1028 #else /* defined(__linux__) */
1029 
1030 void qmp_guest_suspend_disk(Error **err)
1031 {
1032     error_set(err, QERR_UNSUPPORTED);
1033 }
1034 
1035 void qmp_guest_suspend_ram(Error **err)
1036 {
1037     error_set(err, QERR_UNSUPPORTED);
1038 }
1039 
1040 void qmp_guest_suspend_hybrid(Error **err)
1041 {
1042     error_set(err, QERR_UNSUPPORTED);
1043 }
1044 
1045 GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
1046 {
1047     error_set(errp, QERR_UNSUPPORTED);
1048     return NULL;
1049 }
1050 
1051 #endif
1052 
1053 #if !defined(CONFIG_FSFREEZE)
1054 
1055 GuestFsfreezeStatus qmp_guest_fsfreeze_status(Error **err)
1056 {
1057     error_set(err, QERR_UNSUPPORTED);
1058 
1059     return 0;
1060 }
1061 
1062 int64_t qmp_guest_fsfreeze_freeze(Error **err)
1063 {
1064     error_set(err, QERR_UNSUPPORTED);
1065 
1066     return 0;
1067 }
1068 
1069 int64_t qmp_guest_fsfreeze_thaw(Error **err)
1070 {
1071     error_set(err, QERR_UNSUPPORTED);
1072 
1073     return 0;
1074 }
1075 #endif /* CONFIG_FSFREEZE */
1076 
1077 #if !defined(CONFIG_FSTRIM)
1078 void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err)
1079 {
1080     error_set(err, QERR_UNSUPPORTED);
1081 }
1082 #endif
1083 
1084 /* register init/cleanup routines for stateful command groups */
1085 void ga_command_state_init(GAState *s, GACommandState *cs)
1086 {
1087 #if defined(CONFIG_FSFREEZE)
1088     ga_command_state_add(cs, NULL, guest_fsfreeze_cleanup);
1089 #endif
1090     ga_command_state_add(cs, guest_file_init, NULL);
1091 }
1092